Allow for custom footsteps. Some work on footsteps to make the sound less crazy. Various other updates. Added initial documentation and credits files.

This commit is contained in:
Storm Dragon
2025-02-05 02:04:57 -05:00
parent 883dafaac0
commit c29bcd40b7
17 changed files with 431 additions and 43 deletions

View File

@@ -23,7 +23,6 @@ class CoffinObject(Object):
self.is_broken = True
play_sound(self.sounds['coffin_shatter'])
self.level.player.stats.update_stat('Coffins broken', 1)
self.level.player.stats.update_stat('Coffins remaining', -1)
# Stop the ongoing coffin sound
if self.channel:

View File

@@ -2,7 +2,6 @@ from libstormgames import *
from src.object import Object
import pygame
class Enemy(Object):
def __init__(self, xRange, y, enemyType, sounds, level, **kwargs):
# Initialize base object properties
@@ -20,16 +19,20 @@ class Enemy(Object):
self.health = kwargs.get('health', 5) # Default 5 HP
self.damage = kwargs.get('damage', 1) # Default 1 damage
self.attackRange = kwargs.get('attack_range', 1) # Default 1 tile range
self.movementRange = kwargs.get('movement_range', 5) # Default 5 tile patrol
self.sounds = sounds # Store reference to game sounds
# Movement and behavior properties
self.movingRight = True # Initial direction
self.movementSpeed = 0.03 # Base speed
self.patrolStart = self.xRange[0]
self.patrolEnd = self.xRange[0] + self.movementRange
self.patrolStart = self.xRange[0] # Use xRange directly for patrol boundaries
self.patrolEnd = self.xRange[1]
self.lastAttackTime = 0
self.attackCooldown = 1000 # 1 second between attacks
self._currentX = self.xRange[0] # Initialize current position
# Attack pattern configuration
self.attackPattern = kwargs.get('attack_pattern', {'type': 'patrol'})
self.turnThreshold = self.attackPattern.get('turn_threshold', 5)
# Enemy type specific adjustments
if enemyType == "zombie":
@@ -41,21 +44,69 @@ class Enemy(Object):
@property
def xPos(self):
"""Current x position"""
return self._currentX if hasattr(self, '_currentX') else self.xRange[0]
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:
self.xPos += self.movementSpeed
if self.xPos >= self.patrolEnd:
self.movingRight = False
else:
self.xPos -= self.movementSpeed
if self.xPos <= self.patrolStart:
self.movingRight = True
def update(self, currentTime, player):
"""Update enemy position and handle attacks"""
if not self.isActive or self.health <= 0:
return
# Zombie behavior - always chase player
# Handle movement based on enemy type
if self.enemyType == "zombie":
# Determine direction to player
# Zombies always chase player
if player.xPos > self.xPos:
self.movingRight = True
self.xPos += self.movementSpeed
@@ -63,20 +114,13 @@ class Enemy(Object):
self.movingRight = False
self.xPos -= self.movementSpeed
else:
# Normal patrol behavior for other enemies
if self.movingRight:
self.xPos += self.movementSpeed
if self.xPos >= self.patrolEnd:
self.movingRight = False
else:
self.xPos -= self.movementSpeed
if self.xPos <= self.patrolStart:
self.movingRight = True
# Other enemies use their attack pattern
self.update_movement(player)
# Check for attack opportunity
if self.can_attack(currentTime, player):
self.attack(currentTime, player)
def can_attack(self, currentTime, player):
"""Check if enemy can attack player"""
# Must have cooled down from last attack
@@ -128,4 +172,3 @@ class Enemy(Object):
# Update stats
self.level.player.stats.update_stat('Enemies killed', 1)
self.level.player.stats.update_stat('Enemies remaining', -1)

View File

@@ -25,6 +25,12 @@ class Level:
self.rightBoundary = levelData["boundaries"]["right"]
self.levelId = levelData["level_id"]
# Get footstep sound for this level, default to 'footstep' if not specified
self.footstepSound = levelData.get("footstep_sound", "footstep")
# Pass footstep sound to player
self.player.set_footstep_sound(self.footstepSound)
# Create end of level object at right boundary
endLevel = Object(
self.rightBoundary,

View File

@@ -23,6 +23,14 @@ class Player:
self.distanceSinceLastStep = 0
self.stepDistance = 0.5
self.stats = StatTracker()
self.sounds = sounds
# Footstep tracking
self.distanceSinceLastStep = 0
self.stepDistance = 0.8
self.lastStepTime = 0
self.minStepInterval = 250 # Minimum milliseconds between steps
self.footstepSound = "footstep"
# Inventory system
self.inventory = []
@@ -51,6 +59,11 @@ class Player:
attackDuration=200 # 200ms attack duration
))
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)
def update(self, currentTime):
"""Update player state"""
# Check if invincibility has expired
@@ -91,6 +104,10 @@ class Player:
"""Get current max health"""
return self._maxHealth
def set_footstep_sound(self, soundName):
"""Set the current footstep sound"""
self.footstepSound = soundName
def set_health(self, value):
"""Set health and handle death if needed."""
if self.isInvincible:

View File

@@ -4,9 +4,7 @@ class StatTracker:
self.total = {
'Bone dust': 0,
'Enemies killed': 0,
'Enemies remaining': 0,
'Coffins broken': 0,
'Coffins remaining': 0,
'Items collected': 0,
'Total time': 0
}