Update enemy.py

main
Filips Kalniņš 2026-03-16 07:44:52 +00:00
parent 869d2ea540
commit 07f589639f
1 changed files with 37 additions and 28 deletions

View File

@ -1,29 +1,39 @@
import pygame import pygame
from settings import * from settings import *
class Enemy: class Enemy:
def __init__(self, x, y): def __init__(self, x, y):
# Position & physics
self.pos = pygame.Vector2(x, y)
self.rect = pygame.Rect(x, y, 28, 48) self.rect = pygame.Rect(x, y, 28, 48)
self.velocity = pygame.Vector2(0, 0) self.velocity = pygame.Vector2(0, 0)
self.pos = pygame.Vector2(x, y)
# Health
self.health = ENEMY_HEALTH self.health = ENEMY_HEALTH
self.max_health = ENEMY_HEALTH self.max_health = ENEMY_HEALTH
self.alive = True
# Combat
self.attack_rect = pygame.Rect(x, y, 60, 60)
self.attack_damage = ENEMY_ATTACK_DAMAGE
self.attack_range = ENEMY_ATTACK_RANGE
# Timers
self.knockback_timer = 0 self.knockback_timer = 0
self.invulnerable_timer = 0 self.invulnerable_timer = 0
# Attack hitbox
self.attack_rect = pygame.Rect(x, y, 60, 60)
def update(self, dt, world, player): def update(self, dt, world, player):
if not self.alive:
return
dt = min(dt, 0.05) dt = min(dt, 0.05)
# Apply gravity (FIX for flying) # Gravity
self.velocity.y += ENEMY_GRAVITY * dt self.velocity.y += ENEMY_GRAVITY * dt
if self.velocity.y > MAX_FALL_SPEED: if self.velocity.y > MAX_FALL_SPEED:
self.velocity.y = MAX_FALL_SPEED self.velocity.y = MAX_FALL_SPEED
# Basic AI: follow player # Basic AI: move toward player
if self.knockback_timer <= 0: if self.knockback_timer <= 0:
if player.rect.x < self.rect.x: if player.rect.x < self.rect.x:
self.velocity.x = -ENEMY_SPEED self.velocity.x = -ENEMY_SPEED
@ -32,83 +42,82 @@ class Enemy:
else: else:
self.knockback_timer -= dt self.knockback_timer -= dt
# Update position # Update horizontal position
self.pos.x += self.velocity.x * dt self.pos.x += self.velocity.x * dt
self.rect.x = round(self.pos.x) self.rect.x = round(self.pos.x)
self.handle_horizontal_collisions(world) self.handle_horizontal_collisions(world)
# Update vertical position
self.pos.y += self.velocity.y * dt self.pos.y += self.velocity.y * dt
self.rect.y = round(self.pos.y) self.rect.y = round(self.pos.y)
self.handle_vertical_collisions(world) self.handle_vertical_collisions(world)
# Update attack rect position # Update attack rectangle
self.attack_rect.centerx = self.rect.centerx self.attack_rect.center = self.rect.center
self.attack_rect.centery = self.rect.centery
# Decay invulnerability # Decay invulnerability
if self.invulnerable_timer > 0: if self.invulnerable_timer > 0:
self.invulnerable_timer -= dt self.invulnerable_timer -= dt
# Check death
if self.health <= 0:
self.alive = False
def handle_horizontal_collisions(self, world): def handle_horizontal_collisions(self, world):
"""Handle horizontal collision"""
for tile in world.get_nearby_tiles(self.rect): for tile in world.get_nearby_tiles(self.rect):
if tile["solid"] and self.rect.colliderect(tile["rect"]): if tile["solid"] and self.rect.colliderect(tile["rect"]):
if self.velocity.x > 0: if self.velocity.x > 0:
self.rect.right = tile["rect"].left self.rect.right = tile["rect"].left
elif self.velocity.x < 0: elif self.velocity.x < 0:
self.rect.left = tile["rect"].right self.rect.left = tile["rect"].right
self.pos.x = self.rect.x self.pos.x = self.rect.x
self.velocity.x = 0 self.velocity.x = 0
def handle_vertical_collisions(self, world): def handle_vertical_collisions(self, world):
"""Handle vertical collision"""
for tile in world.get_nearby_tiles(self.rect): for tile in world.get_nearby_tiles(self.rect):
if tile["solid"] and self.rect.colliderect(tile["rect"]): if tile["solid"] and self.rect.colliderect(tile["rect"]):
if self.velocity.y > 0: if self.velocity.y > 0:
self.rect.bottom = tile["rect"].top self.rect.bottom = tile["rect"].top
elif self.velocity.y < 0: elif self.velocity.y < 0:
self.rect.top = tile["rect"].bottom self.rect.top = tile["rect"].bottom
self.pos.y = self.rect.y self.pos.y = self.rect.y
self.velocity.y = 0 self.velocity.y = 0
def take_damage(self, damage, direction): def take_damage(self, damage, direction):
"""Take damage and apply knockback""" if self.invulnerable_timer > 0 or not self.alive:
if self.invulnerable_timer > 0:
return return
self.health -= damage self.health -= damage
self.invulnerable_timer = 0.3 self.invulnerable_timer = 0.3
self.knockback_timer = 0.15 self.knockback_timer = 0.15
# Apply knockback (affected by resistance) # Knockback
knockback_force = 400 * ENEMY_KNOCKBACK_RESISTANCE knockback_force = 400 * ENEMY_KNOCKBACK_RESISTANCE
self.velocity.x = direction * knockback_force self.velocity.x = direction * knockback_force
self.velocity.y = -300 # Slight upward knockback self.velocity.y = -300
if self.health <= 0:
self.alive = False
def draw(self, screen, camera): def draw(self, screen, camera):
if not self.alive:
return
draw_rect = camera.apply(self.rect) draw_rect = camera.apply(self.rect)
# Flash when invulnerable # Flash when invulnerable
if self.invulnerable_timer > 0: color = (100, 100, 255) if self.invulnerable_timer > 0 else (0, 0, 255)
color = (100, 100, 255) # Light blue
else:
color = (0, 0, 255) # Blue
pygame.draw.rect(screen, color, draw_rect) pygame.draw.rect(screen, color, draw_rect)
if SHOW_COLLIDERS: if SHOW_COLLIDERS:
pygame.draw.rect(screen, (0, 255, 0), draw_rect, 2) pygame.draw.rect(screen, (0, 255, 0), draw_rect, 2)
# Draw attack hitbox
attack_draw_rect = camera.apply(self.attack_rect) attack_draw_rect = camera.apply(self.attack_rect)
pygame.draw.rect(screen, (255, 0, 0), attack_draw_rect, 1) pygame.draw.rect(screen, (255, 0, 0), attack_draw_rect, 1)
# Draw health bar # Health bar
health_bar_width = 28 health_bar_width = 28
health_bar_height = 4 health_bar_height = 4
health_percent = self.health / self.max_health health_percent = max(0, self.health / self.max_health)
health_bar_rect = pygame.Rect( health_bar_rect = pygame.Rect(
draw_rect.x, draw_rect.x,
draw_rect.y - 8, draw_rect.y - 8,