More content added, weapons, coin collecting, basic combat.
This commit is contained in:
105
src/enemy.py
Normal file
105
src/enemy.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from libstormgames import *
|
||||
from src.object import Object
|
||||
import pygame
|
||||
|
||||
|
||||
class Enemy(Object):
|
||||
def __init__(self, xRange, y, enemyType, sounds, **kwargs):
|
||||
# Initialize base object properties
|
||||
super().__init__(
|
||||
xRange,
|
||||
y,
|
||||
f"{enemyType}", # Base sound for ambient noise
|
||||
isStatic=False,
|
||||
isHazard=True
|
||||
)
|
||||
|
||||
# Enemy specific properties
|
||||
self.enemyType = enemyType
|
||||
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 # Slightly slower than player
|
||||
self.patrolStart = self.xRange[0]
|
||||
self.patrolEnd = self.xRange[0] + self.movementRange
|
||||
self.lastAttackTime = 0
|
||||
self.attackCooldown = 1000 # 1 second between attacks
|
||||
|
||||
@property
|
||||
def xPos(self):
|
||||
"""Current x position"""
|
||||
return self._currentX if hasattr(self, '_currentX') else self.xRange[0]
|
||||
|
||||
@xPos.setter
|
||||
def xPos(self, value):
|
||||
"""Set current x position"""
|
||||
self._currentX = value
|
||||
|
||||
def update(self, currentTime, player):
|
||||
"""Update enemy position and handle attacks"""
|
||||
if not self.isActive or self.health <= 0:
|
||||
return
|
||||
|
||||
# Update position based on patrol behavior
|
||||
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
|
||||
|
||||
# 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
|
||||
if currentTime - self.lastAttackTime < self.attackCooldown:
|
||||
return False
|
||||
|
||||
# Don't attack if player is jumping
|
||||
if player.isJumping:
|
||||
return False
|
||||
|
||||
# Check if player is in range and on same side we're facing
|
||||
distance = abs(player.xPos - self.xPos)
|
||||
tolerance = 0.5 # Same tolerance as we used for the grave
|
||||
|
||||
if distance <= (self.attackRange + tolerance):
|
||||
# Only attack if we're facing the right way
|
||||
playerOnRight = player.xPos > self.xPos
|
||||
return playerOnRight == self.movingRight
|
||||
|
||||
return False
|
||||
|
||||
def attack(self, currentTime, player):
|
||||
"""Perform attack on player"""
|
||||
self.lastAttackTime = currentTime
|
||||
# Play attack sound
|
||||
attackSound = f"{self.enemyType}_attack"
|
||||
if attackSound in self.sounds:
|
||||
self.sounds[attackSound].play()
|
||||
# Deal damage to player
|
||||
player.set_health(player.get_health() - self.damage)
|
||||
speak(f"The {self.enemyType} hits you!")
|
||||
|
||||
def take_damage(self, amount):
|
||||
"""Handle enemy taking damage"""
|
||||
self.health -= amount
|
||||
if self.health <= 0:
|
||||
self.die()
|
||||
|
||||
def die(self):
|
||||
"""Handle enemy death"""
|
||||
self.isActive = False
|
||||
if self.channel:
|
||||
obj_stop(self.channel)
|
||||
self.channel = None
|
Reference in New Issue
Block a user