Загрузка данных
import tkinter as tk
import random
# Константы
WIDTH = 800
HEIGHT = 600
PLAYER_SIZE = 50
ASTEROID_SIZE = 40
BULLET_SIZE = 10
PLAYER_SPEED = 8
ASTEROID_SPEED = 4
BULLET_SPEED = 12
class Game:
def __init__(self):
self.window = tk.Tk()
self.window.title("Космический защитник")
self.canvas = tk.Canvas(self.window, width=WIDTH, height=HEIGHT, bg='black')
self.canvas.pack()
# Счет
self.score = 0
self.score_label = tk.Label(self.window, text=f"Счет: {self.score}", font=("Arial", 16), fg='white', bg='black')
self.score_label.pack()
# Игрок
self.player = self.canvas.create_rectangle(
WIDTH//2 - PLAYER_SIZE//2, HEIGHT - 70,
WIDTH//2 + PLAYER_SIZE//2, HEIGHT - 20,
fill='blue'
)
# Списки объектов
self.asteroids = []
self.bullets = []
# Флаги для плавного движения
self.left_pressed = False
self.right_pressed = False
self.space_pressed = False
self.shoot_delay = 0
self.shoot_cooldown = 10
# Управление - ВАЖНО! фокус на канвас
self.canvas.focus_set()
self.canvas.bind('<KeyPress-Left>', self.key_press)
self.canvas.bind('<KeyRelease-Left>', self.key_release)
self.canvas.bind('<KeyPress-Right>', self.key_press)
self.canvas.bind('<KeyRelease-Right>', self.key_release)
self.canvas.bind('<KeyPress-space>', self.key_press)
self.canvas.bind('<KeyRelease-space>', self.key_release)
# Игровой цикл
self.is_running = True
self.spawn_counter = 0
self.update()
self.window.mainloop()
def key_press(self, event):
print(f"Клавиша нажата: {event.keysym}") # Проверка в консоли
if event.keysym == 'Left':
self.left_pressed = True
elif event.keysym == 'Right':
self.right_pressed = True
elif event.keysym == 'space':
self.space_pressed = True
def key_release(self, event):
if event.keysym == 'Left':
self.left_pressed = False
elif event.keysym == 'Right':
self.right_pressed = False
elif event.keysym == 'space':
self.space_pressed = False
def move_player(self):
x1, y1, x2, y2 = self.canvas.coords(self.player)
if self.left_pressed and x1 > 0:
self.canvas.move(self.player, -PLAYER_SPEED, 0)
if self.right_pressed and x2 < WIDTH:
self.canvas.move(self.player, PLAYER_SPEED, 0)
def shoot(self):
if self.space_pressed and self.shoot_delay <= 0:
x1, y1, x2, y2 = self.canvas.coords(self.player)
bullet = self.canvas.create_rectangle(
x1 + PLAYER_SIZE//2 - BULLET_SIZE//2, y1,
x1 + PLAYER_SIZE//2 + BULLET_SIZE//2, y1 - 20,
fill='yellow'
)
self.bullets.append(bullet)
self.shoot_delay = self.shoot_cooldown
print("Выстрел!") # Проверка в консоли
elif self.shoot_delay > 0:
self.shoot_delay -= 1
def spawn_asteroid(self):
x = random.randint(20, WIDTH - 20)
size = ASTEROID_SIZE
colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple', 'pink', 'cyan']
color = random.choice(colors)
asteroid = self.canvas.create_polygon(
x + size//2, -size,
x + size//3, -size//3,
x, 0,
x + size//2, -size//4,
x + size, 0,
x + size*2//3, -size//3,
fill=color
)
self.asteroids.append(asteroid)
def update(self):
if not self.is_running:
return
# Движение игрока
self.move_player()
# Стрельба
self.shoot()
# Спавн астероидов
self.spawn_counter += 1
if self.spawn_counter >= 20:
self.spawn_counter = 0
self.spawn_asteroid()
# Движение астероидов
for asteroid in self.asteroids[:]:
self.canvas.move(asteroid, 0, ASTEROID_SPEED)
coords = self.canvas.coords(asteroid)
if coords:
star_y_max = max(coords[1::2])
if star_y_max > HEIGHT:
self.canvas.delete(asteroid)
self.asteroids.remove(asteroid)
# Движение пуль
for bullet in self.bullets[:]:
self.canvas.move(bullet, 0, -BULLET_SPEED)
x1, y1, x2, y2 = self.canvas.coords(bullet)
if y2 < 0:
self.canvas.delete(bullet)
self.bullets.remove(bullet)
# Проверка столкновений
self.check_collisions()
# Запуск следующего кадра
self.window.after(33, self.update)
def check_collisions(self):
player_coords = self.canvas.coords(self.player)
for bullet in self.bullets[:]:
bullet_coords = self.canvas.coords(bullet)
for asteroid in self.asteroids[:]:
asteroid_coords = self.canvas.coords(asteroid)
if asteroid_coords and bullet_coords:
# Проверка попадания
bullet_x = (bullet_coords[0] + bullet_coords[2]) / 2
bullet_y = (bullet_coords[1] + bullet_coords[3]) / 2
star_x_min = min(asteroid_coords[0::2])
star_x_max = max(asteroid_coords[0::2])
star_y_min = min(asteroid_coords[1::2])
star_y_max = max(asteroid_coords[1::2])
if star_x_min <= bullet_x <= star_x_max and star_y_min <= bullet_y <= star_y_max:
self.canvas.delete(bullet)
self.canvas.delete(asteroid)
if bullet in self.bullets:
self.bullets.remove(bullet)
if asteroid in self.asteroids:
self.asteroids.remove(asteroid)
self.score += 1
self.score_label.config(text=f"Счет: {self.score}")
break
for asteroid in self.asteroids:
asteroid_coords = self.canvas.coords(asteroid)
if asteroid_coords and player_coords:
player_x = (player_coords[0] + player_coords[2]) / 2
player_y = (player_coords[1] + player_coords[3]) / 2
star_x_min = min(asteroid_coords[0::2])
star_x_max = max(asteroid_coords[0::2])
star_y_min = min(asteroid_coords[1::2])
star_y_max = max(asteroid_coords[1::2])
if star_x_min <= player_x <= star_x_max and star_y_min <= player_y <= star_y_max:
self.game_over()
return
def game_over(self):
self.is_running = False
self.canvas.create_text(
WIDTH//2, HEIGHT//2,
text=f"ИГРА ОКОНЧЕНА\nСчет: {self.score}\nНажмите R для рестарта",
fill='white',
font=("Arial", 30),
justify='center'
)
self.canvas.bind('<KeyPress-r>', self.restart)
def restart(self, event):
self.canvas.delete('all')
self.__init__()
if __name__ == "__main__":
game = Game()