Files
wicked-quest/src/player.py

169 lines
5.6 KiB
Python

import pygame
from libstormgames import *
from src.stat_tracker import StatTracker
from src.weapon import Weapon
class Player:
def __init__(self, xPos, yPos, sounds):
self.sounds = sounds
# Movement attributes
self.xPos = xPos
self.yPos = yPos
self.moveSpeed = 0.05
self.jumpDuration = 1000 # Jump duration in milliseconds
self.jumpStartTime = 0
self.isJumping = False
self.facingRight = True
# Stats and tracking
self._health = 10
self._maxHealth = 10
self._lives = 1
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 = []
self.collectedItems = []
self._coins = 0
self._jack_o_lantern_count = 0
# Combat related attributes
self.weapons = []
self.currentWeapon = None
self.isAttacking = False
self.lastAttackTime = 0
# Power-up states
self.isInvincible = False
self.invincibilityStartTime = 0
self.invincibilityDuration = 10000 # 10 seconds of invincibility
# Initialize starting weapon (rusty shovel)
self.add_weapon(Weapon(
name="rusty_shovel",
damage=2,
range=2,
attackSound="player_shovel_attack",
hitSound="player_shovel_hit",
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
if self.isInvincible and currentTime - self.invincibilityStartTime >= self.invincibilityDuration:
self.isInvincible = False
speak("Invincibility wore off!")
def start_invincibility(self):
"""Activate invincibility from Hand of Glory"""
self.isInvincible = True
self.invincibilityStartTime = pygame.time.get_ticks()
def get_jack_o_lanterns(self):
"""Get number of jack o'lanterns"""
return self._jack_o_lantern_count
def add_jack_o_lantern(self):
"""Add a jack o'lantern"""
self._jack_o_lantern_count += 1
def throw_projectile(self):
"""Throw a jack o'lantern if we have any"""
if self.get_jack_o_lanterns() <= 0:
return None
self._jack_o_lantern_count -= 1
return {
'type': 'jack_o_lantern',
'start_x': self.xPos,
'direction': 1 if self.facingRight else -1
}
def get_health(self):
"""Get current health"""
return self._health
def get_max_health(self):
"""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:
return # No damage while invincible
old_health = self._health
self._health = max(0, value) # Health can't go below 0
if self._health == 0 and old_health > 0:
self._lives -= 1
# Stop all current sounds before playing death sound
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")
def set_max_health(self, value):
"""Set max health"""
self._maxHealth = value
def get_coins(self):
"""Get remaining coins"""
return self._coins
def get_lives(self):
"""Get remaining lives"""
return self._lives
def add_weapon(self, weapon):
"""Add a new weapon to inventory and equip if first weapon"""
self.weapons.append(weapon)
if len(self.weapons) == 1: # If this is our first weapon, equip it
self.equip_weapon(weapon)
def equip_weapon(self, weapon):
"""Equip a specific weapon"""
if weapon in self.weapons:
self.currentWeapon = weapon
def add_item(self, item):
"""Add an item to inventory"""
self.inventory.append(item)
self.collectedItems.append(item)
def start_attack(self, currentTime):
"""Attempt to start an attack with the current weapon"""
if self.currentWeapon and self.currentWeapon.start_attack(currentTime):
self.isAttacking = True
self.lastAttackTime = currentTime
return True
return False
def get_attack_range(self, currentTime):
"""Get the current attack's range based on position and facing direction"""
if not self.currentWeapon or not self.currentWeapon.is_attack_active(currentTime):
return None
return self.currentWeapon.get_attack_range(self.xPos, self.facingRight)