This application is similar to the last. Now the walls become widgets. Also, if ball1 and ball2 collide, we set their velocities equal and opposite, at the angle of collision.
These are the imports. The balls and walls will be based on the Widget class, as will be the root class. The ListProperty will be used to hold the ball's velocity. We will use the Vector class to write the math equations. The Clock will set the framerates for the two balls. We require the python program run with a Kivy version of 1.8.0 or higher.
Now the velocity becomes part of of the Ball class. The initial velocity for the two balls will be set in the kv file. There are four wall Widgets in the kv file. There will be 6 attributes, four representing the walls, and 2 representing the balls.
The initial position of the balls is set in the constructor.
The collide_widget command operates on widgets and checks if there is a collision.
There will be a single update function, and this will update the balls. First we see if the ball1 or ball2 has hit a wall. A for loop checks for the two balls, and negates, either the x-term, or y-term, of the velocity, if a ball-wall, collision is detected.
When two balls collide, we will have the situation shown. We can find the collision vector, this being the vector, from ball2 to ball1. We will set the ball1 direction same as the collision vector, and ball2 direction as opposite of that. Their will be magnitude calculation so the balls conserve energy and momentum.
These calculations are shown here. The term 5 indicates the magnitude of the initial velocity vector. For ellastic collisions of balls off a wall, or between balls, the direction changes, not the net magnitude, which is fixed at 5, in this case.
Finally, we update the ball1 and ball2 positions. It should be noted that this velocity is the velocity per frame.
The app class is created with a title. The clock is set at 60 Hz to call update().
# ex30.py from kivy.uix.widget import Widget from kivy.app import App from kivy.properties import ListProperty from kivy.vector import Vector as Vec from kivy.clock import Clock import kivy kivy.require('1.8.0') class Ball(Widget): vel = ListProperty() class Wall(Widget): pass class Ex30(Widget): def __init__(self, **kwargs): super(Ex30, self).__init__(**kwargs) self.ball1.pos = self.width/2, self.height/2 self.ball2.pos = self.width/3, self.height/3 def update(self,dt): for ball in [self.ball1,self.ball2]: if ball.collide_widget(self.wall_left): ball.vel[0] *= -1 elif ball.collide_widget(self.wall_right): ball.vel[0] *= -1 if ball.collide_widget(self.wall_top): ball.vel[1] *= -1 elif ball.collide_widget(self.wall_down): ball.vel[1] *= -1 if self.ball1.collide_widget(self.ball2): col_vector=Vec(self.ball1.pos)-Vec(self.ball2.pos) col_vector_mag=col_vector.length() self.ball1.vel = 5.0/col_vector_mag*col_vector self.ball2.vel = -5.0/col_vector_mag*col_vector self.ball1.pos = Vec(self.ball1.vel) + Vec(self.ball1.pos) self.ball2.pos = Vec(self.ball2.vel) + Vec(self.ball2.pos) class Ex30App(App): def build(self): self.title = "Two Bouncing Balls with Widget Collisions" ex30 = Ex30() Clock.schedule_interval(ex30.update, 1.0/60) return ex30 if __name__=='__main__': Ex30App().run()
In the kv file, we first set 5 constants which will define the bounding box.
The wall will have a bluish color.
The balls will be 50 by 50 pixels in size. The canvas.after is a circle with the indicated image we downloaded.
For the root, the Widget size is set and then we define attributes for ball1 and ball2, and 4 for the horizontal and the vertical walls.
The background of the root is green.
The vertical walls are defined. Both have the same size, but their positions indicate if they form the left of the box or right of the box.
The horizontal walls have the same size but they have different y-coordinates.
Finally, we have the two balls. Note we set the initial velocity here, as well as the color to apply to the Ellipse.
# ex30.kv #:kivy 1.8.0 #:set Top 500 #:set Down 100 #:set Left 200 #:set Right 600 #:set Width 10 <Wall>: canvas: Color: rgb: 0,.35,1 Rectangle: size: self.size pos: self.pos <Ball>: size: 50,50 canvas.after: Ellipse: pos: self.pos size: self.size source: 'kivy.png' <Ex30>: size: 800, 600 ball1: ball_id1 ball2: ball_id2 wall_left: wallleft_id wall_right: wallright_id wall_top: walltop_id wall_down: walldown_id canvas: Color: rgb: 0,1,0 Rectangle: size: root.width,root.height pos: 0,0 Wall: id: wallleft_id size: Width,Top-Down pos: Left,Down Wall: id: wallright_id size: Width,Top-Down pos: Right-Width,Down Wall: id: walltop_id size: Right-Left,Width pos: Left,Top Wall: id: walldown_id size: Right-Left,Width pos: Left,Down Ball: id: ball_id1 vel: 3,4 canvas.before: Color: rgb: .75, 0, 0 Ball: id: ball_id2 vel: 4,3 canvas.before: Color: rgb: 1, 0, 1
Demo of App on Youtube
Python:
ReplyDeleteGood Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.
https://www.emexotechnologies.com/online-courses/python-training-in-electronic-city/
Good Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.
ReplyDeletePython Training in electronic city
nice information for beginners.thank you.
ReplyDeletejavacodegeeks
welookups python