mirror of
https://github.com/csd4ni3l/fleet-commander.git
synced 2026-01-01 04:23:47 +01:00
Add 10 million timestep model, improve README, add diffculty/mode selector, score, make model training have instant graphs and also multiple envs for faster training, better plotting, improve RL model by including multiple players, better reard system, use EnemyFormation instead of single Enemy-es
This commit is contained in:
118
game/play.py
118
game/play.py
@@ -1,16 +1,17 @@
|
||||
import arcade, arcade.gui, random, time
|
||||
|
||||
from utils.constants import button_style, ENEMY_ROWS, ENEMY_COLS, PLAYER_ATTACK_SPEED
|
||||
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 Enemy, Player, Bullet
|
||||
from game.sprites import EnemyFormation, Player, Bullet
|
||||
|
||||
class Game(arcade.gui.UIView):
|
||||
def __init__(self, pypresence_client):
|
||||
def __init__(self, pypresence_client, settings):
|
||||
super().__init__()
|
||||
|
||||
self.settings = settings
|
||||
self.pypresence_client = pypresence_client
|
||||
self.pypresence_client.update(state="Invading Space")
|
||||
|
||||
@@ -18,42 +19,53 @@ class Game(arcade.gui.UIView):
|
||||
|
||||
self.spritelist = arcade.SpriteList()
|
||||
|
||||
self.player = 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.player)
|
||||
|
||||
self.last_player_shoot = time.perf_counter() # not actually player
|
||||
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.enemies: list[Enemy] = []
|
||||
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.summon_enemies()
|
||||
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 summon_enemies(self):
|
||||
enemy_start_x = self.window.width * 0.15
|
||||
enemy_start_y = self.window.height * 0.9
|
||||
|
||||
for row in range(ENEMY_ROWS):
|
||||
for col in range(ENEMY_COLS):
|
||||
enemy_sprite = Enemy(enemy_start_x + col * 100, enemy_start_y - row * 100)
|
||||
self.spritelist.append(enemy_sprite)
|
||||
self.enemies.append(enemy_sprite)
|
||||
|
||||
def on_update(self, delta_time):
|
||||
for enemy in self.enemies:
|
||||
enemy.update()
|
||||
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 = []
|
||||
|
||||
@@ -62,18 +74,21 @@ class Game(arcade.gui.UIView):
|
||||
|
||||
bullet_hit = False
|
||||
if bullet.direction_y == 1:
|
||||
for enemy in self.enemies:
|
||||
for enemy in self.enemy_formation.enemies:
|
||||
if bullet.rect.intersection(enemy.rect):
|
||||
self.spritelist.remove(enemy)
|
||||
self.enemies.remove(enemy)
|
||||
self.player.target = None
|
||||
self.enemy_formation.remove_enemy(enemy)
|
||||
bullets_to_remove.append(bullet)
|
||||
bullet_hit = True
|
||||
break
|
||||
else:
|
||||
if bullet.rect.intersection(self.player.rect):
|
||||
bullets_to_remove.append(bullet)
|
||||
bullet_hit = True
|
||||
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)
|
||||
@@ -86,20 +101,40 @@ class Game(arcade.gui.UIView):
|
||||
elif bullet_to_remove in self.player_bullets:
|
||||
self.player_bullets.remove(bullet_to_remove)
|
||||
|
||||
self.player.update(self.model, self.enemies, self.enemy_bullets, self.window.width, self.window.height) # not actually player
|
||||
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 self.player.center_x > self.window.width:
|
||||
self.player.center_x = self.window.width
|
||||
elif self.player.center_x < 0:
|
||||
self.player.center_x = 0
|
||||
if player.center_x > self.window.width:
|
||||
player.center_x = self.window.width
|
||||
elif player.center_x < 0:
|
||||
player.center_x = 0
|
||||
|
||||
if self.player.shoot:
|
||||
self.player.shoot = False
|
||||
self.shoot(self.player.center_x, self.player.center_y, 1)
|
||||
if player.shoot:
|
||||
player.shoot = False
|
||||
self.shoot(player.center_x, player.center_y, 1)
|
||||
|
||||
if time.perf_counter() - self.last_player_shoot >= PLAYER_ATTACK_SPEED:
|
||||
self.last_player_shoot = time.perf_counter()
|
||||
self.shoot(self.player.center_x, self.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)
|
||||
@@ -112,11 +147,6 @@ class Game(arcade.gui.UIView):
|
||||
|
||||
bullets.append(bullet)
|
||||
|
||||
def on_key_press(self, symbol, modifiers):
|
||||
if symbol == arcade.key.SPACE:
|
||||
enemy = random.choice(self.enemies)
|
||||
self.shoot(enemy.center_x, enemy.center_y, -1)
|
||||
|
||||
def on_draw(self):
|
||||
super().on_draw()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user