From 5ca8188c2b9a69c6eb3ee13f38336d449e90dde1 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Tue, 11 Feb 2025 12:54:48 -0500 Subject: [PATCH] A couple of small adjustments to level 12 and 13. Added the ability to lock levels meaning all enemies must be defeated before you can pass the right boundary. Raised the volume level of coffins a bit. Fixed hunter style attack patterns. --- levels/Wicked Quest/12.json | 26 ++++++++-------- levels/Wicked Quest/13.json | 1 + sounds/coffin.ogg | 4 +-- sounds/locked.ogg | 3 ++ src/enemy.py | 60 ++++++++++--------------------------- src/level.py | 16 ++++++++-- wicked_quest.py | 2 +- 7 files changed, 49 insertions(+), 63 deletions(-) create mode 100644 sounds/locked.ogg diff --git a/levels/Wicked Quest/12.json b/levels/Wicked Quest/12.json index a5cc8ce..f57bf27 100644 --- a/levels/Wicked Quest/12.json +++ b/levels/Wicked Quest/12.json @@ -1,7 +1,7 @@ { "level_id": 12, "name": "Pumpkin Run", - "description": "Angry at the way you just blew through their defenses like that, monsters have decided to man... er monster the catapults. Good luck." + "description": "Angry at the way you just blew through their defenses like that, monsters have decided to man... er monster the catapults. Good luck.", "player_start": { "x": 0, "y": 0 @@ -26,7 +26,7 @@ "y": 0, "type": "catapult", "fire_interval": 3000, - "range": 50 + "range": 40 }, { "x_range": [55, 60], @@ -56,7 +56,7 @@ "y": 0, "type": "catapult", "fire_interval": 3000, - "range": 50 + "range": 40 }, { "x_range": [105, 110], @@ -86,14 +86,14 @@ "y": 0, "type": "catapult", "fire_interval": 3000, - "range": 50 + "range": 40 }, { "x_range": [145, 165], "y": 15, "type": "skull_storm", "damage": 4, - "maximum_skulls": 3, + "maximum_skulls": 5, "frequency": { "min": 1, "max": 3 @@ -117,7 +117,7 @@ "y": 0, "type": "catapult", "fire_interval": 3000, - "range": 50 + "range": 40 }, { "x_range": [185, 195], @@ -148,7 +148,7 @@ "y": 0, "type": "catapult", "fire_interval": 3000, - "range": 50 + "range": 40 }, { "x_range": [235, 240], @@ -169,7 +169,7 @@ "y": 0, "type": "catapult", "fire_interval": 3000, - "range": 50 + "range": 40 }, { "x_range": [265, 285], @@ -179,7 +179,7 @@ "maximum_skulls": 3, "frequency": { "min": 1, - "max": 3 + "max": 5 } }, { @@ -194,7 +194,7 @@ "y": 0, "type": "catapult", "fire_interval": 3000, - "range": 50 + "range": 40 }, { "x_range": [305, 315], @@ -220,17 +220,17 @@ "y": 0, "type": "catapult", "fire_interval": 3000, - "range": 50 + "range": 40 }, { "x_range": [355, 375], "y": 15, "type": "skull_storm", "damage": 4, - "maximum_skulls": 3, + "maximum_skulls": 5, "frequency": { "min": 1, - "max": 3 + "max": 5 } }, { diff --git a/levels/Wicked Quest/13.json b/levels/Wicked Quest/13.json index 48adb74..5758efc 100644 --- a/levels/Wicked Quest/13.json +++ b/levels/Wicked Quest/13.json @@ -2,6 +2,7 @@ "level_id": 13, "name": "Trick or Treat", "description": "The end of your journey lies ahead, but the monsters have prepared a special welcome. The air crackles with dark magic, and something massive stirs in the darkness.", + "locked": true, "player_start": { "x": 0, "y": 0 diff --git a/sounds/coffin.ogg b/sounds/coffin.ogg index 80370cb..e4f82db 100644 --- a/sounds/coffin.ogg +++ b/sounds/coffin.ogg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b70b98de7ceca8036143357dee7b2c98c9c7c4bf0c08bdef41addbe29e4a7765 -size 60273 +oid sha256:bb3d9ddad96a134c774157e6dd777d8352aa8bb7ed81ae30189ebc92ad93bc2e +size 61691 diff --git a/sounds/locked.ogg b/sounds/locked.ogg new file mode 100644 index 0000000..88f0300 --- /dev/null +++ b/sounds/locked.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee6b45bc10bdc8342f2a3475af02eed29f3f937778c3ee478a65e9e97ecf0b72 +size 42532 diff --git a/src/enemy.py b/src/enemy.py index 7eeab3f..8c7f5eb 100644 --- a/src/enemy.py +++ b/src/enemy.py @@ -53,47 +53,11 @@ class Enemy(Object): return self._currentX @xPos.setter + def xPos(self, value): """Set current x position""" self._currentX = value - def update_movement(self, player): - """Update enemy movement based on attack pattern""" - if self.attackPattern['type'] == 'hunter': - # Calculate distance to player - distanceToPlayer = player.xPos - self.xPos - - if abs(distanceToPlayer) <= (self.patrolEnd - self.patrolStart): # Use full range - # Player is within movement range - if self.movingRight: - # Moving right - if distanceToPlayer < -self.turnThreshold: - # Player is too far behind us, turn around - self.movingRight = False - else: - self.xPos += self.movementSpeed - else: - # Moving left - if distanceToPlayer > self.turnThreshold: - # Player is too far ahead of us, turn around - self.movingRight = True - else: - self.xPos -= self.movementSpeed - - # Ensure we stay within our range - if self.xPos <= self.patrolStart: - self.xPos = self.patrolStart - self.movingRight = True - elif self.xPos >= self.patrolEnd: - self.xPos = self.patrolEnd - self.movingRight = False - else: - # Player out of range, return to normal patrol - self.patrol_movement() - else: - # Default patrol behavior - self.patrol_movement() - def patrol_movement(self): """Standard back-and-forth patrol movement""" if self.movingRight: @@ -109,20 +73,28 @@ class Enemy(Object): """Update enemy position and handle attacks""" if not self.isActive or self.health <= 0: return - - # Handle movement based on enemy type - if self.enemyType == "zombie": - # Zombies always chase player + + # Handle movement based on enemy type and pattern + if self.enemyType == "zombie" or self.attackPattern['type'] == 'hunter': + # Direct chase behavior for zombies and hunters if player.xPos > self.xPos: self.movingRight = True self.xPos += self.movementSpeed else: self.movingRight = False self.xPos -= self.movementSpeed + + # Only enforce level boundaries, not patrol boundaries + if self.xPos < self.level.leftBoundary: + self.xPos = self.level.leftBoundary + self.movingRight = True + elif self.xPos > self.level.rightBoundary: + self.xPos = self.level.rightBoundary + self.movingRight = False else: - # Other enemies use their attack pattern - self.update_movement(player) - + # Other enemies use patrol pattern + self.patrol_movement() + # Check for attack opportunity if self.can_attack(currentTime, player): self.attack(currentTime, player) diff --git a/src/level.py b/src/level.py index 9a89dd0..d60e184 100644 --- a/src/level.py +++ b/src/level.py @@ -22,10 +22,11 @@ class Level: self.player = player self.lastWarningTime = 0 self.warningInterval = int(self.sounds['edge'].get_length() * 1000) # Convert seconds to milliseconds - self.weapon_hit_channel = None + self.leftBoundary = levelData["boundaries"]["left"] self.rightBoundary = levelData["boundaries"]["right"] + self.isLocked = levelData.get("locked", False) # Default to False if not specified self.levelId = levelData["level_id"] # Get footstep sound for this level, default to 'footstep' if not specified @@ -143,7 +144,8 @@ class Level: health=obj.get("health", 5), damage=obj.get("damage", 1), attack_range=obj.get("attack_range", 1), - movement_range=obj.get("movement_range", 5) + movement_range=obj.get("movement_range", 5), + attack_pattern=obj.get("attack_pattern", {'type': 'patrol'}) # Add this line ) self.enemies.append(enemy) else: @@ -394,7 +396,15 @@ class Level: if obj.soundName == "end_of_level": # Check if player has reached or passed the end marker if self.player.xPos >= obj.xPos: - # Stop all current sounds and play end level sound + # If level is locked, check for remaining enemies + if self.isLocked and any(enemy.isActive for enemy in self.enemies): + speak("You must defeat all enemies before proceeding!") + play_sound(self.sounds['locked']) + # Push player back a bit + self.player.xPos -= 1 + return False + + # Level complete pygame.mixer.stop() play_sound(self.sounds['end_of_level']) return True diff --git a/wicked_quest.py b/wicked_quest.py index 2d8950d..1c01ebb 100644 --- a/wicked_quest.py +++ b/wicked_quest.py @@ -90,7 +90,7 @@ class WickedQuest: if keys[pygame.K_c]: speak(f"{player.get_coins()} gbone dust") if keys[pygame.K_h]: - speak(f"{player.get_health()} HP") + speak(f"{player.get_health()} health of {player.get_max_health()}") if keys[pygame.K_l]: speak(f"{player.get_lives()} lives") if keys[pygame.K_j]: # Check jack o'lanterns