Thursday, June 19, 2014

30. Widget Collisions

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

3 comments:

  1. Python:

    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.

    https://www.emexotechnologies.com/online-courses/python-training-in-electronic-city/

    ReplyDelete
  2. 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.

    Python Training in electronic city

    ReplyDelete