与 tkinter-canvas 交互球

Posted

技术标签:

【中文标题】与 tkinter-canvas 交互球【英文标题】:Interacting balls with tkinter-canvas 【发布时间】:2020-08-17 17:01:39 【问题描述】:

我能够使用 tkinter 对一些移动球进行编程。我用了两种不同的颜色。现在我希望白球在击中红球时将颜色变为红色。有人可以帮我吗?

(一个额外但不那么重要的一点是,如果一个球撞到另一个球会改变方向,那么哪个方向应该是随机的,但这不是那么重要)

总的来说,我有一个问题要弄清楚,球是如何相互作用的。这是我的代码:

from tkinter import *
import time
import random

WIDTH = 800
HEIGHT = 500

tk = Tk()
canvas = Canvas(tk, width=WIDTH, height=HEIGHT, bg="black")
tk.title("Drawing")
canvas.pack()

colors = ['red', 'green', 'blue', 'orange', 'yellow', 'cyan', 'magenta',
          'dodgerblue', 'turquoise', 'grey', 'gold', 'pink']

class Ball:
    def __init__(self, color):
        self.size = random.randrange(5, 10)
        #color = random.choice(colors)
        self.xpos = random.randrange(0,WIDTH)
        self.ypos =random.randrange(0,HEIGHT)
        self.shape = canvas.create_oval(self.xpos-self.size, self.ypos -self.size,self.xpos +self.size,self.ypos+self.size, fill=color)
        self.speedx = random.randrange(-5, 5)
        self.speedy = random.randrange(-5, 5)

    def update(self):
        canvas.move(self.shape, self.speedx, self.speedy)
        pos = canvas.coords(self.shape)
        if pos[2] >= (WIDTH) or (pos[0] ) <= 0:
            self.speedx *= -1
        if pos[3] >= (HEIGHT) or (pos[1]) <= 0:
            self.speedy *= -1


ball_list = []
Infiziert_list =[]
for i in range(100):
    ball_list.append(Ball('white'))
for j in range(3):
    ball_list.append(Ball('red'))
while True:
    for ball in ball_list:
        ball.update()
    tk.update()
    #time.sleep(0.001)

非常感谢

【问题讨论】:

这能回答你的问题吗? How to detect collisions of two canvas object Tkinter 首先:非常感谢,但不是真的,因为我不知道如何在我拥有的代码中得到它。所以我需要在更新的东西中以某种方式实现它,但是从 pos 我得到一个返回 3 点的向量。所以对于每个球individuell。所以我不知道如何将位置 ball1 连接到所有其他球 【参考方案1】:

您需要执行以下代码。

如果您想编写自己的代码。这里有一个很好的参考资料,请查看Ball collisions 部分。

运行此代码以获得碰撞球的完整工作示例,这些球在碰撞时会改变颜色。

from tkinter import *
import random

class Balls:
    color = ["red", "orange", "yellow", "green", "blue", "violet"]    
    v1x,v2x,v1y,v2y=0.1*random.randint(-10, 10),0.1*random.randint(-10, 10),0.1*random.randint(-10, 10),0.1*random.randint(-10, 10)
    def __init__(self, canvas,R,x1,y1,x2,y2):
        self.R=R
        self.x1 = x1
        self.y1=y1
        self.x2=x2
        self.y2 = y2
        self.canvas = canvas
        self.ball1 = canvas.create_oval(self.x1-self.R, self.y1-self.R,self.x1+self.R,self.y1+self.R, fill=random.choice(self.color))
        self.ball2 = canvas.create_oval(self.x2-self.R, self.y2-self.R,self.x2+self.R,self.y2+self.R, fill=random.choice(self.color))


    def callback(self):
        color=["red", "orange", "yellow", "green", "blue", "violet"] 
        self.AA=canvas.create_oval(self.x-10, self.y-10,self.x+10,self.y+10, fill=random.choice(color))
        self.vx,self.vy=0.5*random.randint(-10, 10),0.5*random.randint(-10, 10)
        canvas.move(self.AA, self.vx,self.vy)



    def move_balls(self):
        self.canvas.move(self.ball1, self.v1x,self.v1y)
        self.canvas.move(self.ball2, self.v2x,self.v2y)
        self.canvas.after(5, self.move_balls)

    def eventt(self):            
        A=[(canvas.coords(self.ball1)[0]-canvas.coords(self.ball2)[0]),
           (canvas.coords(self.ball1)[1]-canvas.coords(self.ball2)[1])]
        if ((A[0])**2+(A[1])**2)**0.5<=2*self.R:
            self.v1x,self.v1y,self.v2x,self.v2y=self.v2x,self.v2y,self.v1x,self.v1y
            canvas.itemconfig(self.ball1,fill=random.choice(self.color)) 
            canvas.itemconfig(self.ball2,fill=random.choice(self.color))
        if canvas.coords(self.ball1)[0]<=0 or canvas.coords(self.ball1)[2]>=400:
            self.v1x=-self.v1x
        if canvas.coords(self.ball1)[1]<=0 or canvas.coords(self.ball1)[3]>=400:
            self.v1y=-self.v1y
        if canvas.coords(self.ball2)[0]<=0 or canvas.coords(self.ball2)[2]>=400:
            self.v2x=-self.v2x
        if canvas.coords(self.ball2)[1]<=0 or canvas.coords(self.ball2)[3]>=400:
            self.v2y=-self.v2y
        self.canvas.after(10,self.eventt)


# initialize root Window and canvas
root = Tk()
root.title("Balls")
root.resizable(False,False)
canvas = Canvas(root, width = 400, height = 400)
canvas.bind("<Button-1>", Balls.callback)
canvas.pack()

# create two ball objects and animate them
ball = Balls(canvas ,20, 100, 200, 200, 300)
ball.move_balls()
ball.eventt()
root.mainloop()

【讨论】:

非常感谢,但我仍然不知道如何使用例如 50 个白球和 3 个红球来做到这一点。我现在尝试了很长时间,还有你给我的提示。但我无法找到有效的解决方案。也许我再说一遍重点:一开始我想有50个白球和3个红球。如果白球碰到红球,它们应该变成红色。如果任何球撞到另一个球,则应向随机方向移动。如果我不需要自己初始化每个球,那就太好了:/

以上是关于与 tkinter-canvas 交互球的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D摇杆

改变移动 SKSpriteNode 的方向?

单球机器人动力学与控制研究

Unity中的网格与材质球合并

51nod 3145概率与期望扔球游戏

51nod 3145概率与期望扔球游戏