diff --git a/credits.txt b/credits.txt index ea3e741..138db72 100644 --- a/credits.txt +++ b/credits.txt @@ -8,6 +8,7 @@ https://lornn.itch.io/cyberpunk-backgrounds https://oco.itch.io/cyberpunk-character-pack-2 https://biopticmarz.itch.io/pixel-robot-enemy https://ppeldo.itch.io/2d-pixel-art-game-spellmagic-fx +https://luizmelo.itch.io/martial-hero Dialogues: https://ttsmp3.com/ diff --git a/src/assets/audio/guardian-dialogue.mp3 b/src/assets/audio/guardian-dialogue.mp3 new file mode 100644 index 0000000..a8d7764 Binary files /dev/null and b/src/assets/audio/guardian-dialogue.mp3 differ diff --git a/src/assets/images/entities/guardian.png b/src/assets/images/entities/guardian.png new file mode 100644 index 0000000..e21c71c Binary files /dev/null and b/src/assets/images/entities/guardian.png differ diff --git a/src/assets/images/icon.png b/src/assets/images/icon.png new file mode 100644 index 0000000..695e18a Binary files /dev/null and b/src/assets/images/icon.png differ diff --git a/src/assets/images/stages/guardianMeeting.jpg b/src/assets/images/stages/guardianMeeting.jpg new file mode 100644 index 0000000..58cc72b Binary files /dev/null and b/src/assets/images/stages/guardianMeeting.jpg differ diff --git a/src/config.py b/src/config.py index 9b907d9..61601f5 100644 --- a/src/config.py +++ b/src/config.py @@ -88,6 +88,18 @@ "audio": "./assets/audio/cinematic-metal.mp3", "bossPos": (700, 380), "playerPos": (200, 380) + }, + { + "category": "cutscene", + "audio": "./assets/audio/guardian-dialogue.mp3", + "background": "./assets/images/stages/guardianMeeting.jpg" + }, + { + "category": "normal", + "background": "./assets/images/stages/highway.png", + "audio": "./assets/audio/cinematic-metal.mp3", + "guardianPos": (700, 380), + "playerPos": (200, 380) } ] @@ -166,6 +178,26 @@ "TELEPORT_RANGE": (100, 800) } +guardianConfig = { + "ANIMATION_STEPS": [8, 6, 6, 4], + "ANIM_DEATH": 2, + "ANIM_RUN": 0, + "ANIM_ATTACK": 1, + "ANIM_HIT": 3, + "SIZE_X": 200, + "SIZE_Y": 200, + "SCALE": 3, + "OFFSET": [85, 70], + "ANIMATION_COOLDOWN": 100, + "HITBOX_WIDTH": 96, + "HITBOX_HEIGHT": 180, + "BASE_SPEED": 5, + "BASE_HEALTH": 300, + "DAMAGE": 10, + "SPEED": 4, + "ATTACK_FRAME": 4 +} + projectileConfig = { "SPEED": 20, "ANIMATION_STEPS": [45], diff --git a/src/entity/enemy/guardian.py b/src/entity/enemy/guardian.py new file mode 100644 index 0000000..5be0639 --- /dev/null +++ b/src/entity/enemy/guardian.py @@ -0,0 +1,57 @@ +import pygame +from time import time +from config import guardianConfig +from entity.entity import Entity +from random import randrange + + +class Guardian(Entity): + def __init__(self, x, y, guardianSpritesheet): + super().__init__(x, y, guardianSpritesheet, guardianConfig) + self.hit = False + + def updateAnimation(self, surface, player): + attackRange = pygame.Rect((self.body.left if self.flip else self.body.right)-self.body.width, + self.body.top-self.body.height*0.5, self.body.width*2, self.body.height*1.5) + + if self.health <= 0 or not player.alive: + self.health = 0 + self._updateAction(guardianConfig["ANIM_DEATH"]) + elif (attackRange.colliderect(player.body)): + self._updateAction(guardianConfig["ANIM_ATTACK"]) + elif self.hit: + self._updateAction(guardianConfig["ANIM_HIT"]) + else: + self._updateAction(guardianConfig["ANIM_RUN"]) + + current = pygame.time.get_ticks() + self.image = self.animationList[self.action][self.frameIndex] + + if current - self.lastAnimationUpdateTime > self.animationCooldown: + self.frameIndex += 1 + self.lastAnimationUpdateTime = current + + if self.action == guardianConfig["ANIM_ATTACK"] and self.frameIndex == guardianConfig["ATTACK_FRAME"]: + if (attackRange.colliderect(player.body)): + player.health -= guardianConfig["DAMAGE"] + player.hit = True + player.body.y -= 100 + self.frameIndex += 1 + + if self.frameIndex >= len(self.animationList[self.action]): + self.frameIndex = 0 + if self.action == guardianConfig["ANIM_DEATH"]: + self.alive = False + elif self.action == guardianConfig["ANIM_HIT"]: + self.hit = False + + if (self.action == guardianConfig["ANIM_RUN"]): + self.__moveCloserToPlayer(player) + + def __moveCloserToPlayer(self, player): + if (player.body.centerx > self.body.centerx): + self.body.x += guardianConfig["SPEED"] + self.flip = False + elif (player.body.centerx < self.body.centerx): + self.body.x -= guardianConfig["SPEED"] + self.flip = True diff --git a/src/stageLoader.py b/src/stageLoader.py index 471b030..6d7a786 100644 --- a/src/stageLoader.py +++ b/src/stageLoader.py @@ -3,6 +3,7 @@ from entity.enemy.walkingEnemy import WalkingEnemy from entity.emp import Emp from entity.enemy.boss import Boss +from entity.enemy.guardian import Guardian from config import colorsConfig, gameSettings import pygame @@ -25,6 +26,9 @@ def __init__(self): self.__clock = pygame.time.Clock() self.__screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags, DEPTH) + + iconImg = pygame.image.load("./assets/images/icon.png").convert() + pygame.display.set_icon(iconImg) self.__playerSpritesheet = pygame.image.load(SPRITESHEET_PATH + "player.png").convert_alpha() self.__shootingEnemySpritesheet = pygame.image.load(SPRITESHEET_PATH + "shootingEnemy.png").convert_alpha() @@ -32,6 +36,7 @@ def __init__(self): self.__empSpritesheet = pygame.image.load(SPRITESHEET_PATH + "emp.png").convert_alpha() self.__bossSpritesheet = pygame.image.load(SPRITESHEET_PATH + "boss.png").convert_alpha() self.__walkingEnemySpritesheet = pygame.image.load(SPRITESHEET_PATH + "walkingEnemy.png").convert_alpha() + self.__guardianSpritesheet = pygame.image.load(SPRITESHEET_PATH + "guardian.png").convert_alpha() self.__emp = Emp(0, 0, self.__empSpritesheet) @@ -67,7 +72,7 @@ def playCutscene(self, category, audio, background): quit() - def loadNormalStage(self, category, background, audio, playerPos, shootingEnemiesPos=[], walkingEnemiesPos=[], bossPos=None): + def loadNormalStage(self, category, background, audio, playerPos, shootingEnemiesPos=[], walkingEnemiesPos=[], bossPos=None, guardianPos=None): convertedBackground = pygame.image.load(background).convert() player = Player(playerPos[0], playerPos[1], self.__playerSpritesheet, self.__emp) @@ -82,6 +87,9 @@ def loadNormalStage(self, category, background, audio, playerPos, shootingEnemie if(bossPos != None): enemies.append(Boss(bossPos[0], bossPos[1], self.__bossSpritesheet)) + + if(guardianPos != None): + enemies.append(Guardian(guardianPos[0], guardianPos[1], self.__guardianSpritesheet)) if(audio != ""): self.__playAudio(audio) self.__emp.finished = False @@ -118,4 +126,4 @@ def loadNormalStage(self, category, background, audio, playerPos, shootingEnemie pygame.display.update() - if(repeatThisStage): self.loadNormalStage(category, background, audio, playerPos, shootingEnemiesPos, walkingEnemiesPos, bossPos) \ No newline at end of file + if(repeatThisStage): self.loadNormalStage(category, background, audio, playerPos, shootingEnemiesPos, walkingEnemiesPos, bossPos, guardianPos) \ No newline at end of file