Я пытаюсь создать программу, в которой есть 6 разделов и куча шаров отскакивают друг от друга. Шары не делают то, что они должны делать, а вместо этого застревают друг на друге. Иногда они подпрыгивают, иногда нет.
Я пробовал несколько формул для отскока 2D, но однажды кажется, что он действительно сохраняет импульс. Это измененная модель из того, что я имел ранее, которая была в основном прямой копией со страницы википедии для 2D-столкновений. Это не сработало, и текущая модель, которую я взял из другого ответа stackoverflow, дает такие же результаты. Я думаю, что моя физика может быть правильной, но что-то еще в коде все испортило. Я просматривал это снова и снова, но я все еще не могу найти то, что это могло бы быть. Любая помощь будет оценена.
from tkinter import *
import random
tk = Tk()
#canvas object
canv_width = 300
canv_height = 300
canvas1 = Canvas(tk, width = canv_width, height = canv_height, bg = 'black',highlightthickness=1, highlightbackground='white')
canvas2 = Canvas(tk, width = canv_width, height = canv_height, bg = 'black',highlightthickness=1, highlightbackground='white')
canvas3 = Canvas(tk, width = canv_width, height = canv_height, bg = 'black',highlightthickness=1, highlightbackground='white')
canvas4 = Canvas(tk, width = canv_width, height = canv_height, bg = 'black',highlightthickness=1, highlightbackground='white')
canvas5 = Canvas(tk, width = canv_width, height = canv_height, bg = 'black',highlightthickness=1, highlightbackground='white')
canvas6 = Canvas(tk, width = canv_width, height = canv_height, bg = 'black',highlightthickness=1, highlightbackground='white')
canvas1.grid(row=0,column=0)
canvas2.grid(row=0,column=1)
canvas3.grid(row=1,column=0)
canvas4.grid(row=1,column=1)
canvas5.grid(row=2,column=0)
canvas6.grid(row=2,column=1)
tk.title("BounceBox")
towns = {'1': canvas1, '2' : canvas2, '3': canvas3, '4' : canvas4, '5' : canvas5, '6': canvas6}
pops = {'1' : [], '2': [], '3': [], '4': [], '5': [], '6':[]}
def subtract(v1,v2):
x_comp = v1[0] - v2[0]
y_comp = v1[1] - v2[1]
return ((x_comp,y_comp))
def add(v1,v2):
x_comp = v1[0] + v2[0]
y_comp = v1[1] + v2[1]
return((x_comp,y_comp))
def dotproduct(v1,v2):
x_comp = v1[0] * v2[0]
y_comp = v1[1] * v2[1]
return(x_comp + y_comp)
def magnitude(v):
mag = (v[0]**2 + v[1]**2)**0.5
return mag
def mult_sv(s,v):
x_comp = s*v[0]
y_comp = s*v[1]
return((x_comp,y_comp))
def arctan(y,x):
try:
ans = math.atan(y/x)
if x >= 0 and y >= 0:
return ans
elif x <= 0 and y >= 0:
return ans + math.pi
elif x >= 0 and y <= 0:
return ans
else:
return ans - math.pi
except:
if y>0:
return math.pi
else:
return -math.pi
class Ball:
def __init__(self,radius,color,location,location_name):
self.location = location
self.location_name = location_name
self.radius = radius
ball_x = random.randint(0,canv_width - radius)
ball_y = random.randint(0,canv_height - radius)
self.pos = (ball_x,ball_y,ball_x + 2*self.radius, ball_y + 2*self.radius)
self.center = (self.pos[0] + self.radius, self.pos[1] + self.radius)
self.xspeed = random.randint(-1,1)
self.yspeed = random.randint(-1,1)
self.color = color
self.shape = self.location.create_oval(self.pos[0],self.pos[1],self.pos[2], self.pos[3], fill = self.color)
self.ball_update()
def check_collision(self):
for person in pops[self.location_name]:
center = person.center
distance = ((self.center[0] - person.center[0])**2 + (self.center[1] - person.center[1])**2)**0.5
if (distance <= 2*self.radius and person != self):
return (True,person)
return (False,None)
def ball_update(self):
#print(arctan(-1,1))
self.pos = self.location.coords(self.shape)
self.center = (self.pos[0] + self.radius, self.pos[1] + self.radius)
if (self.pos[0] <= 0 or self.pos[2] >= canv_width):
self.xspeed = -self.xspeed
if (self.pos[1] <= 0 or self.pos[3] >= canv_height):
self.yspeed = -self.yspeed
collision = self.check_collision()
if collision[0] == True:
v1 = (self.xspeed,self.yspeed)
v2 = (collision[1].xspeed, collision[1].yspeed)
dist = subtract(self.center,collision[1].center)
v12 = subtract(v1,v2)
dv = mult_sv(dotproduct(v12,dist)/ magnitude(dist)**2,dist)
self.xspeed -= dv[0]
self.yspeed -= dv[1]
collision[1].xspeed += dv[0]
collision[1].yspeed += dv[1]
self.location.move(self.shape, self.xspeed, self.yspeed)
self.center = (self.pos[0] + self.radius, self.pos[1] + self.radius)
tk.after(15,self.ball_update)
def create_populations():
for town in towns:
for pop in range(5):
person = Ball(10,'white',towns[town],town)
pops[town].append(person)
create_populations()
tk.mainloop()