New items added..

This commit is contained in:
Storm Dragon
2025-02-06 02:31:57 -05:00
parent c29bcd40b7
commit 8f57069c98
13 changed files with 178 additions and 133 deletions

View File

@@ -8,7 +8,14 @@
},
"objects": [
{
"x": 5,
"x": 2,
"y": 3,
"item": "guts",
"sound": "coffin",
"type": "coffin"
},
{
"x_range": [5, 8],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -85,7 +92,7 @@
"zombie_spawn_chance": 15
},
{
"x_range": [95, 97],
"x_range": [95, 100],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -98,7 +105,7 @@
"type": "coffin"
},
{
"x_range": [120, 122],
"x_range": [120, 123],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -122,7 +129,7 @@
],
"boundaries": {
"left": 0,
"right": 160
"right": 165
},
"footstep_sound": "footstep_stone"
}

View File

@@ -14,7 +14,7 @@
"type": "coffin"
},
{
"x_range": [15, 17],
"x_range": [15, 18],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -39,6 +39,13 @@
"static": true,
"zombie_spawn_chance": 15
},
{
"x_range": [33, 38],
"y": 3,
"sound": "coin",
"collectible": true,
"static": true
},
{
"x_range": [45, 60],
"y": 12,
@@ -57,7 +64,7 @@
"type": "coffin"
},
{
"x_range": [65, 67],
"x_range": [65, 68],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -89,7 +96,7 @@
"zombie_spawn_chance": 20
},
{
"x_range": [105, 107],
"x_range": [105, 108],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -104,7 +111,7 @@
"range": 15
},
{
"x_range": [130, 160],
"x_range": [130, 165],
"y": 15,
"type": "skull_storm",
"damage": 4,

View File

@@ -36,13 +36,7 @@
"zombie_spawn_chance": 25
},
{
"x": 15,
"y": 3,
"sound": "coffin",
"type": "coffin"
},
{
"x_range": [25, 27],
"x_range": [25, 28],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -71,7 +65,7 @@
}
},
{
"x_range": [42, 44],
"x_range": [40, 44],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -97,7 +91,7 @@
}
},
{
"x_range": [75, 77],
"x_range": [75, 78],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -140,7 +134,7 @@
}
},
{
"x_range": [105, 107],
"x_range": [105, 115],
"y": 3,
"sound": "coin",
"collectible": true,
@@ -185,12 +179,19 @@
}
},
{
"x_range": [155, 157],
"x_range": [155, 158],
"y": 3,
"sound": "coin",
"collectible": true,
"static": true
},
{
"x": 145,
"y": 3,
"item": "hand_of_glory",
"sound": "coffin",
"type": "coffin"
},
{
"x_range": [146, 166],
"y": 0,
@@ -228,6 +229,20 @@
"sound": "coin",
"collectible": true,
"static": true
},
{
"x": 185,
"y": 3,
"item": "extra_life",
"sound": "coffin",
"type": "coffin"
},
{
"x_range": [190, 195],
"y": 3,
"sound": "coin",
"collectible": true,
"static": true
}
],
"boundaries": {

BIN
sounds/extra_life.ogg (Stored with Git LFS)

Binary file not shown.

BIN
sounds/get_guts.ogg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -1,11 +1,12 @@
import random
from libstormgames import *
from src.item_types import ItemProperties
from src.object import Object
from src.powerup import PowerUp
import random
class CoffinObject(Object):
def __init__(self, x, y, sounds, level):
def __init__(self, x, y, sounds, level, item="random"):
super().__init__(
x, y, "coffin",
isStatic=True,
@@ -13,9 +14,10 @@ class CoffinObject(Object):
isHazard=False
)
self.sounds = sounds
self.level = level # Store level reference
self.level = level
self.is_broken = False
self.dropped_item = None
self.specified_item = item
def hit(self, player_pos):
"""Handle being hit by the player's weapon"""
@@ -23,23 +25,31 @@ class CoffinObject(Object):
self.is_broken = True
play_sound(self.sounds['coffin_shatter'])
self.level.player.stats.update_stat('Coffins broken', 1)
# Stop the ongoing coffin sound
if self.channel:
obj_stop(self.channel)
self.channel = None
# Mark coffin as inactive since it's broken
self.isActive = False
# Randomly choose item type
item_type = random.choice(['hand_of_glory', 'jack_o_lantern'])
# Determine item to drop
if self.specified_item == "random":
item_type = ItemProperties.get_random_item()
else:
# Validate specified item
if ItemProperties.is_valid_item(self.specified_item):
item_type = self.specified_item
else:
# Fall back to random if invalid item specified
item_type = ItemProperties.get_random_item()
# Create item 1-2 tiles away in random direction
direction = random.choice([-1, 1])
drop_distance = random.randint(1, 2)
drop_x = self.xPos + (direction * drop_distance)
self.dropped_item = PowerUp(
drop_x,
self.yPos,

View File

@@ -1,89 +0,0 @@
from libstormgames import *
from src.object import Object
import random
class CoffinObject(Object):
def __init__(self, x, y, sounds):
super().__init__(
x, y, "coffin",
isStatic=True,
isCollectible=False,
isHazard=False
)
self.sounds = sounds
self.is_broken = False
self.dropped_item = None
def hit(self, player_pos):
"""Handle being hit by the player's weapon"""
if not self.is_broken:
self.is_broken = True
self.sounds['coffin_shatter'].play()
# Randomly choose item type
item_type = random.choice(['hand_of_glory', 'jack_o_lantern'])
# Create item 1-2 tiles away in random direction
direction = random.choice([-1, 1])
drop_distance = random.randint(1, 2)
drop_x = self.xPos + (direction * drop_distance)
self.dropped_item = Item(
drop_x,
self.yPos,
item_type,
self.sounds,
direction
)
return True
return False
class Item(Object):
def __init__(self, x, y, item_type, sounds, direction):
super().__init__(
x, y, item_type,
isStatic=False,
isCollectible=True,
isHazard=False
)
self.sounds = sounds
self.direction = direction
self.speed = 0.05 # Base movement speed
self.item_type = item_type
self.channel = None
def update(self, current_time):
"""Update item position"""
if not self.isActive:
return False
# Update position
self._currentX += self.direction * self.speed
# Keep bounce sound playing while moving
if self.channel is None or not self.channel.get_busy():
self.channel = self.sounds['item_bounce'].play(-1)
# Check if item has gone too far (20 tiles)
if abs(self._currentX - self.xRange[0]) > 20:
self.isActive = False
if self.channel:
self.channel.stop()
self.channel = None
return False
return True
def apply_effect(self, player):
"""Apply the item's effect when collected"""
if self.item_type == 'hand_of_glory':
player.start_invincibility()
speak("Hand of Glory makes you invincible!")
elif self.item_type == 'jack_o_lantern':
player.add_projectile('jack_o_lantern')
speak("Gained a Jack-o'-lantern projectile!")
# Stop movement sound when collected
if self.channel:
self.channel.stop()
self.channel = None

51
src/item_types.py Normal file
View File

@@ -0,0 +1,51 @@
import random
from enum import Enum, auto
class ItemType(Enum):
"""Defines available item types and their properties"""
GUTS = auto()
HAND_OF_GLORY = auto()
JACK_O_LANTERN = auto()
EXTRA_LIFE = auto()
class ItemProperties:
"""Manages item properties and availability"""
# Items that can appear in random drops
RANDOM_ELIGIBLE = {
ItemType.HAND_OF_GLORY: "hand_of_glory",
ItemType.JACK_O_LANTERN: "jack_o_lantern"
}
# All possible items (including special ones)
ALL_ITEMS = {
ItemType.GUTS: "guts",
ItemType.HAND_OF_GLORY: "hand_of_glory",
ItemType.JACK_O_LANTERN: "jack_o_lantern",
ItemType.EXTRA_LIFE: "extra_life"
}
@staticmethod
def get_sound_name(item_type):
"""Convert enum to sound/asset name"""
return ItemProperties.ALL_ITEMS.get(item_type)
@staticmethod
def get_random_item():
"""Get a random item from eligible items"""
item_type = random.choice(list(ItemProperties.RANDOM_ELIGIBLE.keys()))
return ItemProperties.get_sound_name(item_type)
@staticmethod
def is_valid_item(item_name):
"""Check if an item name is valid"""
return item_name in [v for v in ItemProperties.ALL_ITEMS.values()]
@staticmethod
def get_item_type(item_name):
"""Get ItemType enum from string name"""
for item_type, name in ItemProperties.ALL_ITEMS.items():
if name == item_name:
return item_type
return None

View File

@@ -79,7 +79,8 @@ class Level:
xPos[0],
obj["y"],
self.sounds,
self # Pass level reference
self, # Pass level reference
item=obj.get("item", "random") # Get item type or default to random
)
self.objects.append(coffin)
# Check if this is an enemy
@@ -221,7 +222,7 @@ class Level:
if obj.hit(self.player.xPos):
self.bouncing_items.append(obj.dropped_item)
speak(f"{obj.dropped_item.item_type} falls out!")
#speak(f"{obj.dropped_item.soundName} falls out!")
def handle_collisions(self):
"""Handle all collision checks and return True if level is complete."""
@@ -265,7 +266,6 @@ class Level:
if self.player._coins % 100 == 0:
# Extra life
speak("Extra life")
self.player._coins = 0
self.player._lives += 1
play_sound(self.sounds['extra_life'])
@@ -273,7 +273,7 @@ class Level:
elif obj.isHazard and not self.player.isJumping:
if not self.player.isInvincible:
play_sound(self.sounds[obj.soundName])
speak("You fell in an open grave!")
speak("You fell in an open grave! Now, it's yours!")
self.player.set_health(0)
return False
else:

View File

@@ -14,6 +14,8 @@ class Player:
self.jumpDuration = 1000 # Jump duration in milliseconds
self.jumpStartTime = 0
self.isJumping = False
self.isRunning = False
self.runMultiplier = 1.5 # Same multiplier as jumping
self.facingRight = True
# Stats and tracking
@@ -26,11 +28,14 @@ class Player:
self.sounds = sounds
# Footstep tracking
self.baseStepDistance = 0.8
self.baseStepInterval = 250
self.stepDistance = self.baseStepDistance
self.minStepInterval = self.baseStepInterval
self.distanceSinceLastStep = 0
self.stepDistance = 0.8
self.lastStepTime = 0
self.minStepInterval = 250 # Minimum milliseconds between steps
self.footstepSound = "footstep"
self.isRunning = False
self.runMultiplier = 1.5
# Inventory system
self.inventory = []
@@ -61,8 +66,8 @@ class Player:
def should_play_footstep(self, currentTime):
"""Check if it's time to play a footstep sound"""
return (self.distanceSinceLastStep >= self.stepDistance and
currentTime - self.lastStepTime >= self.minStepInterval)
return (self.distanceSinceLastStep >= self.get_step_distance() and
currentTime - self.lastStepTime >= self.get_step_interval())
def update(self, currentTime):
"""Update player state"""
@@ -76,6 +81,10 @@ class Player:
self.isInvincible = True
self.invincibilityStartTime = pygame.time.get_ticks()
def extra_life(self):
"""Increment lives by 1"""
self._lives += 1
def get_jack_o_lanterns(self):
"""Get number of jack o'lanterns"""
return self._jack_o_lantern_count
@@ -84,6 +93,10 @@ class Player:
"""Add a jack o'lantern"""
self._jack_o_lantern_count += 1
def add_guts(self):
"""Apply guts, increase max_health by 2"""
self._maxHealth += 2
def throw_projectile(self):
"""Throw a jack o'lantern if we have any"""
if self.get_jack_o_lanterns() <= 0:
@@ -96,6 +109,18 @@ class Player:
'direction': 1 if self.facingRight else -1
}
def get_step_distance(self):
"""Get step distance based on current speed"""
if self.isRunning or self.isJumping:
return self.baseStepDistance / self.runMultiplier
return self.baseStepDistance
def get_step_interval(self):
"""Get minimum time between steps based on current speed"""
if self.isRunning or self.isJumping:
return self.baseStepInterval / self.runMultiplier
return self.baseStepInterval
def get_health(self):
"""Get current health"""
return self._health
@@ -104,6 +129,12 @@ class Player:
"""Get current max health"""
return self._maxHealth
def get_current_speed(self):
"""Calculate current speed based on state"""
baseSpeed = self.moveSpeed
if self.isJumping or self.isRunning: return baseSpeed * self.runMultiplier
return baseSpeed
def set_footstep_sound(self, soundName):
"""Set the current footstep sound"""
self.footstepSound = soundName
@@ -122,8 +153,7 @@ class Player:
pygame.mixer.stop()
cut_scene(self.sounds, 'lose_a_life')
if self._lives > 0:
self._health = self._maxHealth # Reset health if we still have lives
speak(f"{self._lives} lives remaining")
self.reset_on_death()
def set_max_health(self, value):
"""Set max health"""
@@ -137,6 +167,13 @@ class Player:
"""Get remaining lives"""
return self._lives
def reset_on_death(self):
"""Reset player state after death"""
self._health = self._maxHealth
self.isJumping = False
self.isRunning = False
self.xPos = 0
def add_weapon(self, weapon):
"""Add a new weapon to inventory and equip if first weapon"""
self.weapons.append(weapon)

View File

@@ -44,8 +44,12 @@ class PowerUp(Object):
"""Apply the item's effect when collected"""
if self.item_type == 'hand_of_glory':
player.start_invincibility()
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()
# Stop movement sound when collected
if self.channel:

View File

@@ -49,9 +49,12 @@ class WickedQuest:
player = self.currentLevel.player
currentTime = pygame.time.get_ticks()
# Calculate current speed based on jumping state
currentSpeed = player.moveSpeed * 1.5 if player.isJumping else player.moveSpeed
# Update running state
player.isRunning = keys[pygame.K_SPACE]
# Get current speed (handles both running and jumping)
currentSpeed = player.get_current_speed()
# Track movement distance for this frame
movementDistance = 0