diff --git a/.idea/CASTLE_WAR.iml b/.idea/CASTLE_WAR.iml index d0876a7..1be71fe 100644 --- a/.idea/CASTLE_WAR.iml +++ b/.idea/CASTLE_WAR.iml @@ -1,8 +1,10 @@ - - + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 0baf0bb..735c5e5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/font/pixel.ttf b/font/pixel.ttf new file mode 100644 index 0000000..cf6fdf4 Binary files /dev/null and b/font/pixel.ttf differ diff --git a/implementable/Functions.py b/implementable/Functions.py new file mode 100644 index 0000000..82b0449 --- /dev/null +++ b/implementable/Functions.py @@ -0,0 +1,316 @@ +import time + +import pygame as pg + +from objects.Constants import * +from objects.Wall import Wall +from objects.players.Archer import Archer +from objects.players.SwordsMan import SwordsMan +from objects.players.Worker import Worker + +pg.font.init() + + +def attack(soldiers, soldier_index, soldier_counter): + if len(soldiers) > 0: + if soldier_index >= len(soldiers): + soldier_index = 0 + soldier = soldiers[soldier_index] + soldier_index += 1 + if soldier.ready_to_dispatch and isinstance(soldier, (Archer, SwordsMan)): + soldier.deploy = True + soldier.run = True + if isinstance(soldier, Archer): + if not soldier.shooting: + soldier.load_run() + else: + soldier.ready_to_shoot() + else: + soldier.load_run() + soldier_counter -= 1 + if soldier_counter <= 0: + soldier_counter = 0 + return soldier_index, soldier_counter + + +def run_to_mine(workers): + for worker in workers and workers: + if worker.ready_to_dispatch and not worker.digging: + worker.deploy = True + worker.run = True + worker.run_to_mine = True + worker.digging = False + worker.repairing = False + worker.run_to_wall = False + worker.to_mine() + + +def at_mine(workers): + if all(worker.digging for worker in workers): + return False + else: + return True + + +def run_to_wall(workers): + for worker in workers and workers: + # if worker.ready_to_dispatch and worker.player.castle.wall.health < Wall.MAX_HEALTH: + if worker.ready_to_dispatch and not worker.repairing and worker.player.castle.wall.health < Wall.MAX_HEALTH: + worker.deploy = True + worker.run = True + worker.digging = False + worker.repairing = False + worker.run_to_mine = False + worker.run_to_wall = True + worker.to_wall() + + +def at_wall(workers): + if all(worker.repairing for worker in workers): + return False + else: + return True + + +def deploy_all(soldiers): + if all(soldier.deploy for soldier in soldiers): + return False + else: + return True + + +def deploy(units): + for i, soldier in enumerate(units): + if soldier.deploy: + if soldier.run: + soldier.move() + soldier.update() + + +def check_added(units, num_units, count_units, total): + if isinstance(units, list): + for i in range(len(units)): + if isinstance(units[i], (Archer, SwordsMan, Worker)): + if units[i].ready_to_dispatch and not units[i].added: + units[i].added = True + num_units += 1 + count_units -= 1 + if total is not None: + total += 1 + return num_units, count_units, total + + +def add_to_queue(military_unit, units, count_soldiers, player_type): + if isinstance(units, list): + for i in range(count_soldiers): + match player_type: + case "a_p1": + soldier = Archer("p1") + if len(units) > 0: + prev_soldier = units[len(units) - 1] + if prev_soldier.ready_to_dispatch and prev_soldier.added: + units.append(soldier) + military_unit.append(soldier) + else: + units.append(soldier) + military_unit.append(soldier) + + case "a_p2": + soldier = Archer("p2") + if len(units) > 0: + prev_soldier = units[len(units) - 1] + if prev_soldier.ready_to_dispatch and prev_soldier.added: + units.append(soldier) + military_unit.append(soldier) + else: + units.append(soldier) + military_unit.append(soldier) + + case "s_p1": + soldier = SwordsMan("p1") + if len(units) > 0: + prev_soldier = units[len(units) - 1] + if prev_soldier.ready_to_dispatch and prev_soldier.added: + units.append(soldier) + military_unit.append(soldier) + else: + units.append(soldier) + military_unit.append(soldier) + + case "s_p2": + soldier = SwordsMan("p2") + if len(units) > 0: + prev_soldier = units[len(units) - 1] + if prev_soldier.ready_to_dispatch and prev_soldier.added: + units.append(soldier) + military_unit.append(soldier) + else: + units.append(soldier) + military_unit.append(soldier) + case "w_p1": + worker = Worker(military_unit) + if len(units) > 0: + prev_worker = units[len(units) - 1] + if prev_worker.ready_to_dispatch and prev_worker.added: + units.append(worker) + else: + units.append(worker) + case "w_p2": + worker = Worker(military_unit) + if len(units) > 0: + prev_worker = units[len(units) - 1] + if prev_worker.ready_to_dispatch and prev_worker.added: + units.append(worker) + else: + units.append(worker) + + +def collide(soldiers, target_unit): + if isinstance(soldiers, list): + for soldier in soldiers: + if isinstance(soldier, Archer): + if soldier.range.colliderect( + target_unit.range if not isinstance(target_unit, + Wall) else target_unit.rect): + soldier.run = False + soldier.ready_to_shoot() + if soldier.shooting: + soldier.move_arrows(target_unit) + elif isinstance(soldier, SwordsMan): + if soldier.rect.colliderect(target_unit.rect): + soldier.run = False + soldier.attack() + if soldier.attacking: + soldier.target_unit = target_unit + + +def tower_collide(tower, target_unit): + if abs(tower.rect.centerx - target_unit.rect.centerx) <= tower.RANGE and not isinstance(target_unit, Wall): + tower.attacking = True + tower.resting = False + else: + tower.attacking = False + tower.resting = True + + +def training(units): + if isinstance(units, list): + for i in range(len(units)): + if units[i].ready_to_dispatch is False: + units[i].train() + + +def check_dead(soldiers): + for i, soldier in enumerate(soldiers): + if isinstance(soldier, (Archer, SwordsMan)): + if soldier.dead and soldier.rest(3): + del soldiers[i] + + +def check_health(soldiers): + for i, soldier in enumerate(soldiers): + if isinstance(soldier, (Archer, SwordsMan)): + if soldier.health <= 0: + soldier.run = False + if isinstance(soldier, Archer): + soldier.arrows.clear() + soldier.shooting = False + soldier.attacking = False + soldier.falling = True + + soldier.load_dead() + + +def check_worker_action(units): + for i, unit in enumerate(units): + if unit.digging: + unit.dig() + elif unit.repairing: + unit.repair() + + +def draw(units, screen): + for i in range(len(units)): + if units[i].ready_to_dispatch: + units[i].draw(screen) + + +def loadImage(image_map, num_img, flip): + images = {} + for i in range(num_img): + image = pg.image.load(image_map['root'] + str(i) + image_map['extension']) + if flip: + image = pg.transform.flip(image, True, False) + images[i] = image + return images + + +def redraw_window(player1, player2, game_over, screen, winner, pause): + screen.blit(BG, (0, 0)) + + # player1 labels + ready_archers_label_1 = DEFAULT_FONT.render(f"Ready Archers: {player1.num_archer}", True, (255, 0, 255)) + ready_swordsmen_label_1 = DEFAULT_FONT.render(f"| Ready Swordsmen: {player1.num_swordsmen}", True, + (255, 0, 255)) + ready_workers_label_1 = DEFAULT_FONT.render(f" | Total Workers: {player1.num_workers}", True, (255, 0, 255)) + + archers_in_training_1 = DEFAULT_FONT.render(f"Issued archers: {player1.count_archer}", True, (255, 0, 255)) + swordsmen_in_training_1 = DEFAULT_FONT.render(f"| Issued swordsmen: {player1.count_sword}", True, (255, 0, 255)) + workers_in_training_1 = DEFAULT_FONT.render(f" | Issued workers: {player1.count_workers}", True, (255, 0, 255)) + player1_resource_label = RESOURCE_FONT.render(f"Resource: {player1.player_resource}", True, (255, 0, 0)) + tot_soldiers_p1_label = DEFAULT_FONT.render(f"Total number of soldiers: {player1.total_soldiers}", + 1, (0, 0, 0)) + screen.blit(player1_resource_label, (10, 5)) + screen.blit(ready_archers_label_1, (10, 35)) + screen.blit(ready_swordsmen_label_1, (ready_archers_label_1.get_width() + 15, 35)) + screen.blit(archers_in_training_1, (10, 45)) + screen.blit(swordsmen_in_training_1, (archers_in_training_1.get_width() + 15, 45)) + screen.blit(ready_workers_label_1, + (ready_archers_label_1.get_width() + ready_swordsmen_label_1.get_width() + 15, 35)) + screen.blit(workers_in_training_1, + (archers_in_training_1.get_width() + swordsmen_in_training_1.get_width() + 15, 45)) + screen.blit(tot_soldiers_p1_label, (10, 60)) + # player 2 labels + ready_archers_label_2 = DEFAULT_FONT.render(f"Ready Archers: {player2.num_archer}", True, (255, 0, 255)) + ready_swordsmen_label_2 = DEFAULT_FONT.render(f"| Ready Swordsmen: {player2.num_swordsmen}", True, + (255, 0, 255)) + ready_workers_label_2 = DEFAULT_FONT.render(f" | Total Workers: {player2.num_workers}", True, (255, 0, 255)) + + archers_in_training_2 = DEFAULT_FONT.render(f"Issued archers: {player2.count_archer}", True, (255, 0, 255)) + swordsmen_in_training_2 = DEFAULT_FONT.render(f"| Issued swordsmen: {player2.count_sword}", True, (255, 0, 255)) + workers_in_training_2 = DEFAULT_FONT.render(f" | Issued workers: {player2.count_workers}", True, (255, 0, 255)) + + player2_resource_label = RESOURCE_FONT.render(f"Resource: {player2.player_resource}", True, (255, 0, 0)) + tot_soldiers_p2_label = DEFAULT_FONT.render(f"Total number of soldiers: {player2.total_soldiers}", + 1, (0, 0, 0)) + screen.blit(player2_resource_label, (SCREEN_WIDTH - player2_resource_label.get_width(), 5)) + screen.blit(ready_archers_label_2, ( + SCREEN_WIDTH - ready_archers_label_2.get_width() - ready_swordsmen_label_2.get_width() - ready_workers_label_2.get_width() - 20, + 35)) + screen.blit(ready_swordsmen_label_2, + (SCREEN_WIDTH - ready_archers_label_2.get_width() - ready_swordsmen_label_2.get_width() - 20, 35)) + screen.blit(ready_workers_label_2, (SCREEN_WIDTH - ready_archers_label_2.get_width() - 20, 35)) + screen.blit(archers_in_training_2, ( + SCREEN_WIDTH - archers_in_training_2.get_width() - swordsmen_in_training_2.get_width() - workers_in_training_2.get_width() - 10, + 45)) + screen.blit(swordsmen_in_training_2, + (SCREEN_WIDTH - archers_in_training_2.get_width() - swordsmen_in_training_2.get_width() - 20, 45)) + screen.blit(workers_in_training_2, (SCREEN_WIDTH - archers_in_training_2.get_width() - 20, 45)) + screen.blit(tot_soldiers_p2_label, (SCREEN_WIDTH - tot_soldiers_p2_label.get_width() - 5, 60)) + + player1.draw(screen) + player2.draw(screen) + if game_over: + game_over_label = GAME_OVER_FONT.render(f"{winner} player wins", True, (0, 0, 0)) + game_over_label_rect = game_over_label.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 3)) + screen.blit(game_over_label, game_over_label_rect) + press_any_key_label = PRESS_ANY_KEY_FONT.render("Press any key to start over", True, (0, 0, 0)) + press_any_keyRect = press_any_key_label.get_rect(center=(SCREEN_WIDTH // 2, (SCREEN_HEIGHT // 3) + 50)) + screen.blit(press_any_key_label, press_any_keyRect) + if pause: + pause_label = PRESS_ANY_KEY_FONT.render(f"Game has been pause, press space to resume o R to restart", True, + (0, 100, 0)) + pause_label_rect = pause_label.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 3)) + screen.blit(pause_label, pause_label_rect) + + pg.display.update() diff --git a/main.py b/main.py index 97ff754..bc0bd8f 100644 --- a/main.py +++ b/main.py @@ -1,55 +1,85 @@ -import time +import sys import pygame as pg -import random -from objects.players.Archer import Archer +from implementable import Functions +from implementable.Functions import redraw_window +from objects.Constants import SCREEN_WIDTH, SCREEN_HEIGHT, PLAYER1_KEY_COMMANDS, PLAYER2_KEY_COMMANDS +from objects.Inputs import Inputs +from objects.players.Player import Player -WIDTH, HEIGHT = 1000, 250 +pg.init() -INITIAL_RESOURCE = 1000 - -screen = pg.display.set_mode((WIDTH, HEIGHT)) +screen = pg.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) clock = pg.time.Clock() -BG = pg.transform.scale(pg.image.load("sprites/background/BG.jpg"), (WIDTH, HEIGHT)) + +player1, player2 = None, None def main(): - archers = [] + global player1, player2 + game_over = False + restarted = False + winner = None + pause = False - player1_resource = INITIAL_RESOURCE - player2_resource = INITIAL_RESOURCE + player1_inputs = Inputs(PLAYER1_KEY_COMMANDS) + player2_inputs = Inputs(PLAYER2_KEY_COMMANDS) - def redraw_window(): - screen.blit(BG, (0, 0)) + player1 = Player("p1", player1_inputs) + player2 = Player("p2", player2_inputs) - for archer in archers: - archer.draw(screen) + player1.opponent = player2 + player2.opponent = player1 - pg.display.update() + loop = True - loop = 1 while loop: - clock.tick(10) - redraw_window() - keys = pg.key.get_pressed() - - if keys[pg.K_t]: - archer = Archer(100, random.randrange(10, 30), 165, False, screen) - player1_resource -= archer.COST - archers.append(archer) - if keys[pg.K_d]: - for archer in archers: - archer.deploy = True + + clock.tick(60) + redraw_window(player1, player2, game_over, screen, winner, pause) for event in pg.event.get(): - if event.type == pg.QUIT: - loop = 0 - for archer in archers: - if archer.deploy is True: - archer.move() - archer.update() + if event.type == pg.QUIT: + sys.exit() + if event.type == pg.KEYDOWN: + if not pause: + player1.key_events(event.key) + player2.key_events(event.key) + if event.key == pg.K_SPACE: + pause = not pause + if event.key == pg.K_r and pause: + restarted = True + pause = False + if game_over and not restarted: + if event.type == pg.KEYDOWN: + restarted = True + game_over = False + + if not game_over: + if restarted: + player1 = Player("p1", player1_inputs) + player2 = Player("p2", player2_inputs) + player1.opponent = player2 + player2.opponent = player1 + winner = None + restarted = False + elif not restarted and not pause: + game_over = player1.update(game_over) + game_over = player2.update(game_over) + elif pause: + pass + + elif game_over: + player1.soldiers.clear() + player1.workers.clear() + player2.soldiers.clear() + player2.workers.clear() + if player1.castle.wall.health <= 0: + winner = "BLUE" + elif player2.castle.wall.health <= 0: + winner = "RED" if __name__ == '__main__': diff --git a/objects/Arrow.py b/objects/Arrow.py index 31683a2..ddef91f 100644 --- a/objects/Arrow.py +++ b/objects/Arrow.py @@ -1,12 +1,49 @@ -from abc import abstractmethod, ABC +import math +import pygame as pg -class Arrow(ABC): - def __init__(self, arrow_speed, position_X, position_Y): - self.arrow_speed = arrow_speed - self.position_X = position_X - self.position_Y = position_Y - @abstractmethod - def hit(self, position_X, position_Y, target_X, target_Y ): - ... \ No newline at end of file +class Arrow: + SPEED = 5 + + def __init__(self, position_X, position_Y, image_map, player, angle): + self.shoot = False + self.x = position_X + self.y = position_Y + self.a_count = 0 + self.speedX = self.SPEED * math.cos(angle) if player else -self.SPEED * math.cos(angle) + self.speedY = self.SPEED * math.sin(angle) + if angle == 0: + self.image_type = 'arrow_hor/arrowhor-' + elif 0 < angle <= ((math.pi / 2) - (math.pi / 6)): + self.image_type = 'arrow_diag/arrowdiag-' + else: + self.image_type = 'arrow_vert/arrowvert-' + + self.animation = self.load_arrows(image_map['root'], image_map['extension'], 2) + self.image = self.animation[0] + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + def load_arrows(self, img_root, img_extension, num_img): + images = {} + for i in range(num_img): + self.image = pg.image.load(img_root + self.image_type + str(i) + img_extension) + images[i] = self.image + return images + + def update_arrow(self): + self.a_count += 0.2 + if self.a_count >= 1: + self.a_count = 0 + self.image = self.animation[int(self.a_count)] + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + def move_arrow(self): + self.update_arrow() + if self.shoot: + self.x += self.speedX + self.y += self.speedY + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + def draw_arrows(self, screen): + screen.blit(self.image, self.rect) diff --git a/objects/Barracks.py b/objects/Barracks.py new file mode 100644 index 0000000..d60de3b --- /dev/null +++ b/objects/Barracks.py @@ -0,0 +1,10 @@ +from objects.Constants import SCREEN_HEIGHT, GROUND_HEIGHT + + +class Barracks: + def __init__(self, img, barrack_x): + self.img = img + self.rect = self.img.get_rect(midbottom=(barrack_x, SCREEN_HEIGHT - GROUND_HEIGHT)) + + def draw(self, screen): + screen.blit(self.img, self.rect) diff --git a/objects/Castle.py b/objects/Castle.py new file mode 100644 index 0000000..1ff98f5 --- /dev/null +++ b/objects/Castle.py @@ -0,0 +1,28 @@ +from objects.Barracks import Barracks +from objects.Constants import WALL_POS, BARRACKS_POS, MINE_POS, SCREEN_WIDTH, P1_SPRITES, P2_SPRITES +from objects.Mine import Mine +from objects.Tower import Tower +from objects.Wall import Wall + + +class Castle: + def __init__(self, player): + wall_x = WALL_POS if player.player_type == "p1" else SCREEN_WIDTH - WALL_POS + barracks_x = BARRACKS_POS if player.player_type == "p1" else SCREEN_WIDTH - BARRACKS_POS + mine_x = MINE_POS if player.player_type == "p1" else SCREEN_WIDTH - MINE_POS + tower_x = WALL_POS if player.player_type == "p1" else SCREEN_WIDTH - WALL_POS + building_sprites = P1_SPRITES if player.player_type == "p1" else P2_SPRITES + + self.wall = Wall(building_sprites['building']['wall'], wall_x) + self.barracks = Barracks(building_sprites['building']['barracks'], barracks_x) + self.mine = Mine(building_sprites['building']['mine'], mine_x) + self.tower = Tower(building_sprites['building']['tower'], tower_x, player.player_type) + + def update(self, target): + self.tower.update(target) + + def draw(self, screen): + self.mine.draw(screen) + self.barracks.draw(screen) + self.tower.draw(screen) + self.wall.draw(screen) diff --git a/objects/Constants.py b/objects/Constants.py new file mode 100644 index 0000000..6932d6b --- /dev/null +++ b/objects/Constants.py @@ -0,0 +1,95 @@ +import pygame + +pygame.init() + +PLAYER_START_RESOURCES = 100 + +PLAYER1_KEY_COMMANDS = { + "worker_train": "q", + "sword_train": "w", + "archer_train": "e", + "to_mine": "a", + "to_wall": "s", + "sword_attack": "d", + "archer_attack": "f", + "unleash": "z" +} + +PLAYER2_KEY_COMMANDS = { + "worker_train": "p", + "sword_train": "o", + "archer_train": "i", + "to_mine": "l", + "to_wall": "k", + "sword_attack": "j", + "archer_attack": "h", + "unleash": "m" +} + +# ARCHER CONTANTS +ARCHER_COST = 5 +ARCHER_TRAIN = 2 +ARCHER_SPEED = 2 +ARCHER_DAMAGE = 20 +ARCHER_RANGE = 100 +ARCHER_REST = 2 +ARCHER_HEALTH = 100 + +# SWORD CONTANTS +SWORD_COST = 5 +SWORD_TRAIN = 2 +SWORD_SPEED = 2 +SWORD_DAMAGE = 20 +SWORD_RANGE = 10 +SWORD_REST = 2 + +# WORKER CONTANTS +WORKER_COST = 5 +WORKER_TRAIN = 2 +WORKER_SPEED = 1 +WORKER_PROD = 3 +WORKER_REPAIR = 10 + +# GLOBAL +SCREEN_WIDTH = 1000 +SCREEN_HEIGHT = 300 +GROUND_HEIGHT = 70 +WALL_POS = 180 +WALL_WIDTH = 62 +WALL_HEIGHT = 80 +WALL_HEALTH = 1000 +MINE_POS = 40 +MINE_WIDTH = 58 +MINE_HEIGHT = 37 +BARRACKS_POS = 106 +BARRACKS_WIDTH = 62 +BARRACKS_HEIGHT = 50 +TOWER_HEIGHT = 160 + +# SPRITE MAPS + +P1_SPRITES = {"building": + { + "barracks": pygame.image.load("./sprites/player1/building/barracks.png"), + "mine": pygame.image.load("./sprites/player1/building/mine.png"), + "tower": pygame.image.load("./sprites/player1/building/tower.png"), + "wall": pygame.image.load("./sprites/player1/building/wall.png") + } +} + +P2_SPRITES = {"building": + { + "barracks": pygame.image.load("./sprites/player2/building/barracks.png"), + "mine": pygame.image.load("./sprites/player2/building/mine.png"), + "tower": pygame.image.load("./sprites/player2/building/tower.png"), + "wall": pygame.image.load("./sprites/player2/building/wall.png") + } +} + +BG = pygame.transform.scale(pygame.image.load("sprites/background/BG.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT)) + +# Fonts +DEFAULT_FONT = pygame.font.SysFont("comicsans", 12) +RESOURCE_FONT = pygame.font.SysFont("comicsans", 20) +GAME_OVER_FONT = pygame.font.Font('font/pixel.ttf', 40) +PRESS_ANY_KEY_FONT = pygame.font.Font('font/pixel.ttf', 25) \ No newline at end of file diff --git a/objects/GameObject.py b/objects/GameObject.py deleted file mode 100644 index dd673e2..0000000 --- a/objects/GameObject.py +++ /dev/null @@ -1,14 +0,0 @@ -from abc import ( - ABC, - abstractmethod -) - -import pygame as pg - - -class GameObject(ABC): - def __init__(self, health, x, y): - super().__init__() - self.health = health - self.x = x - self.y = y diff --git a/objects/Inputs.py b/objects/Inputs.py new file mode 100644 index 0000000..dfa214a --- /dev/null +++ b/objects/Inputs.py @@ -0,0 +1,13 @@ +import pygame as pg + + +class Inputs: + def __init__(self, inputs): + self.worker_train_key = pg.key.key_code(inputs['worker_train']) + self.sword_train_key = pg.key.key_code(inputs['sword_train']) + self.archer_train_key = pg.key.key_code(inputs['archer_train']) + self.to_mine_key = pg.key.key_code(inputs['to_mine']) + self.to_wall_key = pg.key.key_code(inputs['to_wall']) + self.sword_attack_key = pg.key.key_code(inputs['sword_attack']) + self.archer_attack_key = pg.key.key_code(inputs['archer_attack']) + self.unleash_key = pg.key.key_code(inputs['unleash']) diff --git a/objects/Mine.py b/objects/Mine.py new file mode 100644 index 0000000..6eb46d2 --- /dev/null +++ b/objects/Mine.py @@ -0,0 +1,10 @@ +from objects.Constants import SCREEN_HEIGHT, GROUND_HEIGHT + + +class Mine: + def __init__(self, img, mine_x): + self.img = img + self.rect = self.img.get_rect(midbottom=(mine_x, SCREEN_HEIGHT - GROUND_HEIGHT)) + + def draw(self, screen): + screen.blit(self.img, self.rect) diff --git a/objects/PlayerArrow.py b/objects/PlayerArrow.py deleted file mode 100644 index f1c2b23..0000000 --- a/objects/PlayerArrow.py +++ /dev/null @@ -1,7 +0,0 @@ -from objects.Arrow import Arrow - - -class PlayerArrow(Arrow): - def hit(self, x, y, t_X, t_Y): - ... - diff --git a/objects/Tower.py b/objects/Tower.py new file mode 100644 index 0000000..ac7008e --- /dev/null +++ b/objects/Tower.py @@ -0,0 +1,67 @@ +import math +import time + +import pygame as pg + +from objects.Arrow import Arrow +from objects.Constants import GROUND_HEIGHT, SCREEN_HEIGHT + + +class Tower: + RANGE = 200 + TOWER_HIT = 10 + TOWER_REST = 1 + + PLAYER1_ARROW = {"root": f"sprites/player1/bow/", "extension": ".png"} + PLAYER2_ARROW = {"root": f"sprites/player2/bow/", "extension": ".png"} + + def __init__(self, img, tower_x, player_type): + self.start_action = 0 + self.current_time = 0 + self.target_unit = None + self.img = img + self.player_type = True if player_type == "p1" else False + self.rect = self.img.get_rect(midbottom=(tower_x, SCREEN_HEIGHT - GROUND_HEIGHT)) + self.arrows = [] + self.resting = True + self.attacking = False + + self.range = pg.Rect(0, 0, self.rect.w + (self.RANGE * 2), self.rect.h) + self.range.midbottom = self.rect.midbottom + + def update(self, target): + if self.attacking and not self.resting: + if self.rest(1): + x = abs(self.rect.centerx - target.rect.centerx) + y = target.rect.centery - self.rect.top + arrow_angle = math.atan(y / x) + arrow = Arrow(self.rect.centerx, self.rect.top, + self.PLAYER1_ARROW if self.player_type else self.PLAYER2_ARROW, + self.player_type, arrow_angle) + arrow.shoot = True + self.start_action = time.time() + self.arrows.append(arrow) + + self.move_arrows(target) + + def rest(self, rest_amount): + if rest_amount > (self.current_time - self.start_action): + self.current_time = time.time() + return False + else: + return True + + def move_arrows(self, obj): + self.target_unit = obj + for i, arrow in enumerate(self.arrows): + arrow.move_arrow() + if arrow.rect.colliderect(obj.rect) and self.arrows: + obj.health -= self.TOWER_HIT + del self.arrows[i] + if arrow.y > SCREEN_HEIGHT - GROUND_HEIGHT: + del self.arrows[i] + + def draw(self, screen): + screen.blit(self.img, self.rect) + for arrow in self.arrows: + arrow.draw_arrows(screen) diff --git a/objects/Wall.py b/objects/Wall.py new file mode 100644 index 0000000..9cda9f5 --- /dev/null +++ b/objects/Wall.py @@ -0,0 +1,30 @@ +import pygame as pg + +from objects.Constants import GROUND_HEIGHT, SCREEN_HEIGHT, WALL_HEALTH + + +class Wall: + MAX_HEALTH = WALL_HEALTH + + def __init__(self, img, wall_x): + self.img = img + self.x = wall_x + self.rect = self.img.get_rect(midbottom=(wall_x, SCREEN_HEIGHT - GROUND_HEIGHT)) + self.health = self.MAX_HEALTH + self.dead = self.health <= 0 + self.hb_width = 50 + + def draw_health_bar(self, screen): + red_hb_rect = pg.Rect(0, 0, self.hb_width, 6) + red_hb_rect.center = (self.rect.centerx, (self.rect.top // 2) - 15) + pg.draw.rect(screen, (255, 0, 0), red_hb_rect) + + green_hb_rect = pg.Rect(0, 0, self.hb_width * (self.health / self.MAX_HEALTH), 6) + green_hb_rect.topleft = red_hb_rect.topleft + pg.draw.rect(screen, (0, 255, 0), green_hb_rect) + + def draw(self, screen): + screen.blit(self.img, self.rect) + + if self.health < self.MAX_HEALTH: + self.draw_health_bar(screen) diff --git a/objects/players/Archer.py b/objects/players/Archer.py index 19b528f..b328a6a 100644 --- a/objects/players/Archer.py +++ b/objects/players/Archer.py @@ -1,42 +1,196 @@ -import os +import random +import time + import pygame as pg -from objects.players.Player import Player +from implementable import Functions +from objects.Arrow import Arrow +from objects.Constants import BARRACKS_POS, SCREEN_WIDTH, GROUND_HEIGHT, SCREEN_HEIGHT, ARCHER_SPEED, ARCHER_DAMAGE, \ + ARCHER_TRAIN, ARCHER_RANGE, ARCHER_REST, ARCHER_COST, ARCHER_HEALTH +from objects.Wall import Wall -class Archer(Player, pg.sprite.Sprite): +class Archer: + TRAIN_TIME = ARCHER_TRAIN + RANGE = ARCHER_RANGE + HIT_DAMAGE = ARCHER_DAMAGE + REST = ARCHER_REST + COST = ARCHER_COST + SPEED = ARCHER_SPEED + MAX_HEALTH = ARCHER_HEALTH - TRAIN_TURNS = 3 - RANGE = 10 - HIT_DAMAGE = 3 - REST = 1 - COST = 3 - SPEED = 5 + PLAYER1_READY = "sprites/player1/bow/ready.png" + PLAYER2_READY = "sprites/player2/bow/ready.png" + PLAYER1_RUN = {"root": "sprites/player1/bow/run/run-", "extension": ".png"} + PLAYER2_RUN = {"root": "sprites/player2/bow/run/run-", "extension": ".png"} + PLAYER1_SHOOT = {"root": "sprites/player1/bow/shoot/shoot-", "extension": ".png"} + PLAYER2_SHOOT = {"root": "sprites/player2/bow/shoot/shoot-", "extension": ".png"} + PLAYER1_FALLEN = {"root": "sprites/player1/bow/fallen/fallen-", "extension": ".png"} + PLAYER2_FALLEN = {"root": "sprites/player2/bow/fallen/fallen-", "extension": ".png"} + PLAYER1_ARROW = {"root": "sprites/player1/bow/", "extension": ".png"} + PLAYER2_ARROW = {"root": "sprites/player2/bow/", "extension": ".png"} - def __init__(self, health, x, y, deploy, screen): - super().__init__(health, x, y, deploy) + def __init__(self, player_type): + self.hb_width = 15 + self.target_unit = None + self.animation = None + self.deploy = False + self.ready_to_dispatch = False + self.health = Archer.MAX_HEALTH + self.falling = False + self.run = False + self.wait = True + self.dead = False + self.enemy_killed = False self.a_count = 0 - self.deploy = deploy - self.animation = self.loadImage() - self.rect = self.image.get_rect() - self.draw(screen) - - def loadImage(self): - images = {} - for i in range(11): - print(str(i)) - self.image = pg.image.load("sprites/player1/bow/run/run-" + str(i) + ".png") - images[i] = self.image - return images + self.x = BARRACKS_POS if player_type == "p1" else SCREEN_WIDTH - BARRACKS_POS + self.y = SCREEN_HEIGHT - GROUND_HEIGHT + self.image = pg.image.load(Archer.PLAYER1_READY if player_type == "p1" else Archer.PLAYER2_READY) + self.current_time = 0 + self.start_action = 0 + self.shooting = False + self.added = False + self.player_type = player_type + self.arrows = [] + + self.start_time = time.time() + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + self.range = pg.Rect(0, 0, self.rect.w + (self.RANGE * 2), self.rect.h) + self.range.midbottom = self.rect.midbottom + + def load_run(self): + if self.run: + match self.player_type: + case "p1": + self.animation = Functions.loadImage(self.PLAYER1_RUN, 11, False) + case "p2": + self.animation = Functions.loadImage(self.PLAYER2_RUN, 11, False) + + def ready_to_shoot(self): + if not self.falling and not self.dead: + if not self.run and not self.shooting: + self.start_action = time.time() + match self.player_type: + case "p1": + self.image = pg.image.load(self.PLAYER1_READY) + if not self.shooting: + self.shooting = True + self.a_count = 0 + self.load_shoot(self.PLAYER1_SHOOT) + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + case "p2": + self.image = pg.image.load(self.PLAYER2_READY) + if not self.shooting: + self.shooting = True + self.a_count = 0 + self.load_shoot(self.PLAYER2_SHOOT) + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + def load_dead(self): + if self.falling: + match self.player_type: + case "p1": + self.animation = Functions.loadImage(self.PLAYER1_FALLEN, 6, False) + + case "p2": + self.animation = Functions.loadImage(self.PLAYER2_FALLEN, 6, False) def update(self): - self.a_count += 1 - if self.a_count == len(self.animation): - self.a_count = 0 - self.image = self.animation[self.a_count] + self.range.midbottom = self.rect.midbottom + + if not self.dead: + if self.shooting and not self.falling and not self.run: + arrow = None + self.enemy_killed = False + + if self.rest(self.REST): + match self.player_type: + case "p1": + arrow = Arrow(self.rect.right, self.rect.centery, self.PLAYER1_ARROW, True, 0) + case "p2": + arrow = Arrow(self.rect.left, self.rect.centery, self.PLAYER2_ARROW, False, 0) + arrow.shoot = True + self.arrows.append(arrow) + self.a_count = 1 + self.image = self.animation[self.a_count] + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + self.start_action = time.time() + elif self.rest(random.randint(1, 10) * 0.1): + self.a_count = 0 + self.image = self.animation[self.a_count] + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + else: + self.image = self.animation[int(self.a_count)] + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + if not self.falling: + self.a_count += 0.2 + else: + self.a_count += 0.1 + if self.a_count > len(self.animation): + self.a_count = 0 + if self.falling and int(self.a_count) > 4: + self.dead = True + self.falling = False + if self.target_unit is not None and not isinstance(self.target_unit, Wall) and self.target_unit.dead: + self.shooting = False + self.load_run() + if self.rest(random.randint(1, 2)): + self.run = True + elif not self.enemy_killed and not self.run: + self.image = pg.image.load( + Archer.PLAYER1_READY if self.player_type == "p1" else Archer.PLAYER2_READY) def draw(self, screen): - screen.blit(self.image, (self.x, self.y)) + screen.blit(self.image, self.rect) + for arrow in self.arrows: + arrow.draw_arrows(screen) + if not self.dead and self.health < self.MAX_HEALTH: + self.draw_health_bar(screen) def move(self): - self.x += self.SPEED + if self.run: + match self.player_type: + case "p1": + self.x += Archer.SPEED + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + case "p2": + self.x -= Archer.SPEED + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + def move_arrows(self, obj): + self.target_unit = obj + for i, arrow in enumerate(self.arrows): + arrow.move_arrow() + if arrow.rect.colliderect(obj.rect) and self.arrows and obj.health > 0: + obj.health -= self.HIT_DAMAGE + del self.arrows[i] + elif obj.health <= 0: + self.enemy_killed = True + del self.arrows[i] + + def load_shoot(self, image_map): + self.animation = Functions.loadImage(image_map, 2, False) + + def rest(self, rest_amount): + if rest_amount > (self.current_time - self.start_action): + self.current_time = time.time() + return False + else: + return True + + def train(self): + if round(self.current_time - self.start_time) < self.TRAIN_TIME: + self.current_time = time.time() + else: + self.ready_to_dispatch = True + + def draw_health_bar(self, screen): + red_hb_rect = pg.Rect(self.x, self.y - 5, self.hb_width, 3) + red_hb_rect.center = (self.x, self.y - self.rect.h - 5) + pg.draw.rect(screen, (255, 0, 0), red_hb_rect) + + green_hb_rect = pg.Rect(self.x, self.y - 5, self.hb_width * (self.health / self.MAX_HEALTH), 3) + green_hb_rect.topleft = red_hb_rect.topleft + pg.draw.rect(screen, (0, 255, 0), green_hb_rect) diff --git a/objects/players/Player.py b/objects/players/Player.py index 4a988a6..d6bd91b 100644 --- a/objects/players/Player.py +++ b/objects/players/Player.py @@ -1,15 +1,161 @@ -import os -from glob import glob -import pygame as pg +import time -from objects.GameObject import GameObject +from implementable import Functions +from objects.Castle import Castle +from objects.Constants import * +from objects.Wall import Wall -class Player(GameObject): - def __init__(self, health, x, y, deploy): - super().__init__(health, x, y) - self.deploy = deploy +class Player: + def __init__(self, player_type, keys): + self.to_wall = False + self.to_mine = False + self.targeted_unit = None + self.total_soldiers = 0 + self.deploy_all = False + self.total_archer = 0 + self.swordsmen = [] + self.archers = [] + self.worker_index = 0 + self.num_workers = 0 + self.start_action = 0 + self.current_time = 0 + self.total_swords = 0 + self.swordsman_index = 0 + self.num_swordsmen = 0 + self.archer_index = 0 + self.num_archer = 0 + self.count_sword = 0 + self.count_archer = 0 + self.count_workers = 0 + self.image = None + self.keys = keys + self.player_type = player_type + self.castle = Castle(self) + self.player_resource = PLAYER_START_RESOURCES + self.a_count = 0 + self.soldiers = [] + self.workers = [] + self.opponent = None + def choose_target(self): + alive_soldiers = [soldier for soldier in self.opponent.soldiers if not soldier.dead] + if alive_soldiers: + selected_target = min(alive_soldiers, key=lambda unit: abs(self.castle.wall.rect.x - unit.x)) + self.targeted_unit = selected_target if WALL_POS <= selected_target.rect.centerx <= SCREEN_WIDTH - WALL_POS else self.opponent.castle.wall + else: + self.targeted_unit = self.opponent.castle.wall + def key_events(self, key): + if key == self.keys.archer_train_key: + if self.player_resource > 0: + self.player_resource -= ARCHER_COST + self.count_archer += 1 + else: + self.player_resource = 0 + if key == self.keys.sword_train_key: + if self.player_resource > 0: + self.player_resource -= SWORD_COST + self.count_sword += 1 + else: + self.player_resource = 0 + + if key == self.keys.archer_attack_key: + if self.num_archer > 0: + self.archer_index, self.num_archer = Functions.attack(self.archers, self.archer_index, self.num_archer) + + if key == self.keys.sword_attack_key: + if self.num_swordsmen > 0: + self.swordsman_index, self.num_swordsmen = Functions.attack(self.swordsmen, self.swordsman_index, + self.num_swordsmen) + + if key == self.keys.worker_train_key: + if self.player_resource > 0: + self.player_resource -= WORKER_COST + self.count_workers += 1 + else: + self.player_resource = 0 + + if key == self.keys.to_mine_key: + self.to_mine = True + if key == self.keys.to_wall_key: + self.to_wall = True + if key == self.keys.unleash_key: + self.deploy_all = True + self.num_archer = 0 + self.num_swordsmen = 0 + + def update(self, game_over): + self.choose_target() + + Functions.add_to_queue(self.soldiers, self.archers, self.count_archer, + "a_p1" if self.player_type == "p1" else "a_p2") + self.num_archer, self.count_archer, self.total_archer = Functions.check_added(self.archers, self.num_archer, + self.count_archer, + self.total_soldiers) + Functions.add_to_queue(self.soldiers, self.swordsmen, self.count_sword, + "s_p1" if self.player_type == "p1" else "s_p2") + self.num_swordsmen, self.count_sword, self.total_swords = Functions.check_added(self.swordsmen, + self.num_swordsmen, + self.count_sword, + self.total_soldiers) + Functions.add_to_queue(self, self.workers, self.count_workers, "w_p1" if self.player_type == "p1" else "w_p2") + self.num_workers, self.count_workers, NoneType = Functions.check_added(self.workers, + self.num_workers, + self.count_workers, + None) + + if self.count_archer <= 0: + self.count_archer = 0 + if self.count_sword <= 0: + self.count_sword = 0 + if self.count_workers <= 0: + self.count_workers = 0 + + if self.opponent.castle.wall.health <= 0: + game_over = True + if self.castle.wall.health <= Wall.MAX_HEALTH / 2: + self.to_wall = True + + self.total_soldiers = len(self.soldiers) + + if self.deploy_all: + if self.rest(0.3): + self.start_action = time.time() + self.archer_index, self.num_archer = Functions.attack(self.archers, self.archer_index, self.num_archer) + self.swordsman_index, self.num_swordsmen = Functions.attack(self.swordsmen, self.swordsman_index, + self.num_swordsmen) + self.deploy_all = Functions.deploy_all(self.soldiers) + + if self.to_mine: + Functions.run_to_mine(self.workers) + self.to_mine = Functions.at_mine(self.workers) + elif self.to_wall: + Functions.run_to_wall(self.workers) + self.to_wall = Functions.at_wall(self.workers) + + Functions.training(self.soldiers) + Functions.training(self.workers) + Functions.collide(self.soldiers, self.targeted_unit) + Functions.deploy(self.soldiers) + Functions.deploy(self.workers) + Functions.check_health(self.soldiers) + Functions.check_dead(self.soldiers) + Functions.tower_collide(self.castle.tower, self.targeted_unit) + Functions.check_worker_action(self.workers) + self.castle.update(self.targeted_unit) + return game_over + + def draw(self, screen): + self.castle.draw(screen) + Functions.draw(self.soldiers, screen) + Functions.draw(self.workers, screen) + + def rest(self, rest_amount): + if rest_amount > (self.current_time - self.start_action): + self.current_time = time.time() + return False + else: + return True diff --git a/objects/players/SwordMan.py b/objects/players/SwordMan.py deleted file mode 100644 index aa4a108..0000000 --- a/objects/players/SwordMan.py +++ /dev/null @@ -1,10 +0,0 @@ -from objects.players.Player import Player - - -class SwordMan(Player): - def __init__(self, health, x, train_turns, speed, range, hit_damage, rest, cost, resource, deploy): - super().__init__(health, x, train_turns, speed, range, hit_damage, rest, cost, resource, deploy) - - - - diff --git a/objects/players/SwordsMan.py b/objects/players/SwordsMan.py new file mode 100644 index 0000000..402e2e2 --- /dev/null +++ b/objects/players/SwordsMan.py @@ -0,0 +1,160 @@ +import time + +import pygame as pg + +from implementable import Functions +from objects.Constants import BARRACKS_POS, SCREEN_WIDTH, GROUND_HEIGHT, SCREEN_HEIGHT, SWORD_RANGE, SWORD_TRAIN, \ + SWORD_DAMAGE, SWORD_REST, SWORD_COST, SWORD_SPEED +from objects.Wall import Wall + + +class SwordsMan: + TRAIN_TURNS = SWORD_TRAIN + RANGE = SWORD_RANGE + HIT_DAMAGE = SWORD_DAMAGE + REST = SWORD_REST + COST = SWORD_COST + SPEED = SWORD_SPEED + MAX_HEALTH = 100 + PLAYER1_READY = "sprites/player1/sword/ready.png" + PLAYER2_READY = "sprites/player2/sword/ready.png" + PLAYER1_RUN = {"root": "sprites/player1/sword/run/run-", "extension": ".png"} + PLAYER2_RUN = {"root": "sprites/player2/sword/run/run-", "extension": ".png"} + PLAYER1_SHOOT = {"root": "sprites/player1/sword/attack/attack-", "extension": ".png"} + PLAYER2_SHOOT = {"root": "sprites/player2/sword/attack/attack-", "extension": ".png"} + PLAYER1_FALLEN = {"root": "sprites/player1/sword/fallen/fallen-", "extension": ".png"} + PLAYER2_FALLEN = {"root": "sprites/player2/sword/fallen/fallen-", "extension": ".png"} + + def __init__(self, player_type): + self.hb_width = 15 + self.animation = None + self.deploy = False + self.ready_to_dispatch = False + self.health = 100 + self.falling = False + self.run = False + self.dead = False + self.wait = True + self.a_count = 0 + self.x = BARRACKS_POS if player_type == "p1" else SCREEN_WIDTH - BARRACKS_POS + self.y = SCREEN_HEIGHT - GROUND_HEIGHT + self.image = pg.image.load(SwordsMan.PLAYER1_READY if player_type == "p1" else SwordsMan.PLAYER2_READY) + self.current_time = 0 + self.start_action = 0 + self.attacking = False + self.added = False + self.player_type = player_type + self.target_unit = None + + self.start_time = time.time() + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + self.range = pg.Rect(0, 0, self.rect.w + (self.RANGE * 2), self.rect.h) + self.range.midbottom = self.rect.midbottom + + def load_run(self): + if self.run: + match self.player_type: + case "p1": + self.animation = Functions.loadImage(self.PLAYER1_RUN, 11, False) + + case "p2": + self.animation = Functions.loadImage(self.PLAYER2_RUN, 11, False) + + def attack(self): + if not self.falling and not self.dead: + if not self.run and not self.attacking: + self.start_action = 0 + match self.player_type: + case "p1": + self.image = pg.image.load(self.PLAYER1_READY) + if not self.attacking: + self.attacking = True + self.a_count = 0 + self.load_attack(self.PLAYER1_SHOOT) + case "p2": + self.image = pg.image.load(self.PLAYER2_READY) + if not self.attacking: + self.attacking = True + self.a_count = 0 + self.load_attack(self.PLAYER2_SHOOT) + + def load_attack(self, image_map): + self.animation = Functions.loadImage(image_map, 8, False) + + def load_dead(self): + if self.falling: + match self.player_type: + case "p1": + self.animation = Functions.loadImage(self.PLAYER1_FALLEN, 6, False) + + case "p2": + self.animation = Functions.loadImage(self.PLAYER2_FALLEN, 6, False) + + def update(self): + self.range.midbottom = self.rect.midbottom + if not self.dead: + + if self.attacking and self.target_unit.health > 0 and self.a_count >= 6 and not self.run: + if self.rest(1): + self.target_unit.health -= SwordsMan.HIT_DAMAGE + self.a_count = 0 + self.start_action = time.time() + + else: + if self.a_count > len(self.animation): + self.a_count = 0 + if self.falling and int(self.a_count) > 4: + self.falling = False + self.dead = True + self.run = False + + self.image = self.animation[int(self.a_count)] + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + if not self.falling: + self.a_count += 0.2 + else: + self.a_count += 0.1 + if self.target_unit is not None and not isinstance(self.target_unit, Wall) and self.target_unit.dead: + self.run = True + self.attacking = False + self.load_run() + + def draw_health_bar(self, screen): + red_hb_rect = pg.Rect(self.x, self.y - 5, self.hb_width, 3) + red_hb_rect.center = (self.x, self.y - self.rect.h - 5) + pg.draw.rect(screen, (255, 0, 0), red_hb_rect) + + green_hb_rect = pg.Rect(self.x, self.y - 5, self.hb_width * (self.health / self.MAX_HEALTH), 3) + green_hb_rect.topleft = red_hb_rect.topleft + pg.draw.rect(screen, (0, 255, 0), green_hb_rect) + + def draw(self, screen): + screen.blit(self.image, self.rect) + + if not self.dead and self.health < self.MAX_HEALTH: + self.draw_health_bar(screen) + + def move(self): + if self.run: + match self.player_type: + case "p1": + self.x += self.SPEED + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + case "p2": + self.x -= self.SPEED + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + def train(self): + if round(self.current_time - self.start_time) < self.TRAIN_TURNS: + self.current_time = time.time() + else: + self.ready_to_dispatch = True + + def rest(self, rest_amount): + if rest_amount > (self.current_time - self.start_action): + self.current_time = time.time() + return False + else: + return True diff --git a/objects/players/Worker.py b/objects/players/Worker.py new file mode 100644 index 0000000..568de54 --- /dev/null +++ b/objects/players/Worker.py @@ -0,0 +1,149 @@ +import time + +import pygame as pg + +from implementable import Functions +from objects.Constants import WORKER_PROD, WORKER_REPAIR, WORKER_TRAIN, BARRACKS_POS, SCREEN_WIDTH, GROUND_HEIGHT, \ + SCREEN_HEIGHT, WORKER_SPEED, WALL_HEALTH +from objects.Wall import Wall + + +class Worker: + PRODUCTION_RATE = WORKER_PROD + REPAIR_RATE = WORKER_REPAIR + TRAINING_TIME = WORKER_TRAIN + SPEED = WORKER_SPEED + + PLAYER1_READY = "sprites/player1/worker/ready.png" + PLAYER2_READY = "sprites/player2/worker/ready.png" + PLAYER1_RUN = {"root": "sprites/player1/worker/run/run-", "extension": ".png"} + PLAYER2_RUN = {"root": "sprites/player2/worker/run/run-", "extension": ".png"} + PLAYER1_DIG = {"root": "sprites/player1/worker/dig/dig-", "extension": ".png"} + PLAYER2_DIG = {"root": "sprites/player2/worker/dig/dig-", "extension": ".png"} + PLAYER1_REPAIR = {"root": "sprites/player1/worker/repair/repair-", "extension": ".png"} + PLAYER2_REPAIR = {"root": "sprites/player2/worker/repair/repair-", "extension": ".png"} + + def __init__(self, player): + self.production_rate = self.PRODUCTION_RATE + self.repair_rate = self.REPAIR_RATE + self.speed = Worker.SPEED + self.a_count = 0 + self.start_action = 0 + self.ready_to_dispatch = False + self.added = False + self.deploy = False + self.start_time = 0 + self.current_time = 0 + self.player = player + self.x = BARRACKS_POS if player.player_type == "p1" else SCREEN_WIDTH - BARRACKS_POS + self.y = SCREEN_HEIGHT - GROUND_HEIGHT + self.run = False + self.player_type = player.player_type + self.animation = None + self.image = pg.image.load(Worker.PLAYER1_READY if self.player_type == "p1" else Worker.PLAYER2_READY) + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + self.run_to_mine = False + self.run_to_wall = False + self.digging = False + self.repairing = False + self.start_time = time.time() + + def to_wall(self): + self.animation = Functions.loadImage(self.PLAYER1_RUN if self.player_type == "p1" else self.PLAYER2_RUN, 6, + False) + self.run = True + if self.player.castle.wall.rect.centerx > self.rect.centerx: + if self.speed < 0 and self.run_to_wall: + self.speed *= -1 + + elif self.player.castle.wall.rect.centerx < self.rect.centerx: + if self.speed < 0 and self.run_to_wall: + self.speed *= -1 + + def to_mine(self): + self.animation = Functions.loadImage(self.PLAYER1_RUN if self.player_type == "p1" else self.PLAYER2_RUN, 6, + True) + self.run = True + if self.player.castle.mine.rect.centerx < self.rect.centerx: + if self.speed > 0 and self.run_to_mine: + self.speed *= -1 + elif self.speed < 0 and not self.run_to_mine: + self.speed *= -1 + + elif self.player.castle.mine.rect.centerx > self.rect.centerx: + if self.speed > 0 and self.run_to_mine: + self.speed *= -1 + elif self.speed < 0 and not self.run_to_mine: + self.speed *= -1 + def move(self): + if self.run: + match self.player_type: + case "p1": + self.x += self.speed + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + case "p2": + self.x -= self.speed + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + def dig(self): + self.animation = Functions.loadImage(self.PLAYER1_DIG if self.player_type == "p1" else self.PLAYER2_DIG, 9, + True) + + def repair(self): + self.animation = Functions.loadImage(self.PLAYER1_REPAIR if self.player_type == "p1" else self.PLAYER2_REPAIR, + 4, + False) + + def update(self): + + if self.rect.collidepoint(self.player.castle.mine.rect.centerx, + self.player.castle.mine.rect.centery) and not self.digging: + self.run = False + self.digging = True + self.repairing = False + self.run_to_mine = False + + elif self.rect.colliderect(self.player.castle.wall.rect) and not self.repairing: + self.run = False + self.digging = False + self.repairing = True + self.run_to_wall = False + + if self.digging and not self.run and self.a_count >= 8: + if self.rest(1): + self.player.player_resource += self.production_rate + self.a_count = 0 + self.start_action = time.time() + + elif self.repairing and not self.run and self.a_count >= 3: + if self.rest(1): + self.a_count = 0 + if self.player.castle.wall.health < Wall.MAX_HEALTH: + self.player.castle.wall.health += self.repair_rate + self.start_action = time.time() + else: + if self.run: + self.a_count += 0.1 + else: + self.a_count += 0.2 + if self.a_count > len(self.animation): + self.a_count = 0 + self.image = self.animation[int(self.a_count)] + self.rect = self.image.get_rect(midbottom=(self.x, self.y)) + + def draw(self, screen): + screen.blit(self.image, self.rect) + + def train(self): + if round(self.current_time - self.start_time) < self.TRAINING_TIME: + self.current_time = time.time() + else: + self.ready_to_dispatch = True + + def rest(self, rest_amount): + if rest_amount > (self.current_time - self.start_action): + self.current_time = time.time() + return False + else: + return True diff --git a/sprites/player1/bow/arrowdiag-0.png b/sprites/player1/bow/arrow_diag/arrowdiag-0.png similarity index 100% rename from sprites/player1/bow/arrowdiag-0.png rename to sprites/player1/bow/arrow_diag/arrowdiag-0.png diff --git a/sprites/player1/bow/arrowdiag-1.png b/sprites/player1/bow/arrow_diag/arrowdiag-1.png similarity index 100% rename from sprites/player1/bow/arrowdiag-1.png rename to sprites/player1/bow/arrow_diag/arrowdiag-1.png diff --git a/sprites/player1/bow/arrowhor-0.png b/sprites/player1/bow/arrow_hor/arrowhor-0.png similarity index 100% rename from sprites/player1/bow/arrowhor-0.png rename to sprites/player1/bow/arrow_hor/arrowhor-0.png diff --git a/sprites/player1/bow/arrowhor-1.png b/sprites/player1/bow/arrow_hor/arrowhor-1.png similarity index 100% rename from sprites/player1/bow/arrowhor-1.png rename to sprites/player1/bow/arrow_hor/arrowhor-1.png diff --git a/sprites/player1/bow/arrowvert-0.png b/sprites/player1/bow/arrow_vert/arrowvert-0.png similarity index 100% rename from sprites/player1/bow/arrowvert-0.png rename to sprites/player1/bow/arrow_vert/arrowvert-0.png diff --git a/sprites/player1/bow/arrowvert-1.png b/sprites/player1/bow/arrow_vert/arrowvert-1.png similarity index 100% rename from sprites/player1/bow/arrowvert-1.png rename to sprites/player1/bow/arrow_vert/arrowvert-1.png diff --git a/sprites/player1/bow/fallen-2.png b/sprites/player1/bow/fallen/fallen-0.png similarity index 100% rename from sprites/player1/bow/fallen-2.png rename to sprites/player1/bow/fallen/fallen-0.png diff --git a/sprites/player1/bow/fallen-3.png b/sprites/player1/bow/fallen/fallen-1.png similarity index 100% rename from sprites/player1/bow/fallen-3.png rename to sprites/player1/bow/fallen/fallen-1.png diff --git a/sprites/player1/bow/fallen-0.png b/sprites/player1/bow/fallen/fallen-2.png similarity index 100% rename from sprites/player1/bow/fallen-0.png rename to sprites/player1/bow/fallen/fallen-2.png diff --git a/sprites/player1/bow/fallen-1.png b/sprites/player1/bow/fallen/fallen-3.png similarity index 100% rename from sprites/player1/bow/fallen-1.png rename to sprites/player1/bow/fallen/fallen-3.png diff --git a/sprites/player1/bow/fallen-4.png b/sprites/player1/bow/fallen/fallen-4.png similarity index 100% rename from sprites/player1/bow/fallen-4.png rename to sprites/player1/bow/fallen/fallen-4.png diff --git a/sprites/player1/bow/fallen-5.png b/sprites/player1/bow/fallen/fallen-5.png similarity index 100% rename from sprites/player1/bow/fallen-5.png rename to sprites/player1/bow/fallen/fallen-5.png diff --git a/sprites/player1/bow/shoot-0.png b/sprites/player1/bow/shoot/shoot-0.png similarity index 100% rename from sprites/player1/bow/shoot-0.png rename to sprites/player1/bow/shoot/shoot-0.png diff --git a/sprites/player1/bow/shoot-1.png b/sprites/player1/bow/shoot/shoot-1.png similarity index 100% rename from sprites/player1/bow/shoot-1.png rename to sprites/player1/bow/shoot/shoot-1.png diff --git a/sprites/player1/sword/attack-0.png b/sprites/player1/sword/attack/attack-0.png similarity index 100% rename from sprites/player1/sword/attack-0.png rename to sprites/player1/sword/attack/attack-0.png diff --git a/sprites/player1/sword/attack-1.png b/sprites/player1/sword/attack/attack-1.png similarity index 100% rename from sprites/player1/sword/attack-1.png rename to sprites/player1/sword/attack/attack-1.png diff --git a/sprites/player1/sword/attack-2.png b/sprites/player1/sword/attack/attack-2.png similarity index 100% rename from sprites/player1/sword/attack-2.png rename to sprites/player1/sword/attack/attack-2.png diff --git a/sprites/player1/sword/attack-3.png b/sprites/player1/sword/attack/attack-3.png similarity index 100% rename from sprites/player1/sword/attack-3.png rename to sprites/player1/sword/attack/attack-3.png diff --git a/sprites/player1/sword/attack-4.png b/sprites/player1/sword/attack/attack-4.png similarity index 100% rename from sprites/player1/sword/attack-4.png rename to sprites/player1/sword/attack/attack-4.png diff --git a/sprites/player1/sword/attack-5.png b/sprites/player1/sword/attack/attack-5.png similarity index 100% rename from sprites/player1/sword/attack-5.png rename to sprites/player1/sword/attack/attack-5.png diff --git a/sprites/player1/sword/attack-6.png b/sprites/player1/sword/attack/attack-6.png similarity index 100% rename from sprites/player1/sword/attack-6.png rename to sprites/player1/sword/attack/attack-6.png diff --git a/sprites/player1/sword/attack-7.png b/sprites/player1/sword/attack/attack-7.png similarity index 100% rename from sprites/player1/sword/attack-7.png rename to sprites/player1/sword/attack/attack-7.png diff --git a/sprites/player1/sword/fallen-2.png b/sprites/player1/sword/fallen/fallen-0.png similarity index 100% rename from sprites/player1/sword/fallen-2.png rename to sprites/player1/sword/fallen/fallen-0.png diff --git a/sprites/player1/sword/fallen-3.png b/sprites/player1/sword/fallen/fallen-1.png similarity index 100% rename from sprites/player1/sword/fallen-3.png rename to sprites/player1/sword/fallen/fallen-1.png diff --git a/sprites/player1/sword/fallen-0.png b/sprites/player1/sword/fallen/fallen-2.png similarity index 100% rename from sprites/player1/sword/fallen-0.png rename to sprites/player1/sword/fallen/fallen-2.png diff --git a/sprites/player1/sword/fallen-1.png b/sprites/player1/sword/fallen/fallen-3.png similarity index 100% rename from sprites/player1/sword/fallen-1.png rename to sprites/player1/sword/fallen/fallen-3.png diff --git a/sprites/player1/sword/fallen-4.png b/sprites/player1/sword/fallen/fallen-4.png similarity index 100% rename from sprites/player1/sword/fallen-4.png rename to sprites/player1/sword/fallen/fallen-4.png diff --git a/sprites/player1/sword/fallen-5.png b/sprites/player1/sword/fallen/fallen-5.png similarity index 100% rename from sprites/player1/sword/fallen-5.png rename to sprites/player1/sword/fallen/fallen-5.png diff --git a/sprites/player1/sword/run-0.png b/sprites/player1/sword/run/run-0.png similarity index 100% rename from sprites/player1/sword/run-0.png rename to sprites/player1/sword/run/run-0.png diff --git a/sprites/player1/sword/run-1.png b/sprites/player1/sword/run/run-1.png similarity index 100% rename from sprites/player1/sword/run-1.png rename to sprites/player1/sword/run/run-1.png diff --git a/sprites/player1/sword/run-10.png b/sprites/player1/sword/run/run-10.png similarity index 100% rename from sprites/player1/sword/run-10.png rename to sprites/player1/sword/run/run-10.png diff --git a/sprites/player1/sword/run-11.png b/sprites/player1/sword/run/run-11.png similarity index 100% rename from sprites/player1/sword/run-11.png rename to sprites/player1/sword/run/run-11.png diff --git a/sprites/player1/sword/run-2.png b/sprites/player1/sword/run/run-2.png similarity index 100% rename from sprites/player1/sword/run-2.png rename to sprites/player1/sword/run/run-2.png diff --git a/sprites/player1/sword/run-3.png b/sprites/player1/sword/run/run-3.png similarity index 100% rename from sprites/player1/sword/run-3.png rename to sprites/player1/sword/run/run-3.png diff --git a/sprites/player1/sword/run-4.png b/sprites/player1/sword/run/run-4.png similarity index 100% rename from sprites/player1/sword/run-4.png rename to sprites/player1/sword/run/run-4.png diff --git a/sprites/player1/sword/run-5.png b/sprites/player1/sword/run/run-5.png similarity index 100% rename from sprites/player1/sword/run-5.png rename to sprites/player1/sword/run/run-5.png diff --git a/sprites/player1/sword/run-6.png b/sprites/player1/sword/run/run-6.png similarity index 100% rename from sprites/player1/sword/run-6.png rename to sprites/player1/sword/run/run-6.png diff --git a/sprites/player1/sword/run-7.png b/sprites/player1/sword/run/run-7.png similarity index 100% rename from sprites/player1/sword/run-7.png rename to sprites/player1/sword/run/run-7.png diff --git a/sprites/player1/sword/run-8.png b/sprites/player1/sword/run/run-8.png similarity index 100% rename from sprites/player1/sword/run-8.png rename to sprites/player1/sword/run/run-8.png diff --git a/sprites/player1/sword/run-9.png b/sprites/player1/sword/run/run-9.png similarity index 100% rename from sprites/player1/sword/run-9.png rename to sprites/player1/sword/run/run-9.png diff --git a/sprites/player1/worker/dig-0.png b/sprites/player1/worker/dig/dig-0.png similarity index 100% rename from sprites/player1/worker/dig-0.png rename to sprites/player1/worker/dig/dig-0.png diff --git a/sprites/player1/worker/dig-1.png b/sprites/player1/worker/dig/dig-1.png similarity index 100% rename from sprites/player1/worker/dig-1.png rename to sprites/player1/worker/dig/dig-1.png diff --git a/sprites/player1/worker/dig-2.png b/sprites/player1/worker/dig/dig-2.png similarity index 100% rename from sprites/player1/worker/dig-2.png rename to sprites/player1/worker/dig/dig-2.png diff --git a/sprites/player1/worker/dig-3.png b/sprites/player1/worker/dig/dig-3.png similarity index 100% rename from sprites/player1/worker/dig-3.png rename to sprites/player1/worker/dig/dig-3.png diff --git a/sprites/player1/worker/dig-4.png b/sprites/player1/worker/dig/dig-4.png similarity index 100% rename from sprites/player1/worker/dig-4.png rename to sprites/player1/worker/dig/dig-4.png diff --git a/sprites/player1/worker/dig-5.png b/sprites/player1/worker/dig/dig-5.png similarity index 100% rename from sprites/player1/worker/dig-5.png rename to sprites/player1/worker/dig/dig-5.png diff --git a/sprites/player1/worker/dig-6.png b/sprites/player1/worker/dig/dig-6.png similarity index 100% rename from sprites/player1/worker/dig-6.png rename to sprites/player1/worker/dig/dig-6.png diff --git a/sprites/player1/worker/dig-7.png b/sprites/player1/worker/dig/dig-7.png similarity index 100% rename from sprites/player1/worker/dig-7.png rename to sprites/player1/worker/dig/dig-7.png diff --git a/sprites/player1/worker/dig-8.png b/sprites/player1/worker/dig/dig-8.png similarity index 100% rename from sprites/player1/worker/dig-8.png rename to sprites/player1/worker/dig/dig-8.png diff --git a/sprites/player1/worker/repair-0.png b/sprites/player1/worker/repair/repair-0.png similarity index 100% rename from sprites/player1/worker/repair-0.png rename to sprites/player1/worker/repair/repair-0.png diff --git a/sprites/player1/worker/repair-1.png b/sprites/player1/worker/repair/repair-1.png similarity index 100% rename from sprites/player1/worker/repair-1.png rename to sprites/player1/worker/repair/repair-1.png diff --git a/sprites/player1/worker/repair-2.png b/sprites/player1/worker/repair/repair-2.png similarity index 100% rename from sprites/player1/worker/repair-2.png rename to sprites/player1/worker/repair/repair-2.png diff --git a/sprites/player1/worker/repair-3.png b/sprites/player1/worker/repair/repair-3.png similarity index 100% rename from sprites/player1/worker/repair-3.png rename to sprites/player1/worker/repair/repair-3.png diff --git a/sprites/player1/worker/run-0.png b/sprites/player1/worker/run/run-0.png similarity index 100% rename from sprites/player1/worker/run-0.png rename to sprites/player1/worker/run/run-0.png diff --git a/sprites/player1/worker/run-1.png b/sprites/player1/worker/run/run-1.png similarity index 100% rename from sprites/player1/worker/run-1.png rename to sprites/player1/worker/run/run-1.png diff --git a/sprites/player1/worker/run-2.png b/sprites/player1/worker/run/run-2.png similarity index 100% rename from sprites/player1/worker/run-2.png rename to sprites/player1/worker/run/run-2.png diff --git a/sprites/player1/worker/run-3.png b/sprites/player1/worker/run/run-3.png similarity index 100% rename from sprites/player1/worker/run-3.png rename to sprites/player1/worker/run/run-3.png diff --git a/sprites/player1/worker/run-4.png b/sprites/player1/worker/run/run-4.png similarity index 100% rename from sprites/player1/worker/run-4.png rename to sprites/player1/worker/run/run-4.png diff --git a/sprites/player1/worker/run-5.png b/sprites/player1/worker/run/run-5.png similarity index 100% rename from sprites/player1/worker/run-5.png rename to sprites/player1/worker/run/run-5.png diff --git a/sprites/player2/bow/arrowdiag-0.png b/sprites/player2/bow/arrow_diag/arrowdiag-0.png similarity index 100% rename from sprites/player2/bow/arrowdiag-0.png rename to sprites/player2/bow/arrow_diag/arrowdiag-0.png diff --git a/sprites/player2/bow/arrowdiag-1.png b/sprites/player2/bow/arrow_diag/arrowdiag-1.png similarity index 100% rename from sprites/player2/bow/arrowdiag-1.png rename to sprites/player2/bow/arrow_diag/arrowdiag-1.png diff --git a/sprites/player2/bow/arrowhor-0.png b/sprites/player2/bow/arrow_hor/arrowhor-0.png similarity index 100% rename from sprites/player2/bow/arrowhor-0.png rename to sprites/player2/bow/arrow_hor/arrowhor-0.png diff --git a/sprites/player2/bow/arrowhor-1.png b/sprites/player2/bow/arrow_hor/arrowhor-1.png similarity index 100% rename from sprites/player2/bow/arrowhor-1.png rename to sprites/player2/bow/arrow_hor/arrowhor-1.png diff --git a/sprites/player2/bow/arrowvert-0.png b/sprites/player2/bow/arrow_vert/arrowvert-0.png similarity index 100% rename from sprites/player2/bow/arrowvert-0.png rename to sprites/player2/bow/arrow_vert/arrowvert-0.png diff --git a/sprites/player2/bow/arrowvert-1.png b/sprites/player2/bow/arrow_vert/arrowvert-1.png similarity index 100% rename from sprites/player2/bow/arrowvert-1.png rename to sprites/player2/bow/arrow_vert/arrowvert-1.png diff --git a/sprites/player2/bow/fallen-0.png b/sprites/player2/bow/fallen/fallen-0.png similarity index 100% rename from sprites/player2/bow/fallen-0.png rename to sprites/player2/bow/fallen/fallen-0.png diff --git a/sprites/player2/bow/fallen-1.png b/sprites/player2/bow/fallen/fallen-1.png similarity index 100% rename from sprites/player2/bow/fallen-1.png rename to sprites/player2/bow/fallen/fallen-1.png diff --git a/sprites/player2/bow/fallen-2.png b/sprites/player2/bow/fallen/fallen-2.png similarity index 100% rename from sprites/player2/bow/fallen-2.png rename to sprites/player2/bow/fallen/fallen-2.png diff --git a/sprites/player2/bow/fallen-3.png b/sprites/player2/bow/fallen/fallen-3.png similarity index 100% rename from sprites/player2/bow/fallen-3.png rename to sprites/player2/bow/fallen/fallen-3.png diff --git a/sprites/player2/bow/fallen-4.png b/sprites/player2/bow/fallen/fallen-4.png similarity index 100% rename from sprites/player2/bow/fallen-4.png rename to sprites/player2/bow/fallen/fallen-4.png diff --git a/sprites/player2/bow/fallen-5.png b/sprites/player2/bow/fallen/fallen-5.png similarity index 100% rename from sprites/player2/bow/fallen-5.png rename to sprites/player2/bow/fallen/fallen-5.png diff --git a/sprites/player2/bow/run-0.png b/sprites/player2/bow/run/run-0.png similarity index 100% rename from sprites/player2/bow/run-0.png rename to sprites/player2/bow/run/run-0.png diff --git a/sprites/player2/bow/run-1.png b/sprites/player2/bow/run/run-1.png similarity index 100% rename from sprites/player2/bow/run-1.png rename to sprites/player2/bow/run/run-1.png diff --git a/sprites/player2/bow/run-10.png b/sprites/player2/bow/run/run-10.png similarity index 100% rename from sprites/player2/bow/run-10.png rename to sprites/player2/bow/run/run-10.png diff --git a/sprites/player2/bow/run-11.png b/sprites/player2/bow/run/run-11.png similarity index 100% rename from sprites/player2/bow/run-11.png rename to sprites/player2/bow/run/run-11.png diff --git a/sprites/player2/bow/run-2.png b/sprites/player2/bow/run/run-2.png similarity index 100% rename from sprites/player2/bow/run-2.png rename to sprites/player2/bow/run/run-2.png diff --git a/sprites/player2/bow/run-3.png b/sprites/player2/bow/run/run-3.png similarity index 100% rename from sprites/player2/bow/run-3.png rename to sprites/player2/bow/run/run-3.png diff --git a/sprites/player2/bow/run-4.png b/sprites/player2/bow/run/run-4.png similarity index 100% rename from sprites/player2/bow/run-4.png rename to sprites/player2/bow/run/run-4.png diff --git a/sprites/player2/bow/run-5.png b/sprites/player2/bow/run/run-5.png similarity index 100% rename from sprites/player2/bow/run-5.png rename to sprites/player2/bow/run/run-5.png diff --git a/sprites/player2/bow/run-6.png b/sprites/player2/bow/run/run-6.png similarity index 100% rename from sprites/player2/bow/run-6.png rename to sprites/player2/bow/run/run-6.png diff --git a/sprites/player2/bow/run-7.png b/sprites/player2/bow/run/run-7.png similarity index 100% rename from sprites/player2/bow/run-7.png rename to sprites/player2/bow/run/run-7.png diff --git a/sprites/player2/bow/run-8.png b/sprites/player2/bow/run/run-8.png similarity index 100% rename from sprites/player2/bow/run-8.png rename to sprites/player2/bow/run/run-8.png diff --git a/sprites/player2/bow/run-9.png b/sprites/player2/bow/run/run-9.png similarity index 100% rename from sprites/player2/bow/run-9.png rename to sprites/player2/bow/run/run-9.png diff --git a/sprites/player2/bow/shoot-0.png b/sprites/player2/bow/shoot/shoot-0.png similarity index 100% rename from sprites/player2/bow/shoot-0.png rename to sprites/player2/bow/shoot/shoot-0.png diff --git a/sprites/player2/bow/shoot-1.png b/sprites/player2/bow/shoot/shoot-1.png similarity index 100% rename from sprites/player2/bow/shoot-1.png rename to sprites/player2/bow/shoot/shoot-1.png diff --git a/sprites/player2/sword/attack-0.png b/sprites/player2/sword/attack/attack-0.png similarity index 100% rename from sprites/player2/sword/attack-0.png rename to sprites/player2/sword/attack/attack-0.png diff --git a/sprites/player2/sword/attack-1.png b/sprites/player2/sword/attack/attack-1.png similarity index 100% rename from sprites/player2/sword/attack-1.png rename to sprites/player2/sword/attack/attack-1.png diff --git a/sprites/player2/sword/attack-2.png b/sprites/player2/sword/attack/attack-2.png similarity index 100% rename from sprites/player2/sword/attack-2.png rename to sprites/player2/sword/attack/attack-2.png diff --git a/sprites/player2/sword/attack-3.png b/sprites/player2/sword/attack/attack-3.png similarity index 100% rename from sprites/player2/sword/attack-3.png rename to sprites/player2/sword/attack/attack-3.png diff --git a/sprites/player2/sword/attack-4.png b/sprites/player2/sword/attack/attack-4.png similarity index 100% rename from sprites/player2/sword/attack-4.png rename to sprites/player2/sword/attack/attack-4.png diff --git a/sprites/player2/sword/attack-5.png b/sprites/player2/sword/attack/attack-5.png similarity index 100% rename from sprites/player2/sword/attack-5.png rename to sprites/player2/sword/attack/attack-5.png diff --git a/sprites/player2/sword/attack-6.png b/sprites/player2/sword/attack/attack-6.png similarity index 100% rename from sprites/player2/sword/attack-6.png rename to sprites/player2/sword/attack/attack-6.png diff --git a/sprites/player2/sword/attack-7.png b/sprites/player2/sword/attack/attack-7.png similarity index 100% rename from sprites/player2/sword/attack-7.png rename to sprites/player2/sword/attack/attack-7.png diff --git a/sprites/player2/sword/fallen-0.png b/sprites/player2/sword/fallen/fallen-0.png similarity index 100% rename from sprites/player2/sword/fallen-0.png rename to sprites/player2/sword/fallen/fallen-0.png diff --git a/sprites/player2/sword/fallen-1.png b/sprites/player2/sword/fallen/fallen-1.png similarity index 100% rename from sprites/player2/sword/fallen-1.png rename to sprites/player2/sword/fallen/fallen-1.png diff --git a/sprites/player2/sword/fallen-2.png b/sprites/player2/sword/fallen/fallen-2.png similarity index 100% rename from sprites/player2/sword/fallen-2.png rename to sprites/player2/sword/fallen/fallen-2.png diff --git a/sprites/player2/sword/fallen-3.png b/sprites/player2/sword/fallen/fallen-3.png similarity index 100% rename from sprites/player2/sword/fallen-3.png rename to sprites/player2/sword/fallen/fallen-3.png diff --git a/sprites/player2/sword/fallen-4.png b/sprites/player2/sword/fallen/fallen-4.png similarity index 100% rename from sprites/player2/sword/fallen-4.png rename to sprites/player2/sword/fallen/fallen-4.png diff --git a/sprites/player2/sword/fallen-5.png b/sprites/player2/sword/fallen/fallen-5.png similarity index 100% rename from sprites/player2/sword/fallen-5.png rename to sprites/player2/sword/fallen/fallen-5.png diff --git a/sprites/player2/sword/run-0.png b/sprites/player2/sword/run/run-0.png similarity index 100% rename from sprites/player2/sword/run-0.png rename to sprites/player2/sword/run/run-0.png diff --git a/sprites/player2/sword/run-1.png b/sprites/player2/sword/run/run-1.png similarity index 100% rename from sprites/player2/sword/run-1.png rename to sprites/player2/sword/run/run-1.png diff --git a/sprites/player2/sword/run-10.png b/sprites/player2/sword/run/run-10.png similarity index 100% rename from sprites/player2/sword/run-10.png rename to sprites/player2/sword/run/run-10.png diff --git a/sprites/player2/sword/run-11.png b/sprites/player2/sword/run/run-11.png similarity index 100% rename from sprites/player2/sword/run-11.png rename to sprites/player2/sword/run/run-11.png diff --git a/sprites/player2/sword/run-2.png b/sprites/player2/sword/run/run-2.png similarity index 100% rename from sprites/player2/sword/run-2.png rename to sprites/player2/sword/run/run-2.png diff --git a/sprites/player2/sword/run-3.png b/sprites/player2/sword/run/run-3.png similarity index 100% rename from sprites/player2/sword/run-3.png rename to sprites/player2/sword/run/run-3.png diff --git a/sprites/player2/sword/run-4.png b/sprites/player2/sword/run/run-4.png similarity index 100% rename from sprites/player2/sword/run-4.png rename to sprites/player2/sword/run/run-4.png diff --git a/sprites/player2/sword/run-5.png b/sprites/player2/sword/run/run-5.png similarity index 100% rename from sprites/player2/sword/run-5.png rename to sprites/player2/sword/run/run-5.png diff --git a/sprites/player2/sword/run-6.png b/sprites/player2/sword/run/run-6.png similarity index 100% rename from sprites/player2/sword/run-6.png rename to sprites/player2/sword/run/run-6.png diff --git a/sprites/player2/sword/run-7.png b/sprites/player2/sword/run/run-7.png similarity index 100% rename from sprites/player2/sword/run-7.png rename to sprites/player2/sword/run/run-7.png diff --git a/sprites/player2/sword/run-8.png b/sprites/player2/sword/run/run-8.png similarity index 100% rename from sprites/player2/sword/run-8.png rename to sprites/player2/sword/run/run-8.png diff --git a/sprites/player2/sword/run-9.png b/sprites/player2/sword/run/run-9.png similarity index 100% rename from sprites/player2/sword/run-9.png rename to sprites/player2/sword/run/run-9.png diff --git a/sprites/player2/worker/dig-0.png b/sprites/player2/worker/dig/dig-0.png similarity index 100% rename from sprites/player2/worker/dig-0.png rename to sprites/player2/worker/dig/dig-0.png diff --git a/sprites/player2/worker/dig-1.png b/sprites/player2/worker/dig/dig-1.png similarity index 100% rename from sprites/player2/worker/dig-1.png rename to sprites/player2/worker/dig/dig-1.png diff --git a/sprites/player2/worker/dig-2.png b/sprites/player2/worker/dig/dig-2.png similarity index 100% rename from sprites/player2/worker/dig-2.png rename to sprites/player2/worker/dig/dig-2.png diff --git a/sprites/player2/worker/dig-3.png b/sprites/player2/worker/dig/dig-3.png similarity index 100% rename from sprites/player2/worker/dig-3.png rename to sprites/player2/worker/dig/dig-3.png diff --git a/sprites/player2/worker/dig-4.png b/sprites/player2/worker/dig/dig-4.png similarity index 100% rename from sprites/player2/worker/dig-4.png rename to sprites/player2/worker/dig/dig-4.png diff --git a/sprites/player2/worker/dig-5.png b/sprites/player2/worker/dig/dig-5.png similarity index 100% rename from sprites/player2/worker/dig-5.png rename to sprites/player2/worker/dig/dig-5.png diff --git a/sprites/player2/worker/dig-6.png b/sprites/player2/worker/dig/dig-6.png similarity index 100% rename from sprites/player2/worker/dig-6.png rename to sprites/player2/worker/dig/dig-6.png diff --git a/sprites/player2/worker/dig-7.png b/sprites/player2/worker/dig/dig-7.png similarity index 100% rename from sprites/player2/worker/dig-7.png rename to sprites/player2/worker/dig/dig-7.png diff --git a/sprites/player2/worker/dig-8.png b/sprites/player2/worker/dig/dig-8.png similarity index 100% rename from sprites/player2/worker/dig-8.png rename to sprites/player2/worker/dig/dig-8.png diff --git a/sprites/player2/worker/repair-0.png b/sprites/player2/worker/repair/repair-0.png similarity index 100% rename from sprites/player2/worker/repair-0.png rename to sprites/player2/worker/repair/repair-0.png diff --git a/sprites/player2/worker/repair-1.png b/sprites/player2/worker/repair/repair-1.png similarity index 100% rename from sprites/player2/worker/repair-1.png rename to sprites/player2/worker/repair/repair-1.png diff --git a/sprites/player2/worker/repair-2.png b/sprites/player2/worker/repair/repair-2.png similarity index 100% rename from sprites/player2/worker/repair-2.png rename to sprites/player2/worker/repair/repair-2.png diff --git a/sprites/player2/worker/repair-3.png b/sprites/player2/worker/repair/repair-3.png similarity index 100% rename from sprites/player2/worker/repair-3.png rename to sprites/player2/worker/repair/repair-3.png diff --git a/sprites/player2/worker/run-0.png b/sprites/player2/worker/run/run-0.png similarity index 100% rename from sprites/player2/worker/run-0.png rename to sprites/player2/worker/run/run-0.png diff --git a/sprites/player2/worker/run-1.png b/sprites/player2/worker/run/run-1.png similarity index 100% rename from sprites/player2/worker/run-1.png rename to sprites/player2/worker/run/run-1.png diff --git a/sprites/player2/worker/run-2.png b/sprites/player2/worker/run/run-2.png similarity index 100% rename from sprites/player2/worker/run-2.png rename to sprites/player2/worker/run/run-2.png diff --git a/sprites/player2/worker/run-3.png b/sprites/player2/worker/run/run-3.png similarity index 100% rename from sprites/player2/worker/run-3.png rename to sprites/player2/worker/run/run-3.png diff --git a/sprites/player2/worker/run-4.png b/sprites/player2/worker/run/run-4.png similarity index 100% rename from sprites/player2/worker/run-4.png rename to sprites/player2/worker/run/run-4.png diff --git a/sprites/player2/worker/run-5.png b/sprites/player2/worker/run/run-5.png similarity index 100% rename from sprites/player2/worker/run-5.png rename to sprites/player2/worker/run/run-5.png