Не удается записать регистрацию столкновения

royalxdx

Новичок
Пользователь
Дек 13, 2023
1
0
1
Windows 10
python 3.11.5
стандартные библиотеки

Всем привет, делаю на питоне подобие игры арканойд и столкнулся с такой проблемой. Не могу понять, как мне в коде записать процесс, когда шарик бьется об кирпич и тот в свою очередь самоуничтожается(либо перемещается за границы экрна)
Как мне правильно записать регистрацию столкновения шарика с кирпичом, что бы потом он уничтожался, может кто подскажет?

Безымянный.png


Python:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Игра Прыг-скок
базовая версия
+ простая машина состояний
"""
import tkinter
import random
import time

class Zone():
    def __init__(self, canvas, color, position=[200,70,300,100]):
        self.Name = 'Zone'
        self.canvas = canvas
        self.position = position
        self.id = canvas.create_rectangle(position[0], position[1],
                                          position[2], position[3], fill=color)
# %%
class Point():
    def __init__(self, Point):
        self.renew(Point)
    def renew(self, Point):
        self.P = Point
        self.x0 = Point[0]
        self.y0 = Point[1]
        self.x1 = Point[2]
        self.y1 = Point[3]

def isInRange(x, a, b):
    """ проверка, находится ли х внутри диапазона a,b """
    return x>=a and x<=b

def isIntersect(pA, pB):
    """ проверка на пересечение области А с областью В
    pA, pB - объекты Point, задающие крайние точки объекта
    """
    xInside = isInRange(pA.x0, pB.x0, pB.x1) or isInRange(pA.x1, pB.x0, pB.x1)
    yInside = isInRange(pA.y0, pB.y0, pB.y1) or isInRange(pA.y1, pB.y0, pB.y1)
    return xInside and yInside

class Paddle():
    def __init__(self, canvas, color, width=100, height=10):
        self.canvas = canvas
        self.canvasH = self.canvas.winfo_reqheight()
        self.canvasW = self.canvas.winfo_reqwidth()

        self.id = canvas.create_rectangle(0, 0, width, height, fill=color)
        self.width = width
        self.height = height
        self.canvas.move(self.id,
                         int(self.canvasW/2 - width/2),
                         self.canvasH - height - 5)
        self.vx = 0
        # биндим нажатия клавиш на методы класса
        self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
        self.canvas.bind_all('<KeyRelease-Left>', self.stop)
        self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
        self.canvas.bind_all('<KeyRelease-Right>', self.stop)

    def turn_left(self, evt):
        self.vx = -2
    def turn_right(self, evt):
        self.vx = 2
    def stop(self, evt):
        self.vx = 0

    def draw(self):
        """ поведение ракетки """
        pos = self.canvas.coords(self.id)
        if pos[0] < 0:
            self.vx = 0
            self.canvas.move(self.id, -pos[0], 0) # сдвигаем к краю, если заехали за границу
        if pos[2] > self.canvasW:
            self.vx = 0
            self.canvas.move(self.id, self.canvasW-pos[2], 0)

        self.canvas.move(self.id, self.vx, 0)

class Ball():
    COLORS = ['red', 'green', 'blue', 'yellow', 'magenta', 'black', 'white']
    def __init__(self, canvas, paddle, color, kir1):
        # сохраняем ссылки на объекты канва и ракетка
        self.canvas = canvas
        self.canvasH = self.canvas.winfo_reqheight()
        self.canvasW = self.canvas.winfo_reqwidth()
        self.paddle = paddle
        self.color = color
        self.kir1 = kir1
        # создаём шарик
        self.r = 8 # радиус в пикселях
        self.id = canvas.create_oval(-self.r+1, -self.r+1,
                                     self.r, self.r, fill=color)
        self.canvas.move(self.id, int(0.5*self.canvasW), int(0.25*self.canvasH)) # начальное положение мяча
        # начальная скорость
        self.vx = random.choice([-3, -2, -1, 1, 2, 3])
        self.vy = -2

        # положения шарика, ракетки и зоны
        self.pBall = Point(self.canvas.coords(self.id))
        self.pPad = Point(self.canvas.coords(self.paddle.id))
        self.pkir1 = Point(self.canvas.coords(self.kir1.id))
        self.state = 'normal'

    def draw(self):
        """ здесь задаём поведение шарика """
        # обновили положение шара и ракетки
        self.pBall.renew(self.canvas.coords(self.id))
        pBall = self.pBall # алиасы
        pkir1 = self.pkir1
        # Поведение шарика
        
        # Эти два события работают всегда:
        # 1. Проверка на удар сверху и снизу
        if pBall.y0 <=0:
            self.canvas.move(self.id, 0, -pBall.y0)
            self.vy = abs(self.vy)
        if pBall.y1 >= self.canvasH:
            self.canvas.move(self.id, 0, -(pBall.y1-self.canvasH))
            self.vy = -abs(self.vy)

        # 2. Проверка на удары об стенки
        if (pBall.x0 <= 0) or (pBall.x1 >= self.canvasW):
            self.vx = -self.vx
            if pBall.x0<=0:
                self.canvas.move(self.id, -pBall.x0, 0)
            if pBall.x1>=self.canvasW:
                self.canvas.move(self.id, -(pBall.x1-self.canvasW), 0)
        
        # 3. проверка на удар об боковые стенки кипича
        if (pBall.x1 > pkir1.x0) & (pBall.y0 < pkir1.y1) & (pBall.y1 > pkir1.y0) & (pBall.x0 < pkir1.x0):
            self.vx = -self.vx
        
        if (pBall.x0 < pkir1.x1) & (pBall.y0 < pkir1.y1) & (pBall.y1 > pkir1.y0) & (pBall.x1 > pkir1.x1):
            self.vx = -self.vx
            
        # 4. проверка на удар об горизонтальные стенки кирпича
        if (pBall.y0 < pkir1.y1) & (pBall.x0 < pkir1.x1) & (pBall.x1 > pkir1.x0) & (pBall.y1 > pkir1.y1):
            self.vy = -self.vy
            
        if (pBall.y1 > pkir1.y0) & (pBall.x0 < pkir1.x1) & (pBall.x1 > pkir1.x0) & (pBall.y0 < pkir1.y0):
            self.vy = -self.vy

        self.canvas.move(self.id, self.vx, self.vy)

 
    # Проверки
    def inZone(self):
        """ проверка, не заходим ли мы в зону, хоть краешком """
        self.pBall.renew(self.canvas.coords(self.id))
        # print('ball:', self.pBall.P, 'zone', self.pZone.P)
        # self.pZone.renew(self.canvas.coords(self.zone.id)) # вдруг зона двигается
        return isIntersect(self.pBall, self.pZone)

    def notInZone(self):
        """ мы не в зоне """
        return not self.inZone()
    def touchesPad(self):
        """ проверка, не зашли ли мы на ракетку """
        self.pBall.renew(self.canvas.coords(self.id))
        self.pPad.renew(self.canvas.coords(self.paddle.id))
        return isIntersect(self.pBall, self.pPad)
    def touchesLine(self):
        """ проверка, не касаемся ли линии"""
        self.pBall.renew(self.canvas.coords(self.id))
        return isIntersect(self.pBall, self.pLine)


    # Действия
    def setRandomColor(self):
        # меняем цвет шарика, выбираем случайный из списка COLORS
        self.canvas.itemconfig(self.id, fill=random.choice(self.COLORS))
    def restoreColor(self):
        # меняем цвет шарика на первоначальный
        self.canvas.itemconfig(self.id, fill=self.color)
    def hitUp(self):
        # в случае касания ракетки, меняем vx на вверх
       self.vy = -abs(self.vy)
#% % Игра
# Создаём окно и канву для рисования
window = tkinter.Tk()
window.title("Игра Прыг-скок")
window.resizable(0, 0)
window.wm_attributes("-topmost", 1)

# # грязный хак для нормального закрытия окна - использую глобальную переменную isPlaying
isPlaying = True
def close_window():
   global isPlaying # так не делайте
   isPlaying = False
# Вызов close_window при а) закрытии окна и б) при нажатии Esc
window.protocol("WM_DELETE_WINDOW", close_window)
window.bind('<Escape>', lambda e: close_window())

# Создаём канву
canvas = tkinter.Canvas(window, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()

# создаем кирпич
kirpich1 = Zone(canvas, 'red', position=[270,250,480,190])
#kirpich2 = Zone(canvas, 'red', position=[190,60,10,90])

# Создаём игровые объекты
paddle = Paddle(canvas, 'blue')
ball = Ball(canvas, paddle, 'red', kirpich1)

var = tkinter.StringVar()
var.set('state')
lbl = tkinter.Label(canvas, textvariable=var) #anchor='se'
lbl.place(x = 10,y = 10)

# Главный цикл
try:
    while isPlaying:
        ball.draw()
        paddle.draw()

        window.update_idletasks()
        window.update()
        time.sleep(0.01)
finally:
    window.destroy() # уничтожаем окно
 

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
933
208
43
20
Москва
Так у тебя уже прописана проверка на касание кирпича, просто напиши исчезновение (self.canvas.delete(self.kir1.id))
 

Форум IT Специалистов