I am trying to make a ball bounce within a box correctly, specifically handling corners at specific angles and handling a corner head on. I have a problem, because my ball keeps coming out of the box. I have this function that tells if my ball is out of the box and it handles corners and walls. The code is this:
if ((self._x > self._Grid.getWidth()) or (self._x < 0)):
print("RandomNode:outside paramaters: x! self._x = %s , self._velx = %s" % (self._x , self._velx))
if ((self._y > self._Grid.getLength()) or (self._y < 0)):
print("RandomNode:outside paramaters: y!")
if ((self._velx + self._x) > self._Grid.getWidth()):
diff = self._Grid.getWidth()-self._x
self._velx *= -1
if (diff == 0):
self._x -= self._velx
else:
self._x+= diff
tampered = True
#print("eqn1: self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
if (self._velx + self._x < 0):
diff = self._x
self._velx *= -1
if (diff == 0):
self._x += self._velx
else:
self._x-= diff
tampered = True
#print("eqn2: self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
if ((self._vely + self._y) > self._Grid.getLength()):
diff = self._Grid.getLength()-self._y
self._vely *= -1
if (diff == 0):
self._y -= self._vely
if (tampered == True):
if ((self._velx * -1 == self._vely) or (self._velx == self._vely)):
self._x += self._velx
self._y += self._vely
#print("eqn31:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._x += (self._velx - diff)
self._y += self._vely
#print("eqn32:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
tampered = True
#print("eqn33:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._y+= diff
if (tampered == True):
if ((self._velx * -1 == self._vely) or (self._velx == self._vely)):
self._x += self._velx
self._y += self._vely
#print("eqn31:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._x += (self._velx - diff)
self._y += self._vely
#print("eqn32:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
tampered = True
#print("eqn33:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
if (self._vely + self._y < 0):
diff = self._y
self._vely *= -1
if (diff == 0):
self._y += self._vely
if (tampered == True):
if ((self._velx * -1 == self._vely) or (self._velx == self._vely)):
self._x += self._velx
self._y += self._vely
#print("eqn41:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._x += (self._velx + diff)
self._y += self._vely
#print("eqn42:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
tampered = True
#print("eqn43:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._y-= diff
if (tampered == True):
if ((self._velx * -1 == self._vely) or (self._velx == self._vely)):
self._x += self._velx
self._y += self._vely
#print("eqn41:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
self._x += (self._velx + diff)
self._y += self._vely
#print("eqn42:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
else:
tampered = True
#print("eqn43:self._x = %s , self._y = %s , self._velx= %s, self._vely= %s" % (self._x, self._y, self._velx, self._vely))
return tampered
I don't know why it is not working. x and y are obviously its coordinates. Velx and Vely are its x and y velocities. Tampered is a Boolean that prevents the ball from moving normally and only being moved within check.
Here is my question. What is wrong with this code? OR....is there a template written in python somewhere on the net or where ever, or a code that you have used that does the exact thing I am trying to handle and do? Please revise the code at will, just let me know. Any links to this already solved would be great as well. Thanks.
Rewrite this code. It is way too complex for the simple problem you're trying to solve.
First, a 2D motion of a ball is just 2 1D problems. You can completely separate X and Y. For example, hitting a corner is completely equivalent of hitting a wall in X axis + hitting a wall in Y axis. Hitting a wall in X just reverses the X velocity (and possibly loses some energy if you want to simulate that). Hitting a wall in Y reverses Y velocity.
Second, since the handling of X and Y is so similar, extract a method out of it
def handle_axis_movement(location, velocity):
"returns updated location and velocity"
...
self.x, self.vel_x = handle_axis_movement(self.x, self.vel_x)
self.y, self.vel_y = handle_axis_movement(self.y, self.vel_y)
This will cut the amount of code (and bugs) in half.
Third, you don't have to treat diff==0 and diff<0 seperately. Both cases mean the ball hit a wall, and should reverse its velocity. Then you should correct the location to account for the fact that it couldn't have passed through the wall.
location += velocity
if location > max_bound:
location = max_bound - (location - max_bound)
velocity *= -1
if location < min_bound:
location = min_bound - (location - min_bound)
velocity *= -1
You shouldn't be reinventing this wheel when pymunk does it for you so well. ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With