Files
fleet-commander/game/play.py

153 lines
6.9 KiB
Python

import arcade, arcade.gui, random, time
from utils.constants import button_style, ENEMY_ATTACK_SPEED, ENEMY_SPEED
from utils.preload import button_texture, button_hovered_texture
from stable_baselines3 import PPO
from game.sprites import EnemyFormation, Player, Bullet
class Game(arcade.gui.UIView):
def __init__(self, pypresence_client, settings):
super().__init__()
self.settings = settings
self.pypresence_client = pypresence_client
self.pypresence_client.update(state="Invading Space")
self.anchor = self.add_widget(arcade.gui.UIAnchorLayout(size_hint=(1, 1)))
self.spritelist = arcade.SpriteList()
self.players = []
for _ in range(settings["player_count"]):
self.players.append(Player(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), 100)) # not actually player
self.spritelist.append(self.players[-1])
self.model = PPO.load("invader_agent.zip")
self.enemy_formation = EnemyFormation(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), self.window.height * 0.9, self.spritelist, settings["enemy_rows"], settings["enemy_cols"])
self.player_bullets: list[Bullet] = []
self.enemy_bullets: list[Bullet] = []
self.player_respawns = settings["player_respawns"]
self.enemy_respawns = settings["enemy_respawns"]
self.score = 0
self.last_enemy_shoot = time.perf_counter()
self.game_over = False
def on_show_view(self):
super().on_show_view()
self.back_button = self.anchor.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50), anchor_x="left", anchor_y="top", align_x=5, align_y=-5)
self.back_button.on_click = lambda event: self.main_exit()
self.score_label = self.anchor.add(arcade.gui.UILabel("Score: 0", font_size=24), anchor_x="center", anchor_y="top")
def main_exit(self):
from menus.main import Main
self.window.show_view(Main(self.pypresence_client))
def on_update(self, delta_time):
if self.game_over:
return
if self.window.keyboard[arcade.key.LEFT] or self.window.keyboard[arcade.key.A]:
self.enemy_formation.move(self.window.width, self.window.height, "x", -ENEMY_SPEED)
if self.window.keyboard[arcade.key.RIGHT] or self.window.keyboard[arcade.key.D]:
self.enemy_formation.move(self.window.width, self.window.height, "x", ENEMY_SPEED)
if self.window.keyboard[arcade.key.DOWN] or self.window.keyboard[arcade.key.S]:
self.enemy_formation.move(self.window.width, self.window.height, "y", -ENEMY_SPEED)
if self.window.keyboard[arcade.key.UP] or self.window.keyboard[arcade.key.W]:
self.enemy_formation.move(self.window.width, self.window.height, "y", ENEMY_SPEED)
if self.enemy_formation.enemies and self.window.keyboard[arcade.key.SPACE] and time.perf_counter() - self.last_enemy_shoot >= ENEMY_ATTACK_SPEED:
self.last_enemy_shoot = time.perf_counter()
enemy = self.enemy_formation.get_lowest_enemy()
self.shoot(enemy.center_x, enemy.center_y, -1)
bullets_to_remove = []
for bullet in self.player_bullets + self.enemy_bullets:
bullet.update()
bullet_hit = False
if bullet.direction_y == 1:
for enemy in self.enemy_formation.enemies:
if bullet.rect.intersection(enemy.rect):
self.enemy_formation.remove_enemy(enemy)
bullets_to_remove.append(bullet)
bullet_hit = True
break
else:
for player in self.players:
if bullet.rect.intersection(player.rect):
self.spritelist.remove(player)
self.players.remove(player)
bullets_to_remove.append(bullet)
bullet_hit = True
self.score += 75
break
if not bullet_hit and bullet.center_y > self.window.height or bullet.center_y < 0:
bullets_to_remove.append(bullet)
for bullet_to_remove in bullets_to_remove:
self.spritelist.remove(bullet_to_remove)
if bullet_to_remove in self.enemy_bullets:
self.enemy_bullets.remove(bullet_to_remove)
elif bullet_to_remove in self.player_bullets:
self.player_bullets.remove(bullet_to_remove)
for player in self.players:
player.update(self.model, self.enemy_formation, self.enemy_bullets, self.window.width, self.window.height, self.player_respawns / self.settings["player_respawns"], self.enemy_respawns / self.settings["enemy_respawns"]) # not actually player
if player.center_x > self.window.width:
player.center_x = self.window.width
elif player.center_x < 0:
player.center_x = 0
if player.shoot:
player.shoot = False
self.shoot(player.center_x, player.center_y, 1)
if len(self.players) == 0:
if self.player_respawns > 0:
self.player_respawns -= 1
for _ in range(self.settings["player_count"]):
self.players.append(Player(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), 100)) # not actually player
self.spritelist.append(self.players[-1])
self.score += 300
else:
self.game_over = True
self.game_over_label = self.anchor.add(arcade.gui.UILabel("You (The enemies) won!", font_size=48), anchor_x="center", anchor_y="center")
elif len(self.enemy_formation.enemies) == 0:
if self.enemy_respawns > 0:
self.enemy_respawns -= 1
self.enemy_formation.create_formation(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), self.window.height * 0.9)
else:
self.game_over = True
self.game_over_label = self.anchor.add(arcade.gui.UILabel("You lost! The Players win!", font_size=48), anchor_x="center", anchor_y="center")
self.score += 5 * delta_time
self.score_label.text = f"Score: {int(self.score)}"
def shoot(self, x, y, direction_y):
bullet = Bullet(x, y, direction_y)
self.spritelist.append(bullet)
if direction_y == 1:
bullets = self.player_bullets
else:
bullets = self.enemy_bullets
bullets.append(bullet)
def on_draw(self):
super().on_draw()
self.spritelist.draw()