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:
4
files/credits.txt
Normal file
4
files/credits.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Billy Wolfe: Designer and coder.
|
||||
https://social.wolfe.casa/storm
|
||||
Source code is available at:
|
||||
https://git.stormux.org/storm/wicked-quest
|
40
files/instructions.txt
Normal file
40
files/instructions.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
Welcome to Wicked Quest
|
||||
|
||||
For years, your bones have lain in disarray, scattered about the mausoleum where you were interred.
|
||||
Some foolish mortal wandered in to your burial chamber and put you back together.
|
||||
Now, you can wonder around spreading chaos and destruction where ever you go.
|
||||
First, however, you have to make it past the dead so you can plague the living.
|
||||
You will nead some kind of weapon to make it through.
|
||||
You spot a grave digger's shovel and quickly grab it even though it's covered in rust.
|
||||
You give an evil grin, oh wait, your a skeleton, your skull is always doing that.
|
||||
|
||||
Controls
|
||||
|
||||
a: move left
|
||||
d: move right
|
||||
w: jump
|
||||
Control: attack
|
||||
f: throw jack O'lantern
|
||||
c: check bone dust
|
||||
h check health
|
||||
j: check jack O'lanterns
|
||||
l: check lives remaining
|
||||
|
||||
Notes
|
||||
|
||||
Each 5 bone dust restores 1 health.
|
||||
Each 100 bone dust gains an extra unlife.
|
||||
|
||||
Enemies
|
||||
|
||||
Goblin: Walks back and forth in his area trying to break your bones.
|
||||
Ghoul: Same behavior as goblin, but if you enter his area he will actively chase you, staying close.
|
||||
Pumpkin Catapult: Fires pumpkins at you in hopes of smashing you into bone dust.
|
||||
Skull Storm: Screaming skulls rain down causing damage if they hit you.
|
||||
Zombie: Slow moving creatures that have a chance to climb out of the open grave. They are slow moving but deadly. If they hit you you lose a life.
|
||||
|
||||
Bonuses and items
|
||||
|
||||
Bone dust: Currency of the game. Collect it to gain health and extra lives.
|
||||
Hand of Glory: Grants invincibility for a short time.
|
||||
Jack O'lantern: Throw these at your enemies to hit them from a distance.
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"level_id": 1,
|
||||
"name": "The Mausoleum",
|
||||
"description": "After years of existing as a pile of bones, someone was crazy enough to assemble your skeleton. Time to wreak some havoc! Use W to jump, A/D to move, and CTRL to attack with your shovel.",
|
||||
"description": "After years of existing as a pile of bones, someone was crazy enough to assemble your skeleton. Time to wreak some havoc!",
|
||||
"player_start": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
@@ -28,13 +28,15 @@
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x": 25,
|
||||
"x_range": [25, 30],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 3,
|
||||
"damage": 1,
|
||||
"attack_range": 1,
|
||||
"movement_range": 5
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x": 35,
|
||||
@@ -64,13 +66,15 @@
|
||||
"type": "coffin"
|
||||
},
|
||||
{
|
||||
"x": 75,
|
||||
"x_range": [75, 80],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 5,
|
||||
"damage": 2,
|
||||
"attack_range": 1,
|
||||
"movement_range": 5
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x": 85,
|
||||
@@ -107,10 +111,18 @@
|
||||
"direction": -1,
|
||||
"fire_interval": 5000,
|
||||
"range": 15
|
||||
},
|
||||
{
|
||||
"x_range": [154, 159],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
}
|
||||
],
|
||||
"boundaries": {
|
||||
"left": 0,
|
||||
"right": 160
|
||||
}
|
||||
},
|
||||
"footstep_sound": "footstep_stone"
|
||||
}
|
||||
|
@@ -21,13 +21,15 @@
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x": 25,
|
||||
"x_range": [21, 29],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 4,
|
||||
"damage": 2,
|
||||
"attack_range": 1,
|
||||
"movement_range": 5
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x": 35,
|
||||
@@ -62,13 +64,15 @@
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x": 75,
|
||||
"x_range": [71, 79],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 5,
|
||||
"damage": 2,
|
||||
"attack_range": 1,
|
||||
"movement_range": 6
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x": 85,
|
||||
@@ -109,10 +113,18 @@
|
||||
"min": 2,
|
||||
"max": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"x_range": [145, 150],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
}
|
||||
],
|
||||
"boundaries": {
|
||||
"left": 0,
|
||||
"right": 170
|
||||
}
|
||||
},
|
||||
"footstep_sound": "footstep_tall_grass"
|
||||
}
|
||||
|
238
levels/3.json
Normal file
238
levels/3.json
Normal file
@@ -0,0 +1,238 @@
|
||||
{
|
||||
"level_id": 3,
|
||||
"name": "Endless Graves",
|
||||
"description": "Graves continue in all directions as far as you can see. The dead seem restless.",
|
||||
"player_start": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"objects": [
|
||||
{
|
||||
"x_range": [1, 4],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 3,
|
||||
"sound": "coffin",
|
||||
"type": "coffin"
|
||||
},
|
||||
{
|
||||
"x_range": [6, 10],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x": 15,
|
||||
"y": 0,
|
||||
"hazard": true,
|
||||
"sound": "grave",
|
||||
"static": true,
|
||||
"zombie_spawn_chance": 25
|
||||
},
|
||||
{
|
||||
"x": 15,
|
||||
"y": 3,
|
||||
"sound": "coffin",
|
||||
"type": "coffin"
|
||||
},
|
||||
{
|
||||
"x_range": [25, 27],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x_range": [21, 31],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 5,
|
||||
"damage": 2,
|
||||
"attack_range": 1,
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x_range": [35, 50],
|
||||
"y": 12,
|
||||
"type": "skull_storm",
|
||||
"damage": 3,
|
||||
"maximum_skulls": 2,
|
||||
"frequency": {
|
||||
"min": 2,
|
||||
"max": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"x_range": [42, 44],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x": 55,
|
||||
"y": 0,
|
||||
"hazard": true,
|
||||
"sound": "grave",
|
||||
"static": true,
|
||||
"zombie_spawn_chance": 25
|
||||
},
|
||||
{
|
||||
"x_range": [60, 70],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 5,
|
||||
"damage": 2,
|
||||
"attack_range": 1,
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x_range": [75, 77],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x_range": [71, 81],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 5,
|
||||
"damage": 2,
|
||||
"attack_range": 1,
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x": 85,
|
||||
"y": 0,
|
||||
"hazard": true,
|
||||
"sound": "grave",
|
||||
"static": true,
|
||||
"zombie_spawn_chance": 28
|
||||
},
|
||||
{
|
||||
"x": 85,
|
||||
"y": 3,
|
||||
"sound": "coffin",
|
||||
"type": "coffin"
|
||||
},
|
||||
{
|
||||
"x_range": [95, 120],
|
||||
"y": 15,
|
||||
"type": "skull_storm",
|
||||
"damage": 3,
|
||||
"maximum_skulls": 2,
|
||||
"frequency": {
|
||||
"min": 2,
|
||||
"max": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"x_range": [105, 107],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x_range": [101, 111],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 6,
|
||||
"damage": 2,
|
||||
"attack_range": 1,
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x": 125,
|
||||
"y": 0,
|
||||
"hazard": true,
|
||||
"sound": "grave",
|
||||
"static": true,
|
||||
"zombie_spawn_chance": 28
|
||||
},
|
||||
{
|
||||
"x": 135,
|
||||
"y": 0,
|
||||
"hazard": true,
|
||||
"sound": "grave",
|
||||
"static": true,
|
||||
"zombie_spawn_chance": 30
|
||||
},
|
||||
{
|
||||
"x_range": [140, 150],
|
||||
"y": 0,
|
||||
"enemy_type": "goblin",
|
||||
"health": 6,
|
||||
"damage": 2,
|
||||
"attack_range": 1,
|
||||
"attack_pattern": {
|
||||
"type": "patrol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"x_range": [155, 157],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
},
|
||||
{
|
||||
"x_range": [146, 166],
|
||||
"y": 0,
|
||||
"enemy_type": "ghoul",
|
||||
"health": 10,
|
||||
"damage": 3,
|
||||
"attack_range": 2,
|
||||
"attack_pattern": {
|
||||
"type": "hunter",
|
||||
"turn_threshold": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"x_range": [165, 190],
|
||||
"y": 15,
|
||||
"type": "skull_storm",
|
||||
"damage": 4,
|
||||
"maximum_skulls": 3,
|
||||
"frequency": {
|
||||
"min": 2,
|
||||
"max": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"x": 175,
|
||||
"y": 0,
|
||||
"type": "catapult",
|
||||
"direction": -1,
|
||||
"fire_interval": 4500,
|
||||
"range": 20
|
||||
},
|
||||
{
|
||||
"x_range": [173, 176],
|
||||
"y": 3,
|
||||
"sound": "coin",
|
||||
"collectible": true,
|
||||
"static": true
|
||||
}
|
||||
],
|
||||
"boundaries": {
|
||||
"left": 0,
|
||||
"right": 200
|
||||
},
|
||||
"footstep_sound": "footstep_tall_grass"
|
||||
}
|
BIN
sounds/footstep_stone.ogg
(Stored with Git LFS)
Normal file
BIN
sounds/footstep_stone.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
sounds/footstep_tall_grass.ogg
(Stored with Git LFS)
Normal file
BIN
sounds/footstep_tall_grass.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
sounds/ghoul.ogg
(Stored with Git LFS)
Normal file
BIN
sounds/ghoul.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
sounds/ghoul_dies.ogg
(Stored with Git LFS)
Normal file
BIN
sounds/ghoul_dies.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
sounds/zombie.ogg
(Stored with Git LFS)
BIN
sounds/zombie.ogg
(Stored with Git LFS)
Binary file not shown.
BIN
sounds/zombie_dies.ogg
(Stored with Git LFS)
Normal file
BIN
sounds/zombie_dies.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -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:
|
||||
|
81
src/enemy.py
81
src/enemy.py
@@ -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)
|
||||
|
@@ -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,
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -65,6 +65,14 @@ class WickedQuest:
|
||||
player.xPos += currentSpeed
|
||||
player.facingRight = True
|
||||
|
||||
# Handle footsteps
|
||||
if movementDistance > 0 and not player.isJumping:
|
||||
player.distanceSinceLastStep += movementDistance
|
||||
if player.should_play_footstep(currentTime):
|
||||
play_sound(self.sounds[player.footstepSound])
|
||||
player.distanceSinceLastStep = 0
|
||||
player.lastStepTime = currentTime
|
||||
|
||||
# Status queries
|
||||
if keys[pygame.K_c]:
|
||||
speak(f"{player.get_coins()} gbone dust")
|
||||
@@ -84,13 +92,6 @@ class WickedQuest:
|
||||
if (keys[pygame.K_LCTRL] or keys[pygame.K_RCTRL]) and player.start_attack(currentTime):
|
||||
play_sound(self.sounds[player.currentWeapon.attackSound])
|
||||
|
||||
# Play footstep sounds if moving and not jumping
|
||||
if movementDistance > 0 and not player.isJumping:
|
||||
player.distanceSinceLastStep += movementDistance
|
||||
if player.distanceSinceLastStep >= player.stepDistance:
|
||||
play_sound(self.sounds['footstep'])
|
||||
player.distanceSinceLastStep = 0
|
||||
|
||||
# Handle jumping
|
||||
if keys[pygame.K_w] and not player.isJumping:
|
||||
player.isJumping = True
|
||||
@@ -100,9 +101,10 @@ class WickedQuest:
|
||||
# Check if jump should end
|
||||
if player.isJumping and currentTime - player.jumpStartTime >= player.jumpDuration:
|
||||
player.isJumping = False
|
||||
play_sound(self.sounds['footstep'])
|
||||
play_sound(self.sounds[player.footstepSound]) # Landing sound
|
||||
# Reset step distance tracking after landing
|
||||
player.distanceSinceLastStep = 0
|
||||
player.lastStepTime = currentTime
|
||||
|
||||
def display_level_stats(self, timeTaken):
|
||||
"""Display level completion statistics."""
|
||||
@@ -214,6 +216,8 @@ class WickedQuest:
|
||||
self.player = None # Reset player for new game
|
||||
if self.load_level(1):
|
||||
self.game_loop()
|
||||
elif choice == "learn_sounds":
|
||||
choice = learn_sounds(self.sounds)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Reference in New Issue
Block a user