Python developed the ball completely elastic collision game code
- 2020-04-02 13:04:00
- OfStack
Complete this ball's fully elastic collision game inspired by:
(link: http://runjs.cn/detail/g9jukpct)
Here's a ball full elastic collision game I spent a week off work writing:
Game initialization status:
< img Alt = "" border = 0 SRC =" / / img.jbzj.com/file_images/article/201310/201310151506543.png "width = 505 height = 584 >
The bottom cursor and changes the speed of the ball
< img Alt = "" border = 0 SRC =" / / img.jbzj.com/file_images/article/201310/201310151506544.png "width = 505 height = 584 >
Source code:
#python tkinter
#python version 3.3.2
from tkinter import *
'''
judge
Two balls
{
Circle: A(x1,y1) Radius: r X Shaft speed: Vax Y Shaft speed: Vay
Circle: B(x2,y2) Radius: R X Shaft speed: Vbx Y Shaft speed: Vby
}
The conditions for collision are:
1. The distance between the center of the two balls should not be greater than the sum of their radii (r+R) , that is:
{
(x2 - x1)^2 + (y2 - y1)^2 <= (r + R)^2
}
2. After the ball collision, the two balls exchange several degrees, that is:
{
tempVax = Vax
tempVay = Vay
Vax = Vbx
Vay = Vby
Vbx = tempVax
Vby = tempVay
Or:
Vax = Vax + Vbx
Vbx = Vax - Vbx
Vax = Vax - Vbx
Vay = Vay + Vby
Vby = Vay - Vby
Vay = Vay - Vby
}
Rules of the game:
Five balls move around the canvas, and they collide with each other, and of course the balls collide with the top, the bottom, the left, the right
After a collision, the ball changes direction and returns
The bottom cursor is used to adjust the speed of the ball [-100, 100]
Defects or BUG :
1. When the cursor data is modified to change the speed of the ball, the distance of the ball cannot be timely updated
Causing the ball to escape from the canvas
2. The ball may sometimes escape from the canvas as it moves
Conclusion:
It took a week off work to complete the game. In the process, I not only went back to study high school mathematics,
I forgot a lot of things about physics, but I soon came back to it.
Many games are math problems.
There are also flaws in the game BUG I hope like-minded people can improve together.
'''
__author__ = {'author' : 'Hongten',
'Email' : 'hongtenzone@foxmail.com',
'Blog' : 'http://www.cnblogs.com/hongten/',
'Created' : '2013-09-28',
'Version' : '1.0'}
class Pong(Frame):
def createWidgets(self):
## The canvas
self.draw = Canvas(self, width="5i", height="5i", bg='white')
## The cursor ( Control ball movement speed, range: [-100, 100])
self.speed = Scale(self, orient=HORIZONTAL, label="ball speed",
from_=-100, to=100)
self.speed.pack(side=BOTTOM, fill=X)
# The extent to which the ball hits the wall
self.scaling_right = 4.8
self.scaling_left = 0.2
# Small ball diameter
self.ball_d = 0.4
# The cursor degree
self.scale_value = self.speed.get()
# Put the shrinkage
self.scaling = 100.0
# Store the array of spheres
self.balls = []
# For small ball x Coordinate arrays
self.ball_x = []
# For small ball y Coordinate arrays
self.ball_y = []
# For small ball x Axial velocity array
self.ball_v_x = []
# For small ball y Axial velocity array
self.ball_v_y = []
# Five balls
self.ball = self.draw.create_oval("0.10i", "0.10i", "0.50i", "0.50i",
fill="red")
self.second_ball = self.draw.create_oval("0.70i", "0.70i", "1.10i", "1.10i",
fill='black')
self.three_ball = self.draw.create_oval("1.30i", "1.30i", "1.70i", "1.70i",
fill='brown')
self.four_ball = self.draw.create_oval("2.0i", "2.0i", "2.40i", "2.40i",
fill='green')
self.five_ball = self.draw.create_oval("3.0i", "3.0i", "3.40i", "3.40i",
fill='gray')
# Put the five balls into the array
self.balls.append(self.ball)
self.balls.append(self.second_ball)
self.balls.append(self.three_ball)
self.balls.append(self.four_ball)
self.balls.append(self.five_ball)
# The first ball, namely self.ball Center of a circle (self.x, self.y), I've scaled it up here , In order to
# More fluid as the ball moves
self.x = 0.3
self.y = 0.3
# The velocity direction of the first ball
self.velocity_x = -0.2
self.velocity_y = 0.5
self.second_ball_x = 0.9
self.second_ball_y = 0.9
self.second_ball_v_x = 0.4
self.second_ball_v_y = -0.5
self.three_ball_x = 1.5
self.three_ball_y = 1.5
self.three_ball_v_x = -0.3
self.three_ball_v_y = -0.5
self.four_ball_x = 2.2
self.four_ball_y = 2.2
self.four_ball_v_x = 0.1
self.four_ball_v_y = -0.5
self.five_ball_x = 3.2
self.five_ball_y = 3.2
self.five_ball_v_x = 0.3
self.five_ball_v_y = 0.5
# Update the coordinates of the ball
self.update_ball_x_y()
self.draw.pack(side=LEFT)
def update_ball_x_y(self, *args):
''' Update the coordinates of the balls, that is, store the center coordinate information and speed information of each ball into the array.
Easy to use later in the loop traversal. '''
# The first little ball information
self.ball_x.append(self.x)
self.ball_y.append(self.y)
self.ball_v_x.append(self.velocity_x)
self.ball_v_y.append(self.velocity_y)
self.ball_x.append(self.second_ball_x)
self.ball_y.append(self.second_ball_y)
self.ball_v_x.append(self.second_ball_v_x)
self.ball_v_y.append(self.second_ball_v_y)
self.ball_x.append(self.three_ball_x)
self.ball_y.append(self.three_ball_y)
self.ball_v_x.append(self.three_ball_v_x)
self.ball_v_y.append(self.three_ball_v_y)
self.ball_x.append(self.four_ball_x)
self.ball_y.append(self.four_ball_y)
self.ball_v_x.append(self.four_ball_v_x)
self.ball_v_y.append(self.four_ball_v_y)
self.ball_x.append(self.five_ball_x)
self.ball_y.append(self.five_ball_y)
self.ball_v_x.append(self.five_ball_v_x)
self.ball_v_y.append(self.five_ball_v_y)
def update_ball_velocity(self, index, *args):
''' Update the speed information of each ball, that is, the speed information of the ball colliding to the surrounding and other balls '''
# Swim values
self.scale_value = self.speed.get()
# Collision wall
if (self.ball_x[index] > self.scaling_right) or (self.ball_x[index] < self.scaling_left):
self.ball_v_x[index] = -1.0 * self.ball_v_x[index]
if (self.ball_y[index] > self.scaling_right) or (self.ball_y[index] < self.scaling_left):
self.ball_v_y[index] = -1.0 * self.ball_v_y[index]
'''
#TEST:
for n in range(len(self.balls)):
#print((self.ball_x[index] - self.ball_x[n])**2)
#print(round((self.ball_x[index] - self.ball_x[n])**2 + (self.ball_y[index] - self.ball_y[n])**2, 2))
print(round((self.ball_x[index] - self.ball_x[n])**2 + (self.ball_y[index] - self.ball_y[n])**2, 2) <= round(self.ball_d**2, 2))
'''
for n in range(len(self.balls)):
# Ball collision conditions, namely: (x2 - x1)^2 + (y2 - y1)^2 <= (r + R)^2
if (round((self.ball_x[index] - self.ball_x[n])**2 + (self.ball_y[index] - self.ball_y[n])**2, 2) <= round(self.ball_d**2, 2)):
# The two balls exchange velocities
temp_vx = self.ball_v_x[index]
temp_vy = self.ball_v_y[index]
self.ball_v_x[index] = self.ball_v_x[n]
self.ball_v_y[index] = self.ball_v_y[n]
self.ball_v_x[n] = temp_vx
self.ball_v_y[n] = temp_vy
#print(self.ball_v_x, self.ball_v_y)
'''
#WRONG:
for n in range(len(self.balls)):
if (((self.ball_x[index] - self.ball_x[n])**2 + (self.ball_y[index] - self.ball_y[n])**2) <= self.ball_d**2):
# The two balls exchange velocities
self.ball_v_x[index] = self.ball_v_x[index] + self.ball_v_x[n]
self.ball_v_x[n] = self.ball_v_x[0] - self.ball_v_x[n]
self.ball_v_x[index] = self.ball_v_x[index] - self.ball_v_x[n]
self.ball_v_y[index] = self.ball_v_y[index] + self.ball_v_y[n]
self.ball_v_y[n] = self.ball_v_y[index] - self.ball_v_y[n]
self.ball_v_y[index] = self.ball_v_y[index] - self.ball_v_y[n]
print(self.ball_v_x, self.ball_v_y)
'''
def get_ball_deltax(self, index, *args):
''' For small ball X The axis moves the distance and updates the center of the ball X Coordinates, return X The distance the axis needs to travel '''
deltax = (self.ball_v_x[index] * self.scale_value / self.scaling)
self.ball_x[index] = self.ball_x[index] + deltax
return deltax
def get_ball_deltay(self, index, *args):
''' For small ball Y The axis moves the distance and updates the center of the ball Y Coordinates, return Y The distance the axis needs to travel '''
deltay = (self.ball_v_y[index] * self.scale_value / self.scaling)
self.ball_y[index] = self.ball_y[index] + deltay
return deltay
def moveBall(self, *args):
''' Move the first ball, numbered: 0, This is according to the array: self.balls Sure. '''
self.update_ball_velocity(0)
deltax = self.get_ball_deltax(0)
deltay = self.get_ball_deltay(0)
# A ball moving
self.draw.move(self.ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.moveBall)
def move_second_ball(self, *args):
self.update_ball_velocity(1)
deltax = self.get_ball_deltax(1)
deltay = self.get_ball_deltay(1)
self.draw.move(self.second_ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.move_second_ball)
def move_three_ball(self, *args):
self.update_ball_velocity(2)
deltax = self.get_ball_deltax(2)
deltay = self.get_ball_deltay(2)
self.draw.move(self.three_ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.move_three_ball)
def move_four_ball(self, *args):
self.update_ball_velocity(3)
deltax = self.get_ball_deltax(3)
deltay = self.get_ball_deltay(3)
self.draw.move(self.four_ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.move_four_ball)
def move_five_ball(self, *args):
self.update_ball_velocity(4)
deltax = self.get_ball_deltax(4)
deltay = self.get_ball_deltay(4)
self.draw.move(self.five_ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.move_five_ball)
def __init__(self, master=None):
''' Initialization function '''
Frame.__init__(self, master)
Pack.config(self)
self.createWidgets()
self.after(10, self.moveBall)
self.after(10, self.move_three_ball)
self.after(10, self.move_four_ball)
self.after(10, self.move_five_ball)
self.after(10, self.move_second_ball)
game = Pong()
game.mainloop()
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Second version version 1.1: Edit by Hongten 2013-09-28 17:40
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Modification record:
Adjust the canvas size
2. The radius of the ball, the initial velocity of the ball and the coordinates of the center of the ball were adjusted
3. The scope of the cursor is modified to: [-200, 200]
These modifications are mainly for the above defects.
Advantages:
1. The movement of the ball is more intuitive
2. The movement speed of the ball is reduced, but the movement speed of the ball can be modified according to the cursor
3. The interface is more friendly than before
Operation effect:
< img Alt = "" border = 0 SRC =" / / img.jbzj.com/file_images/article/201310/201310151506545.png "width = 649 height = 420 >
#python tkinter
#python version 3.3.2
from tkinter import *
'''
judge
Two balls
{
Circle: A(x1,y1) Radius: r X Shaft speed: Vax Y Shaft speed: Vay
Circle: B(x2,y2) Radius: R X Shaft speed: Vbx Y Shaft speed: Vby
}
The conditions for collision are:
1. The distance between the center of the two balls should not be greater than the sum of their radii (r+R) , that is:
{
(x2 - x1)^2 + (y2 - y1)^2 <= (r + R)^2
}
2. After the ball collision, the two balls exchange several degrees, that is:
{
tempVax = Vax
tempVay = Vay
Vax = Vbx
Vay = Vby
Vbx = tempVax
Vby = tempVay
Or:
Vax = Vax + Vbx
Vbx = Vax - Vbx
Vax = Vax - Vbx
Vay = Vay + Vby
Vby = Vay - Vby
Vay = Vay - Vby
}
Rules of the game:
Five balls move around the canvas, and they collide with each other, and of course the balls collide with the top, the bottom, the left, the right
After a collision, the ball changes direction and returns
The bottom cursor is used to adjust the speed of the ball [-100, 100]
Defects or BUG :
1. When the cursor data is modified to change the speed of the ball, the distance of the ball cannot be timely updated
Causing the ball to escape from the canvas
2. The ball may sometimes escape from the canvas as it moves
Conclusion:
It took a week off work to complete the game. In the process, I not only went back to study high school mathematics,
I forgot a lot of things about physics, but I soon came back to it.
Many games are math problems.
There are also flaws in the game BUG I hope like-minded people can improve together.
Modification record:
1. Resize the canvas
2. The radius of the ball was adjusted , And the initial velocity of the ball, the coordinates of the center of the ball
3. The scope of the cursor is changed to: [-200, 200]
These modifications are mainly for the above defects.
Advantages:
1. The movement of the ball is more intuitive
2. The ball moves slower, but you can modify the ball's speed based on the cursor
3. The interface is much friendlier than before
'''
__author__ = {'author' : 'Hongten',
'Email' : 'hongtenzone@foxmail.com',
'Blog' : 'http://www.cnblogs.com/hongten/',
'Created' : '2013-09-28',
'Version' : '1.1'}
class Pong(Frame):
def createWidgets(self):
# Put the shrinkage
self.scaling = 100.0
# Proportion of the canvas
self.canvas_width = 10
self.canvas_height = 5.6
## The canvas
self.draw = Canvas(self, width=(self.canvas_width * self.scaling),
height=(self.canvas_height * self.scaling),
bg='white')
## The cursor ( Control ball movement speed, range: [-100, 100])
self.speed = Scale(self, orient=HORIZONTAL, label="ball speed",
from_=-200, to=200)
self.speed.pack(side=BOTTOM, fill=X)
# Small ball diameter
self.ball_d = 1.0
# The extent to which the ball hits the wall
self.scaling_left = round(self.ball_d / 2, 1)
self.scaling_right = self.canvas_width - self.scaling_left
self.scaling_bottom = self.canvas_height - self.scaling_left
self.scaling_top = self.scaling_left
# The cursor degree
self.scale_value = self.speed.get() * 0.1
# Store the array of spheres
self.balls = []
# For small ball x Coordinate arrays
self.ball_x = []
# For small ball y Coordinate arrays
self.ball_y = []
# For small ball x Axial velocity array
self.ball_v_x = []
# For small ball y Axial velocity array
self.ball_v_y = []
# Five balls
self.ball = self.draw.create_oval("0.60i", "0.60i", "1.60i", "1.60i",
fill="red")
self.second_ball = self.draw.create_oval("2.0i", "2.0i", "3.0i", "3.0i",
fill='black')
self.three_ball = self.draw.create_oval("4.0i", "4.0i", "5.0i", "5.0i",
fill='brown')
self.four_ball = self.draw.create_oval("6.0i", "2.0i", "7.0i", "3.0i",
fill='green')
self.five_ball = self.draw.create_oval("8.0i", "3.0i", "9.0i", "4.0i",
fill='gray')
# Put the five balls into the array
self.balls.append(self.ball)
self.balls.append(self.second_ball)
self.balls.append(self.three_ball)
self.balls.append(self.four_ball)
self.balls.append(self.five_ball)
# The first ball, namely self.ball Center of a circle (self.x, self.y), I've scaled it up here , In order to
# More fluid as the ball moves
self.x = 1.1
self.y = 1.1
# The velocity direction of the first ball
self.velocity_x = -0.2
self.velocity_y = 0.1
self.second_ball_x = 2.5
self.second_ball_y = 2.5
self.second_ball_v_x = 0.1
self.second_ball_v_y = -0.2
self.three_ball_x = 4.5
self.three_ball_y = 4.5
self.three_ball_v_x = -0.1
self.three_ball_v_y = -0.2
self.four_ball_x = 6.5
self.four_ball_y = 2.5
self.four_ball_v_x = 0.1
self.four_ball_v_y = -0.2
self.five_ball_x = 8.5
self.five_ball_y = 3.5
self.five_ball_v_x = 0.1
self.five_ball_v_y = 0.2
# Update the coordinates of the ball
self.update_ball_x_y()
self.draw.pack(side=LEFT)
def update_ball_x_y(self, *args):
''' Update the coordinates of the balls, that is, store the center coordinate information and speed information of each ball into the array.
Easy to use later in the loop traversal. '''
# The first little ball information
self.ball_x.append(self.x)
self.ball_y.append(self.y)
self.ball_v_x.append(self.velocity_x)
self.ball_v_y.append(self.velocity_y)
self.ball_x.append(self.second_ball_x)
self.ball_y.append(self.second_ball_y)
self.ball_v_x.append(self.second_ball_v_x)
self.ball_v_y.append(self.second_ball_v_y)
self.ball_x.append(self.three_ball_x)
self.ball_y.append(self.three_ball_y)
self.ball_v_x.append(self.three_ball_v_x)
self.ball_v_y.append(self.three_ball_v_y)
self.ball_x.append(self.four_ball_x)
self.ball_y.append(self.four_ball_y)
self.ball_v_x.append(self.four_ball_v_x)
self.ball_v_y.append(self.four_ball_v_y)
self.ball_x.append(self.five_ball_x)
self.ball_y.append(self.five_ball_y)
self.ball_v_x.append(self.five_ball_v_x)
self.ball_v_y.append(self.five_ball_v_y)
def update_ball_velocity(self, index, *args):
''' Update the speed information of each ball, that is, the speed information of the ball colliding to the surrounding and other balls '''
# Swim values
self.scale_value = self.speed.get() * 0.1
# Collision wall
if (self.ball_x[index] > self.scaling_right) or (self.ball_x[index] < self.scaling_left):
self.ball_v_x[index] = -1.0 * self.ball_v_x[index]
if (self.ball_y[index] > self.scaling_bottom) or (self.ball_y[index] < self.scaling_top):
self.ball_v_y[index] = -1.0 * self.ball_v_y[index]
'''
#TEST:
for n in range(len(self.balls)):
#print((self.ball_x[index] - self.ball_x[n])**2)
#print(round((self.ball_x[index] - self.ball_x[n])**2 + (self.ball_y[index] - self.ball_y[n])**2, 2))
print(round((self.ball_x[index] - self.ball_x[n])**2 + (self.ball_y[index] - self.ball_y[n])**2, 2) <= round(self.ball_d**2, 2))
'''
for n in range(len(self.balls)):
# Ball collision conditions, namely: (x2 - x1)^2 + (y2 - y1)^2 <= (r + R)^2
if (round((self.ball_x[index] - self.ball_x[n])**2 + (self.ball_y[index] - self.ball_y[n])**2, 2) <= round(self.ball_d**2, 2)):
# The two balls exchange velocities
temp_vx = self.ball_v_x[index]
temp_vy = self.ball_v_y[index]
self.ball_v_x[index] = self.ball_v_x[n]
self.ball_v_y[index] = self.ball_v_y[n]
self.ball_v_x[n] = temp_vx
self.ball_v_y[n] = temp_vy
#print(self.ball_v_x, self.ball_v_y)
'''
#WRONG:
for n in range(len(self.balls)):
if (((self.ball_x[index] - self.ball_x[n])**2 + (self.ball_y[index] - self.ball_y[n])**2) <= self.ball_d**2):
# The two balls exchange velocities
self.ball_v_x[index] = self.ball_v_x[index] + self.ball_v_x[n]
self.ball_v_x[n] = self.ball_v_x[0] - self.ball_v_x[n]
self.ball_v_x[index] = self.ball_v_x[index] - self.ball_v_x[n]
self.ball_v_y[index] = self.ball_v_y[index] + self.ball_v_y[n]
self.ball_v_y[n] = self.ball_v_y[index] - self.ball_v_y[n]
self.ball_v_y[index] = self.ball_v_y[index] - self.ball_v_y[n]
print(self.ball_v_x, self.ball_v_y)
'''
def get_ball_deltax(self, index, *args):
''' For small ball X The axis moves the distance and updates the center of the ball X Coordinates, return X The distance the axis needs to travel '''
deltax = (self.ball_v_x[index] * self.scale_value / self.scaling)
self.ball_x[index] = self.ball_x[index] + deltax
return deltax
def get_ball_deltay(self, index, *args):
''' For small ball Y The axis moves the distance and updates the center of the ball Y Coordinates, return Y The distance the axis needs to travel '''
deltay = (self.ball_v_y[index] * self.scale_value / self.scaling)
self.ball_y[index] = self.ball_y[index] + deltay
return deltay
def moveBall(self, *args):
''' Move the first ball, numbered: 0, This is according to the array: self.balls Sure. '''
self.update_ball_velocity(0)
deltax = self.get_ball_deltax(0)
deltay = self.get_ball_deltay(0)
# A ball moving
self.draw.move(self.ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.moveBall)
def move_second_ball(self, *args):
self.update_ball_velocity(1)
deltax = self.get_ball_deltax(1)
deltay = self.get_ball_deltay(1)
self.draw.move(self.second_ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.move_second_ball)
def move_three_ball(self, *args):
self.update_ball_velocity(2)
deltax = self.get_ball_deltax(2)
deltay = self.get_ball_deltay(2)
self.draw.move(self.three_ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.move_three_ball)
def move_four_ball(self, *args):
self.update_ball_velocity(3)
deltax = self.get_ball_deltax(3)
deltay = self.get_ball_deltay(3)
self.draw.move(self.four_ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.move_four_ball)
def move_five_ball(self, *args):
self.update_ball_velocity(4)
deltax = self.get_ball_deltax(4)
deltay = self.get_ball_deltay(4)
self.draw.move(self.five_ball, "%ri" % deltax, "%ri" % deltay)
self.after(10, self.move_five_ball)
def __init__(self, master=None):
''' Initialization function '''
Frame.__init__(self, master)
Pack.config(self)
self.createWidgets()
self.after(10, self.moveBall)
self.after(10, self.move_three_ball)
self.after(10, self.move_four_ball)
self.after(10, self.move_five_ball)
self.after(10, self.move_second_ball)
game = Pong()
game.mainloop()
The source code download: (link: http://xiazai.jb51.net/201310/other/python_tkinter_pong (jb51.net). Rar)