如何检查两个对象是否在python tkinter中相互接触?

问题描述 投票:0回答:1

我正在尝试创建一个函数,该函数告诉我两个画布对象(在我的代码中,rec和block)在Tkinter中是否彼此接触。我尝试使用其坐标的信息来执行此操作,但似乎不起作用。您能帮我吗?

该函数将在我在下面的代码中创建的蛇中使用,所以不要问我为什么代码这么长。

该函数在第119行中,same_poz

这是我的代码:

from tkinter import *
import time
import random
import threading

root = Tk()
root.title('Snake')
x, y = 484, 484
recX, recY = x // 2, y // 2
recW, recH = recX + 22, recY + 22
randoms = []
for i in range(484):
    if i % 11 == 0:
        randoms.append(i)
blockX, blockY = random.choice(randoms), random.choice(randoms)
blockW, blockH = blockX + 22, blockY + 22
c = Canvas(root, bg='black', width=x, height=y)
c.pack()



class Snake(threading.Thread):
    def __init__(self, c, x, y, recX, recY, recW, recH, blockX, blockY, blockW, blockH):
        super(Snake, self).__init__()
        self.c = c
        self.x = x
        self.y = y
        self.recX = recX
        self.recY = recY
        self.recW = recW
        self.recH = recH
        self.blockW = blockW
        self.blockH = blockH
        self.rec = c.create_rectangle(recX, recY, recW, recH, fill='red', outline='white')
        self.blockX = blockX
        self.blockY = blockY
        self.block = c.create_rectangle(blockX, blockY, blockW, blockH, fill='green', 
        outline='white')
        self.moving_right = False
        self.moving_left = False
        self.moving_up = False
        self.moving_down = False
        self.moving = False

    def movingright(self):
        self.moving_right = True
        self.moving_left = False
        self.moving_up = False
        self.moving_down = False
        self.moving = True
        c.move(self.rec, 11, 0)
        self.after4 = root.after(150, self.movingright)

    def movingleft(self):
        self.moving_left = True
        self.moving_left = False
        self.moving_up = False
        self.moving_down = False
        self.moving = True
        c.move(self.rec, -11, 0)
        self.after3 = root.after(150, self.movingleft)

    def movingup(self):
        self.moving_up = True
        self.moving_right = False
        self.moving_left = False
        self.moving_up = False
        self.moving = True
        c.move(self.rec, 0, -11)
        self.after = root.after(150, self.movingup)

    def movingdown(self):
        self.moving_down = True
        self.moving_right = False
        self.moving_left = False
        self.moving_down = False
        self.moving = True
        c.move(self.rec, 0, 11)
        self.after2 = root.after(150, self.movingdown)

    def stop(self):
        self.moving_right = False
        self.moving_left = False
        self.moving_up = False
        self.moving_down = False
        self.moving = False

        try:
            root.after_cancel(self.after)
        except AttributeError:
            pass
        try:
            root.after_cancel(self.after2)
        except AttributeError:
            pass
        try:
            root.after_cancel(self.after3)
        except AttributeError:
            pass
        try:
            root.after_cancel(self.after4)
        except AttributeError:
            pass

    def move(self, n):
        if n.keysym == 'Up':
            self.stop()
            self.movingup()
        if n.keysym == 'Down':
            self.stop()
            self.movingdown()
        if n.keysym == 'Right':
            self.stop()
            self.movingright()
        if n.keysym == 'Left':
            self.stop()
            self.movingleft()

    def same_poz(self):
        if self.blockY == self.recY:
            self.helpY = random.randint(10, self.y - self.blockY)
            self.c.move(self.block, 0, self.helpY)
        if self.blockX == self.recY:
            self.helpX = random.randint(10, self.x - self.blockX)
            self.c.move(self.block, 0, self.helpX)
        if self.blockW == self.recW:
            self.helpW = random.randint(10, self.x - self.blockW)
            self.c.move(self.block, 0, self.helpW)
        if self.blockH == self.recH:
            self.helpH = random.randint(10, self.y - self.blockH)
            self.c.move(self.block, 0, helpH)



cube = Snake(c, x, y, recX, recY, recW, recH, blockX, blockY, blockW, blockH)
cube.start()




cube.c.bind_all('<Key>', cube.move, cube.stop)
cube.c.bind_all('<Key>', cube.moving_left, cube.moving_right)
cube.c.bind_all('<Key', cube.moving_up, cube.moving_down)
cube.c.bind(cube.same_poz)
root.mainloop()
python-3.x multithreading canvas tkinter collision
1个回答
0
投票

您提供的代码中存在太多问题。我不知道为什么在仍然缺乏Python基础知识的情况下为何使用Tkinter进行编程。 (不是要听起来刺耳)

  1. 我不知道您为什么决定何时从threading.Thread继承您对Thread提供的任何内容都没有任何用处课。
  2. 没有太多实例参数,根本没有用,并且有太多实例参数必须每次更改。
  3. 不使用elif,而是经常使用if
  4. 如果使用线程处理mainloop之外的Tkinter更改,则基本上不需要这样做,因此不需要使用.after。>
  5. Tkinter对每个键都有专用的绑定,包括键的组合。无需捕获每个按键事件。
  6. 如果使用单个脚本,请使用if __name__ == '__main__':进行测试。
  7. Tkinter上的某些阅读材料-http://effbot.org/tkinterbook/
  8. 这里是对代码的最小重做,正在工作。

import time
import random
import threading
from tkinter import *

MOVINGUP = 'u'
MOVINGDOWN = 'd'
MOVINGLEFT = 'l'
MOVINGRIGHT = 'r'
NOTMOVING = '0'


class Snake:
    def __init__(self, root, recX, recY, recW, recH, blockX, blockY, blockW, blockH):
        self.root = root

        self.c = Canvas(root, bg='black', width=x, height=y)
        self.c.pack()

        self.rec = self.c.create_rectangle(recX, recY, recW, recH, fill='red', outline='white')
        self.block = self.c.create_rectangle(blockX, blockY, blockW, blockH, fill='green', outline='white')

        self.direction = NOTMOVING

        self.root.bind('<Up>', lambda e: self.moveset(MOVINGUP))
        self.root.bind('<Down>', lambda e: self.moveset(MOVINGDOWN))
        self.root.bind('<Left>', lambda e: self.moveset(MOVINGLEFT))
        self.root.bind('<Right>', lambda e: self.moveset(MOVINGRIGHT))

    def moveset(self, direction):
        self.direction = direction

    def movement(self):
        if self.direction == MOVINGUP:
            self.c.move(self.rec, 0, -11)
        elif self.direction == MOVINGDOWN:
            self.c.move(self.rec, 0, 11)
        elif self.direction == MOVINGLEFT:
            self.c.move(self.rec, -11, 0)
        elif self.direction == MOVINGRIGHT:
            self.c.move(self.rec, 11, 0)
        self.same_poz()

    def run(self):
        while True:
            time.sleep(0.15)
            self.movement()

    def same_poz(self):
        # Snake (x0, y0, x1, y1)
        snakepos = self.c.bbox(self.rec)
        # Food block (x0, y0, x1, y1)
        food = self.c.bbox(self.block)
        # If direction matters, if not then possible to only use self.hit in a single condition.
        if self.direction == MOVINGRIGHT and self.hit(snakepos, food):
            print('Caught the food moving right.')
        elif self.direction == MOVINGLEFT and self.hit(snakepos, food):
            print('Caught the food moving left.')
        elif self.direction == MOVINGUP and self.hit(snakepos, food):
            print('Caught the food moving up.')
        elif self.direction == MOVINGDOWN and self.hit(snakepos, food):
            print('Caught the food moving down.')

    def hit(self, snakepos, food):
        """
            Recieves coordinates of food block and snake block and returns if they collide.
        :param snakepos: Tuple containing (x0, y0, x1, y1) of the snake.
        :param food: Tuple containing (x0, y0, x1, y1) of the food block.
        :return: Boolean whether they collide
        """
        snakex = (snakepos[0], snakepos[2])
        snakey = (snakepos[1], snakepos[3])
        foodx = (food[0], food[2])
        foody = (food[1], food[3])
        # Returns True if any of the snake x cooridnates are between the food x coordinates, or both x coordinates match.
        if any((foodx[0] < xcoord < foodx[1] for xcoord in snakex)) or foodx == snakex:
            # Returns True if any of the snake y cooridnates are between the food y coordinates, or both y coordinates match.
            return any((foody[0] < ycoord < foody[1] for ycoord in snakey)) or foody == snakey
        return False


if __name__ == '__main__':
    root = Tk()
    root.title('Snake')
    x, y = 484, 484
    recX, recY = x // 2, y // 2
    recW, recH = recX + 22, recY + 22
    randoms = []
    for i in range(484):
        if i % 11 == 0:
            randoms.append(i)
    blockX, blockY = random.choice(randoms), random.choice(randoms)
    blockW, blockH = blockX + 22, blockY + 22


    snake = Snake(root, recX, recY, recW, recH, blockX, blockY, blockW, blockH)
    threading.Thread(target=snake.run, daemon=True).start()

    root.mainloop()
© www.soinside.com 2019 - 2024. All rights reserved.