如何忽略一些Tkinter碰撞?

2024-10-03 19:31:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我在画布上画了一个网格,在一些单元格里画了一个圆圈。我的目标是绕着网格移动一圈,而不是越过另一圈。所以当我移动圆的时候,我检查是否有东西在移动,如果有,取消移动。首先,我试着在运动结束时检查碰撞情况,但我没能让它工作。所以我试着在移动时检查,但是我意识到画布线也是对象,所以有碰撞。 有没有什么“简单”的方法可以忽略这些线的碰撞而不是圆的碰撞?你知道吗

class Deplacement:
def __init__(self, canvas, event):
    self.x = event.x
    self.y = event.y
    self.canvas = canvas
    self.obj = "à déterminer"
    self.obj2 = "à déterminer"
    self.couleur = "à déterminer"
    self.couleur2 = "à déterminer"
    self.collision = "à déterminer"
    canvas.bind("<ButtonPress-1>", self.StartMove)
    canvas.bind("B1-Motion", self.OnMotion)
    canvas.bind("<ButtonRelease-1>", self.StopMove)

def StartMove(self, event): #Getting the object I want to move
    self.x = event.x
    self.y = event.y
    self.obj = self.canvas.find_overlapping(self.x - 15, self.y - 15, self.x + 15, self.y + 15) 

def OnMotion(self, event): #This is where I struggle
    #Trying to get the second circle if it exists
    self.obj2 = self.canvas.find_overlapping(event.x - 15, event.y - 15, event.x + 15, event.y + 15)
    if not self.obj2:
        self.collision = False
    else:
        self.collision = True

def StopMove(self, event): #This works fine, in context, checking items colors to move them or not
#And objects must be moved by one axis
    self.couleur = self.canvas.itemcget(self.obj, "fill")
    if not self.collision:
        if self.couleur == 'black' or self.couleur == 'white' or self.couleur == 'red':
            if event.x > self.x and self.y - 10 <= event.y <= self.y + 10:
                self.move(event, self.obj)
            elif event.x < self.x and self.y - 10 <= event.y <= self.y + 10:
                self.move(event, self.obj)
            elif event.y > self.y and self.x - 10 <= event.x <= self.x + 10:
                self.move(event, self.obj)
            elif event.y < self.y and self.x - 10 <= event.x <= self.x + 10:
                self.move(event, self.obj)

def move(self, event, obj): #Finally moving objects, works nicely aswell
    self.x = (event.x - 20) // 50 + 1
    self.y = (event.y - 20) // 50 + 1
    self.obj = obj
    if event.x < 20:
        self.x = 1
        self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15)
    elif event.y < 20:
        self.y = 1
        self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15)
    elif event.x > 470:
        self.x = 9
        self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15)
    elif event.y > 470:
        self.y = 9
        self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15)
    else:
        self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15)

附言:忽略法语单词。你知道吗


Tags: andselfeventobjmoveifbinddef
2条回答

我假设名为canvas的变量是Tkinters的Canvas类的一个实例。您没有显示填充画布的代码,但我假设您使用方法调用来填充画布,例如canvas.create_line()canvas.create_oval()等等。每个方法都返回一个整数,它是所创建形状的ID。您必须做的是存储要忽略的形状的ID,换句话说,创建一组不应构成冲突的形状ID。假设你把它们放到一个名为ignore_these的集合中。你知道吗

方法find_overlapping返回与指定矩形重叠的形状元组。假设我们将这个返回值称为possible_collisions。因此,要判断是否发生碰撞,只需要一行代码,例如:

if any(s not in ignore_these for s in possible_collisions):
    # handle the collision
else:
    # go ahead and make the move

这是一个两步的过程(创建一组非冲突的形状,然后用它来分析find\u重叠的结果)。你要求一个简单的方法来做这件事,但我怀疑是否有办法避免这两个步骤;Tkinter至少给了你编写必要逻辑所需的钩子。你知道吗

手册参考:http://effbot.org/tkinterbook/canvas.htm#Tkinter.Canvas

将项添加到画布时,使用的方法将返回这些对象的唯一id(整数)。必须在集合中收集这些ID,并为发生冲突的项的ID添加一个集合。(您可以分离不发生碰撞的项目,但每次运行碰撞检测部件时都必须对其进行过滤)

这是伪代码:

def create_canvas_objects(self):
    id = canvas.create_object()
    self.all_canvas_objects_ids.append(id)
    if object_collides:
        self.colliding_objects.append(id)

def check_collisions(self):
    for object in self.colliding_objects:
        check the collision

这样,在创建碰撞对象和非碰撞对象时只过滤一次,而不是每一帧。你知道吗

相关问题 更多 >