Windows 10
python 3.11.5
стандартные библиотеки
Всем привет, делаю на питоне подобие игры арканойд и столкнулся с такой проблемой. Не могу понять, как мне в коде записать процесс, когда шарик бьется об кирпич и тот в свою очередь самоуничтожается(либо перемещается за границы экрна)
Как мне правильно записать регистрацию столкновения шарика с кирпичом, что бы потом он уничтожался, может кто подскажет?
python 3.11.5
стандартные библиотеки
Всем привет, делаю на питоне подобие игры арканойд и столкнулся с такой проблемой. Не могу понять, как мне в коде записать процесс, когда шарик бьется об кирпич и тот в свою очередь самоуничтожается(либо перемещается за границы экрна)
Как мне правильно записать регистрацию столкновения шарика с кирпичом, что бы потом он уничтожался, может кто подскажет?
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() # уничтожаем окно