"""Лови звёзды — первая 2D-аркада для детей на Python Arcade 3.3.3. Управление: A/D или стрелки. Собери 10 звёзд, избегай метеоритов. После победы или проигрыша нажми R, чтобы начать заново. """ import random import arcade WIDTH = 900 HEIGHT = 600 SHIP_Y = 75 SHIP_SPEED = 420 GOAL = 10 BACKGROUND = (10, 17, 45) WHITE = (241, 247, 255) GOLD = (255, 211, 91) CORAL = (255, 103, 111) BLUE = (82, 187, 255) class StarCatchGame(arcade.Window): """Окно хранит состояние игры и реагирует на клавиши и кадры.""" def __init__(self): super().__init__(WIDTH, HEIGHT, "Лови звёзды — Python Arcade") self.background_color = BACKGROUND self.sky = [(random.randrange(WIDTH), random.randrange(HEIGHT), random.choice((1, 2))) for _ in range(65)] self.restart() def restart(self): """Вернуть счёт, жизни и корабль в начальное состояние.""" self.ship_x = WIDTH / 2 self.left_pressed = False self.right_pressed = False self.drops = [] self.spawn_time = 0 self.score = 0 self.lives = 3 self.state = "playing" def on_draw(self): """Нарисовать один кадр игры.""" self.clear() for x, y, radius in self.sky: arcade.draw_circle_filled(x, y, radius, (100, 137, 203)) arcade.draw_text("ЛОВИ ЗВЁЗДЫ", 28, HEIGHT - 46, WHITE, 23, bold=True, font_name="Arial") arcade.draw_text(f"Звёзды: {self.score}/{GOAL}", 30, HEIGHT - 82, GOLD, 18, font_name="Arial") arcade.draw_text(f"Жизни: {self.lives}", WIDTH - 153, HEIGHT - 49, CORAL, 18, font_name="Arial") arcade.draw_text("A / D или ← / → • R — заново", 30, 19, (177, 196, 232), 14, font_name="Arial") for drop in self.drops: x, y = drop["x"], drop["y"] if drop["kind"] == "star": arcade.draw_circle_filled(x, y, 18, GOLD) arcade.draw_circle_filled(x, y, 7, WHITE) else: arcade.draw_circle_filled(x, y, 19, CORAL) arcade.draw_circle_filled(x - 5, y + 4, 5, (185, 52, 84)) # Корабль состоит из треугольника, кабины и двух огней. arcade.draw_triangle_filled(self.ship_x, SHIP_Y + 37, self.ship_x - 31, SHIP_Y - 24, self.ship_x + 31, SHIP_Y - 24, BLUE) arcade.draw_circle_filled(self.ship_x, SHIP_Y + 4, 10, WHITE) arcade.draw_circle_filled(self.ship_x - 23, SHIP_Y - 17, 6, GOLD) arcade.draw_circle_filled(self.ship_x + 23, SHIP_Y - 17, 6, GOLD) if self.state != "playing": title = "ПОБЕДА!" if self.state == "won" else "ИГРА ОКОНЧЕНА" color = GOLD if self.state == "won" else CORAL arcade.draw_lbwh_rectangle_filled(190, 215, 520, 170, (16, 30, 65, 240)) arcade.draw_text(title, WIDTH / 2, 315, color, 37, anchor_x="center", bold=True, font_name="Arial") arcade.draw_text("Нажми R, чтобы сыграть ещё раз", WIDTH / 2, 257, WHITE, 18, anchor_x="center", font_name="Arial") def on_update(self, delta_time): """Передвинуть объекты и проверить столкновения.""" if self.state != "playing": return direction = int(self.right_pressed) - int(self.left_pressed) self.ship_x += direction * SHIP_SPEED * delta_time self.ship_x = max(35, min(WIDTH - 35, self.ship_x)) self.spawn_time += delta_time if self.spawn_time >= 0.65: self.spawn_time = 0 self.drops.append({ "x": random.randrange(35, WIDTH - 35), "y": HEIGHT + 20, "kind": random.choice(("star", "star", "star", "meteor")), "speed": random.randrange(175, 255), }) for drop in self.drops[:]: drop["y"] -= drop["speed"] * delta_time caught = abs(drop["x"] - self.ship_x) < 39 and abs(drop["y"] - SHIP_Y) < 35 if caught: self.drops.remove(drop) if drop["kind"] == "star": self.score += 1 else: self.lives -= 1 elif drop["y"] < -20: self.drops.remove(drop) if self.lives <= 0: self.state = "lost" elif self.score >= GOAL: self.state = "won" def on_key_press(self, key, modifiers): """Запомнить, какая клавиша нажата.""" if key in (arcade.key.LEFT, arcade.key.A): self.left_pressed = True elif key in (arcade.key.RIGHT, arcade.key.D): self.right_pressed = True elif key == arcade.key.R: self.restart() def on_key_release(self, key, modifiers): """Остановить движение, когда клавишу отпустили.""" if key in (arcade.key.LEFT, arcade.key.A): self.left_pressed = False elif key in (arcade.key.RIGHT, arcade.key.D): self.right_pressed = False if __name__ == "__main__": StarCatchGame() arcade.run()