напиши игру
Ниже ‒ полностью-графическая, однофайловая игра «Космический Штурман».
Скопируй код в файл cosmic_shooter.py и запусти python cosmic_shooter.py.
Нужна только стандартная библиотека Python (tkinter встроен во все дистрибутивы).
# cosmic_shooter.py
import math
import random
import tkinter as tk
WIDTH, HEIGHT = 600, 700
PLAYER_SIZE = 40
ENEMY_SIZE = 30
BULLET_SIZE = 5
STAR_COUNT = 80
root = tk.Tk()
root.title("Космический Штурман")
root.resizable(False, False)
canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="black")
canvas.pack()
# ------------------------ объекты ------------------------
class Player:
def __init__(self):
x, y = WIDTH // 2, HEIGHT - 60
self.id = canvas.create_rectangle(x, y,
x + PLAYER_SIZE, y + PLAYER_SIZE,
fill="cyan", outline="white")
self.half = PLAYER_SIZE / 2
self.speed = 6
self.cooldown = 0
def move(self, dx, dy):
coords = canvas.coords(self.id)
new_x = max(0, min(WIDTH - PLAYER_SIZE, coords[0] + dx * self.speed))
new_y = max(0, min(HEIGHT - PLAYER_SIZE, coords[1] + dy * self.speed))
canvas.coords(self.id, new_x, new_y,
new_x + PLAYER_SIZE, new_y + PLAYER_SIZE)
def shoot(self):
if self.cooldown <= 0:
x, y = canvas.coords(self.id)[:2]
bx = x + self.half
by = y
bullets.append(Bullet(bx, by))
self.cooldown = 8
class Bullet:
def __init__(self, x, y):
self.id = canvas.create_oval(x - BULLET_SIZE, y - BULLET_SIZE,
x + BULLET_SIZE, y + BULLET_SIZE,
fill="yellow", outline="white")
self.speed = 12
def update(self):
canvas.move(self.id, 0, -self.speed)
if canvas.coords(self.id)[1] < 0:
self.destroy()
def destroy(self):
canvas.delete(self.id)
bullets.remove(self)
class Enemy:
def __init__(self):
x = random.randint(0, WIDTH - ENEMY_SIZE)
y = -ENEMY_SIZE
color = random.choice(["red", "magenta", "orange"])
self.id = canvas.create_oval(x, y,
x + ENEMY_SIZE, y + ENEMY_SIZE,
fill=color, outline="white")
self.speed = random.uniform(1.5, 3.5)
self.hp = 1 if color != "magenta" else 2 # магентовые - боссики
def update(self):
canvas.move(self.id, 0, self.speed)
x, y = canvas.coords(self.id)[:2]
if y > HEIGHT:
self.destroy()
def hit(self):
self.hp -= 1
if self.hp <= 0:
self.destroy()
return True
return False
def destroy(self):
canvas.delete(self.id)
if self in enemies:
enemies.remove(self)
# ------------------------ функции игры ------------------------
def spawn_enemy():
enemies.append(Enemy())
root.after(random.randint(700, 2000), spawn_enemy)
def spawn_star():
x = random.randint(0, WIDTH)
y = random.randint(-10, HEIGHT)
s = random.randint(1, 2)
sid = canvas.create_oval(x, y, x + s, y + s, fill="white", outline="")
stars.append(sid)
animate_star(sid)
def animate_star(sid):
canvas.move(sid, 0, 2)
x, y = canvas.coords(sid)[:2]
if y > HEIGHT:
canvas.coords(sid, random.randint(0, WIDTH), -5)
root.after(50, lambda: animate_star(sid))
def collision(a, b, size_a, size_b):
ax, ay = canvas.coords(a)[:2]
bx, by = canvas.coords(b)[:2]
return math.hypot(ax - bx, ay - by) < (size_a + size_b) / 2
def game_loop():
global score
player.cooldown = max(0, player.cooldown - 1)
# движение пуль
for b in bullets[:]:
b.update()
# движение врагов
for e in enemies[:]:
e.update()
# столкновения
for b in bullets[:]:
for e in enemies[:]:
if collision(b.id, e.id, BULLET_SIZE * 2, ENEMY_SIZE):
b.destroy()
if e.hit():
score += 10
break
# столкновение врага с игроком
for e in enemies[:]:
if collision(player.id, e.id, PLAYER_SIZE, ENEMY_SIZE):
game_over()
return
canvas.itemconfig(score_text, text=f"Счёт: {score}")
root.after(16, game_loop)
def game_over():
canvas.create_text(WIDTH // 2, HEIGHT // 2,
text="Конец игры!", fill="white",
font=("Courier", 36, "bold"))
canvas.create_text(WIDTH // 2, HEIGHT // 2 + 60,
text=f"Финальный счёт: {score}",
fill="white", font=("Courier", 18))
# ------------------------ управление ------------------------
keys = set()
def key_press(e):
keys.add(e.keysym)
def key_release(e):
keys.discard(e.keysym)
def handle_keys():
if "Left" in keys or "a" in keys: player.move(-1, 0)
if "Right" in keys or "d" in keys: player.move(1, 0)
if "Up" in keys or "w" in keys: player.move(0, -1)
if "Down" in keys or "s" in keys: player.move(0, 1)
if "space" in keys: player.shoot()
root.after(30, handle_keys)
# ------------------------ инициализация ------------------------
player = Player()
bullets, enemies = [], []
stars = []
score = 0
score_text = canvas.create_text(10, 10, anchor="nw",
text="Счёт: 0",
fill="white", font=("Courier", 14))
root.bind("<KeyPress>", key_press)
root.bind("<KeyRelease>", key_release)
for _ in range(STAR_COUNT):
spawn_star()
spawn_enemy()
handle_keys()
game_loop()
root.mainloop()
Как играть
← → ↑ ↓ или WASD — летать
Пробел — стрелять
Цель — набрать побольше очков, не позволив врагам коснуться корабля.