Search code examples
pythongraphics2dcollision-detection

Python 2d Ball Collision


Here is what I have mustered up:

from graphics import *
from random import *
from math import *

class Ball(Circle): def init(self, win_width, win_high, point, r, vel1, vel2): Circle.init(self, point, r)

    self.width = win_width
    self.high = win_high

    self.vecti1 = vel1
    self.vecti2 = vel2


def collide_wall(self):
    bound1 = self.getP1()
    bound2 = self.getP2()

    if (bound2.y >= self.width):            
        self.vecti2 = -self.vecti2
        self.move(0, -1)
    if (bound2.x >= self.high):
        self.vecti1 = -self.vecti1
        self.move(-1, 0)
    if (bound1.x <= 0):
        self.vecti1 = -self.vecti1
        self.move(1, 0)
    if (bound2.y <= 0):            
        self.vecti2 = -self.vecti2
        self.move(0, 1)

def ball_collision(self, cir2):
    radius = self.getRadius()
    radius2 = cir2.getRadius()

    bound1 = self.getP1()      
    bound3 = cir2.getP1()


    center1 = Point(radius + bound1.x,radius + bound1.y)
    center2 = Point(radius2 + bound3.x,radius2 + bound3.y)

    centerx = center2.getX() - center1.getX()
    centery = center2.getY() - center1.getY()

    distance = sqrt((centerx * centerx) + (centery * centery))

    if (distance <= (radius + radius2)):
        xdistance = abs(center1.getX() - center2.getX())
        ydistance = abs(center1.getY() - center2.getY())

        if (xdistance <= ydistance):
            if ((self.vecti2 > 0 & bound1.y < bound3.y) | (self.vecti2 < 0 & bound1.y > bound3.y)):
                self.vecti2 = -self.vecti2


            if ((cir2.vecti2 > 0 & bound3.y < bound1.y) | (cir2.vecti2 < 0 & bound3.y > bound1.y)):
                cir2.vecti2 = -cir2.vecti2



        elif (xdistance > ydistance):
            if ((self.vecti1 > 0 & bound1.x < bound3.x) | (self.vecti1 < 0 & bound1.x > bound3.x)):
                self.vecti1 = -self.vecti1

            if ((cir2.vecti1 > 0 & bound3.x < bound1.x) | (cir2.vecti1 < 0 & bound3.x > bound1.x)):
                cir2.vecti1 = -cir2.vecti1

def main(): win = GraphWin("Ball screensaver", 700,700)

velo1 = 4
velo2 = 3
velo3 = -4
velo4 = -3

cir1 = Ball(win.getWidth(),win.getHeight(),Point(50,50), 20, velo1, velo2)

cir1.setOutline("red")
cir1.setFill("red")
cir1.draw(win)

cir2 = Ball(win.getWidth(),win.getHeight(),Point(200,200), 20, velo3, velo4)
cir2.setOutline("blue")
cir2.setFill("blue")
cir2.draw(win)


while(True):
    cir1.move(cir1.vecti1, cir1.vecti2)
    cir2.move(cir2.vecti1, cir2.vecti2)
    time.sleep(.010)
    cir1.collide_wall()
    cir2.collide_wall()

    cir1.ball_collision(cir2)
    #cir2.ball_collision(cir1)

main()

Ok so here is the problem. This Math is not working correctly at all. Sometimes it works perfectly sometimes one ball overpowers the other ball or they don't react like a ball collision should. I am racking my brain trying to figure out what the problem is but I feel I am too close to the project at the moment to see it. Any help would be appreciated.


Solution

  • Fix your "if" statements to be legal and straightforward. I think that you might be trying to say something like what's below. It's hard to tell, since you haven't documented your code.

    if cir2.vecti2 > 0 and bound3.y > bound1.y:
        cir2.vecti2 = -cir2.vecti2
    

    Note that bound3 has no value. You will find other problems, I'm sure.

    I suggest that you back up and try incremental coding. First, try getting one ball to move around legally, bouncing off walls. Put in tracing print statements for the position, and label them so you know where you are in your code.

    Once you have that working, then add the second ball. Continue with the print statements, commenting out the ones you don't think you need any more. Don't delete them until you have the whole program working.

    Does this get you going?