diff --git a/levels/2.json b/levels/2.json index 82beaa8..254d813 100644 --- a/levels/2.json +++ b/levels/2.json @@ -24,7 +24,7 @@ "x_range": [21, 29], "y": 0, "enemy_type": "goblin", - "health": 4, + "health": 2, "damage": 2, "attack_range": 1, "attack_pattern": { @@ -37,7 +37,7 @@ "hazard": true, "sound": "grave", "static": true, - "zombie_spawn_chance": 15 + "zombie_spawn_chance": 10 }, { "x_range": [33, 38], @@ -61,7 +61,8 @@ "x": 55, "y": 3, "sound": "coffin", - "type": "coffin" + "type": "coffin", + "item": "guts" }, { "x_range": [65, 70], @@ -74,7 +75,7 @@ "x_range": [71, 79], "y": 0, "enemy_type": "goblin", - "health": 5, + "health": 2, "damage": 2, "attack_range": 1, "attack_pattern": { @@ -93,7 +94,7 @@ "hazard": true, "sound": "grave", "static": true, - "zombie_spawn_chance": 20 + "zombie_spawn_chance": 10 }, { "x_range": [105, 108], @@ -127,11 +128,52 @@ "sound": "coin", "collectible": true, "static": true + }, + { + "x": 160, + "y": 0, + "hazard": true, + "sound": "grave", + "static": true, + "zombie_spawn_chance": 10 + }, + { + "x": 170, + "y": 3, + "sound": "coffin", + "type": "coffin", + "item": "extra_life" + }, + { + "x_range": [175, 180], + "y": 3, + "sound": "coin", + "collectible": true, + "static": true + }, + { + "x": 185, + "y": 0, + "hazard": true, + "sound": "grave", + "static": true, + "zombie_spawn_chance": 10 + }, + { + "x_range": [189, 198], + "y": 0, + "enemy_type": "witch", + "health": 4, + "damage": 2, + "attack_range": 1.5, + "attack_pattern": { + "type": "patrol" + } } ], "boundaries": { "left": 0, - "right": 170 + "right": 200 }, "footstep_sound": "footstep_tall_grass" } diff --git a/sounds/_edge.ogg b/sounds/_edge.ogg new file mode 100644 index 0000000..76a2c13 --- /dev/null +++ b/sounds/_edge.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09d25038bd409b2aed89548e15bd34b7132f85ac7dd1ac1e8c6a79a8f198d0cd +size 5340 diff --git a/sounds/get_cauldron.ogg b/sounds/get_cauldron.ogg new file mode 100644 index 0000000..4accc87 --- /dev/null +++ b/sounds/get_cauldron.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7766bb2439162bdd150bc5aa10c0eda706a4c0798a7d62d9cf45a8aa9b42c2d +size 27373 diff --git a/sounds/get_witch_broom.ogg b/sounds/get_witch_broom.ogg new file mode 100644 index 0000000..2a15a47 --- /dev/null +++ b/sounds/get_witch_broom.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9f7ac82eedb43aea94ec9e870aa29ea95bb222bd8d7a54e4bbb490ca4806476 +size 25232 diff --git a/sounds/player_broom_attack.ogg b/sounds/player_broom_attack.ogg new file mode 100644 index 0000000..75eeeee --- /dev/null +++ b/sounds/player_broom_attack.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0e9fede149adbca9e3c1acca4b57e0c7d0b02b551c71c56ef1c19b37071b23f +size 6117 diff --git a/sounds/player_broom_hit.ogg b/sounds/player_broom_hit.ogg new file mode 100644 index 0000000..946693d --- /dev/null +++ b/sounds/player_broom_hit.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a2f51236a8feb5e81f21d26cb220583fa7f54b7e139a8984dc228ef6008a824 +size 6402 diff --git a/sounds/witch.ogg b/sounds/witch.ogg new file mode 100644 index 0000000..4c82256 --- /dev/null +++ b/sounds/witch.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6763f200e0574334304a2e096dadb151e48baeb8214a79353686eb6d2852ed7a +size 19389 diff --git a/sounds/witch_dies.ogg b/sounds/witch_dies.ogg new file mode 100644 index 0000000..ee899de --- /dev/null +++ b/sounds/witch_dies.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79daf41c38359fe0066809270a43650130cc16ea53561a947f8dffe8fd9dd965 +size 14948 diff --git a/src/enemy.py b/src/enemy.py index 0b66d6a..5b47aa8 100644 --- a/src/enemy.py +++ b/src/enemy.py @@ -1,5 +1,6 @@ from libstormgames import * from src.object import Object +from src.powerup import PowerUp import pygame class Enemy(Object): @@ -171,5 +172,25 @@ class Enemy(Object): if deathSound in self.sounds: self.channel = obj_play(self.sounds, deathSound, self.level.player.xPos, self.xPos, loop=False) + # Handle witch-specific drops + if self.enemyType == "witch": + # Determine which item to drop + hasBroom = any(weapon.name == "witch_broom" for weapon in self.level.player.weapons) + itemType = "cauldron" if hasBroom else "witch_broom" + + # Create drop 1-2 tiles away in random direction + direction = random.choice([-1, 1]) + dropDistance = random.randint(1, 2) + dropX = self.xPos + (direction * dropDistance) + + droppedItem = PowerUp( + dropX, + self.yPos, + itemType, + self.sounds, + direction + ) + self.level.bouncing_items.append(droppedItem) + # Update stats self.level.player.stats.update_stat('Enemies killed', 1) diff --git a/src/item_types.py b/src/item_types.py index d317966..5bd14ad 100644 --- a/src/item_types.py +++ b/src/item_types.py @@ -8,6 +8,8 @@ class ItemType(Enum): HAND_OF_GLORY = auto() JACK_O_LANTERN = auto() EXTRA_LIFE = auto() + CAULDRON = auto() + WITCH_BROOM = auto() class ItemProperties: """Manages item properties and availability""" @@ -23,7 +25,9 @@ class ItemProperties: ItemType.GUTS: "guts", ItemType.HAND_OF_GLORY: "hand_of_glory", ItemType.JACK_O_LANTERN: "jack_o_lantern", - ItemType.EXTRA_LIFE: "extra_life" + ItemType.EXTRA_LIFE: "extra_life", + ItemType.CAULDRON: "cauldron", + ItemType.WITCH_BROOM: "witch_broom" } @staticmethod diff --git a/src/player.py b/src/player.py index b485874..f8cac9f 100644 --- a/src/player.py +++ b/src/player.py @@ -129,6 +129,10 @@ class Player: """Get current max health""" return self._maxHealth + def restore_health(self): + """Restore health to maximum""" + self._health = self._maxHealth + def get_current_speed(self): """Calculate current speed based on state""" baseSpeed = self.moveSpeed diff --git a/src/powerup.py b/src/powerup.py index 2daa420..56c3996 100644 --- a/src/powerup.py +++ b/src/powerup.py @@ -1,5 +1,6 @@ from libstormgames import * from src.object import Object +from src.weapon import Weapon class PowerUp(Object): def __init__(self, x, y, item_type, sounds, direction): @@ -44,12 +45,18 @@ class PowerUp(Object): """Apply the item's effect when collected""" if self.item_type == 'hand_of_glory': player.start_invincibility() + elif self.item_type == 'cauldron': + player.restore_health() elif self.item_type == 'guts': player.add_guts() elif self.item_type == 'jack_o_lantern': player.add_jack_o_lantern() elif self.item_type == 'extra_life': player.extra_life() + elif self.item_type == 'witch_broom': + broomWeapon = Weapon.create_witch_broom() + player.add_weapon(broomWeapon) + player.equip_weapon(broomWeapon) # Stop movement sound when collected if self.channel: diff --git a/src/weapon.py b/src/weapon.py index 51536b4..97dd180 100644 --- a/src/weapon.py +++ b/src/weapon.py @@ -10,6 +10,19 @@ class Weapon: self.lastAttackTime = 0 self.hitEnemies = set() + @classmethod + def create_witch_broom(cls): + """Create the witch's broom weapon""" + return cls( + name="witch_broom", + damage=3, + range=2.5, + attackSound="player_broom_attack", + hitSound="player_broom_hit", + cooldown=500, + attackDuration=200 + ) + def can_attack(self, currentTime): """Check if enough time has passed since last attack""" return currentTime - self.lastAttackTime >= self.cooldown