mirror of
https://github.com/BreizhHardware/project_sanic.git
synced 2026-03-18 21:50:33 +01:00
Feat(Enemy) - Update enemy sizes and add boss behavior; refactor loading and scaling of enemy sprites.
This commit is contained in:
@@ -177,7 +177,7 @@
|
|||||||
"attack_interval": 2.0,
|
"attack_interval": 2.0,
|
||||||
"attack_range": 300,
|
"attack_range": 300,
|
||||||
"sprite_sheet": "assets/map/enemy/turret.gif",
|
"sprite_sheet": "assets/map/enemy/turret.gif",
|
||||||
"size": [50,100]
|
"size": [80,80]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "enemy3_01",
|
"id": "enemy3_01",
|
||||||
@@ -206,7 +206,7 @@
|
|||||||
"attack_interval": 2.0,
|
"attack_interval": 2.0,
|
||||||
"attack_range": 300,
|
"attack_range": 300,
|
||||||
"sprite_sheet": "assets/map/enemy/turret.gif",
|
"sprite_sheet": "assets/map/enemy/turret.gif",
|
||||||
"size": [50,100]
|
"size": [80,80]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -272,7 +272,7 @@
|
|||||||
"attack_interval": 2.0,
|
"attack_interval": 2.0,
|
||||||
"attack_range": 300,
|
"attack_range": 300,
|
||||||
"sprite_sheet": "assets/map/enemy/turret.gif",
|
"sprite_sheet": "assets/map/enemy/turret.gif",
|
||||||
"size": [50,100]
|
"size": [80,80]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "enemy2_02",
|
"id": "enemy2_02",
|
||||||
@@ -343,7 +343,7 @@
|
|||||||
"attack_interval": 2.0,
|
"attack_interval": 2.0,
|
||||||
"attack_range": 300,
|
"attack_range": 300,
|
||||||
"sprite_sheet": "assets/map/enemy/turret.gif",
|
"sprite_sheet": "assets/map/enemy/turret.gif",
|
||||||
"size": [50,100]
|
"size": [80,80]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "enemy1_05",
|
"id": "enemy1_05",
|
||||||
@@ -356,7 +356,7 @@
|
|||||||
"attack_interval": 2.0,
|
"attack_interval": 2.0,
|
||||||
"attack_range": 300,
|
"attack_range": 300,
|
||||||
"sprite_sheet": "assets/map/enemy/turret.gif",
|
"sprite_sheet": "assets/map/enemy/turret.gif",
|
||||||
"size": [50,100]
|
"size": [80,80]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "enemy1_06",
|
"id": "enemy1_06",
|
||||||
|
|||||||
@@ -135,6 +135,19 @@
|
|||||||
"attack_interval": 2.0,
|
"attack_interval": 2.0,
|
||||||
"attack_range": 300,
|
"attack_range": 300,
|
||||||
"sprite_sheet": "assets/map/enemy/turret_enemy.png"
|
"sprite_sheet": "assets/map/enemy/turret_enemy.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "boss",
|
||||||
|
"type": "boss",
|
||||||
|
"x": 2000,
|
||||||
|
"y": 0,
|
||||||
|
"health": 3,
|
||||||
|
"damage": 1,
|
||||||
|
"behavior": "boss",
|
||||||
|
"attack_interval": 1.0,
|
||||||
|
"attack_range": 1000,
|
||||||
|
"sprite_sheet": "assets/map/enemy/boss.gif",
|
||||||
|
"size": [200,200]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from src.Entity.Projectile import Projectile
|
|||||||
class Enemy(Entity):
|
class Enemy(Entity):
|
||||||
def __init__(self, enemy_data):
|
def __init__(self, enemy_data):
|
||||||
self.size = enemy_data.get("size", [50, 50])
|
self.size = enemy_data.get("size", [50, 50])
|
||||||
|
print(self.size)
|
||||||
super().__init__(self.size)
|
super().__init__(self.size)
|
||||||
|
|
||||||
# Base attributes
|
# Base attributes
|
||||||
@@ -30,13 +31,13 @@ class Enemy(Entity):
|
|||||||
sprite_path = enemy_data.get("sprite_sheet", "assets/enemy/default_enemy.png")
|
sprite_path = enemy_data.get("sprite_sheet", "assets/enemy/default_enemy.png")
|
||||||
|
|
||||||
# Load sprite sheet or GIF depending on enemy type and file extension
|
# Load sprite sheet or GIF depending on enemy type and file extension
|
||||||
if sprite_path.lower().endswith(".gif") and self.enemy_type == "turret":
|
if sprite_path.lower().endswith(".gif"):
|
||||||
self.load_gif_frames(sprite_path)
|
self.load_gif_frames(sprite_path, self.size)
|
||||||
if self.frames:
|
if self.frames:
|
||||||
self.surf = self.frames[0]
|
self.surf = self.frames[0]
|
||||||
else:
|
else:
|
||||||
# Default sprite
|
# Default sprite
|
||||||
self.surf = pygame.Surface((40, 40))
|
self.surf = pygame.Surface(self.size)
|
||||||
self.surf.fill((255, 0, 0))
|
self.surf.fill((255, 0, 0))
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
@@ -44,7 +45,7 @@ class Enemy(Entity):
|
|||||||
self.surf = pygame.transform.scale(self.surf, self.size)
|
self.surf = pygame.transform.scale(self.surf, self.size)
|
||||||
except:
|
except:
|
||||||
# Default sprite
|
# Default sprite
|
||||||
self.surf = pygame.Surface((40, 40))
|
self.surf = pygame.Surface(self.size)
|
||||||
self.surf.fill((255, 0, 0))
|
self.surf.fill((255, 0, 0))
|
||||||
|
|
||||||
# Initial rectangle
|
# Initial rectangle
|
||||||
@@ -63,7 +64,7 @@ class Enemy(Entity):
|
|||||||
self.is_attacking = False
|
self.is_attacking = False
|
||||||
self.detected_player = False
|
self.detected_player = False
|
||||||
|
|
||||||
def load_gif_frames(self, gif_path):
|
def load_gif_frames(self, gif_path, size=(80, 80)):
|
||||||
"""Load frames from a GIF file"""
|
"""Load frames from a GIF file"""
|
||||||
try:
|
try:
|
||||||
gif = Image.open(gif_path)
|
gif = Image.open(gif_path)
|
||||||
@@ -73,7 +74,7 @@ class Enemy(Entity):
|
|||||||
frame_surface = pygame.image.fromstring(
|
frame_surface = pygame.image.fromstring(
|
||||||
frame.convert("RGBA").tobytes(), frame.size, "RGBA"
|
frame.convert("RGBA").tobytes(), frame.size, "RGBA"
|
||||||
)
|
)
|
||||||
frame_surface = pygame.transform.scale(frame_surface, (80, 80))
|
frame_surface = pygame.transform.scale(frame_surface, size)
|
||||||
self.frames.append(frame_surface)
|
self.frames.append(frame_surface)
|
||||||
frame_count += 1
|
frame_count += 1
|
||||||
|
|
||||||
@@ -92,9 +93,11 @@ class Enemy(Entity):
|
|||||||
self.chase(player)
|
self.chase(player)
|
||||||
elif self.behavior == "stationary" and player:
|
elif self.behavior == "stationary" and player:
|
||||||
self.stationary_attack(player)
|
self.stationary_attack(player)
|
||||||
|
elif self.behavior == "boss" and player:
|
||||||
|
self.boss(player)
|
||||||
|
|
||||||
# Animation management for turret enemies
|
# Animation management for turret enemies
|
||||||
if self.enemy_type == "turret" and self.frames:
|
if (self.enemy_type == "turret" or self.enemy_type == "boss") and self.frames:
|
||||||
self.animation_timer += dt
|
self.animation_timer += dt
|
||||||
if self.animation_timer >= self.animation_speed:
|
if self.animation_timer >= self.animation_speed:
|
||||||
self.animation_timer = 0
|
self.animation_timer = 0
|
||||||
@@ -159,7 +162,7 @@ class Enemy(Entity):
|
|||||||
self.is_attacking = True
|
self.is_attacking = True
|
||||||
|
|
||||||
# For turret-type enemies, create a projectile
|
# For turret-type enemies, create a projectile
|
||||||
if self.enemy_type == "turret":
|
if self.enemy_type == "turret" or self.enemy_type == "boss":
|
||||||
# Calculate direction to player
|
# Calculate direction to player
|
||||||
direction = vec(player.pos.x - self.pos.x, player.pos.y - self.pos.y)
|
direction = vec(player.pos.x - self.pos.x, player.pos.y - self.pos.y)
|
||||||
|
|
||||||
@@ -209,3 +212,27 @@ class Enemy(Entity):
|
|||||||
# KB LOL MINECRAFT
|
# KB LOL MINECRAFT
|
||||||
knockback_direction = 1 if player.pos.x > self.pos.x else -1
|
knockback_direction = 1 if player.pos.x > self.pos.x else -1
|
||||||
player.vel.x = knockback_direction * 8
|
player.vel.x = knockback_direction * 8
|
||||||
|
|
||||||
|
def boss(self, player, FPS=60):
|
||||||
|
"""
|
||||||
|
Boss behavior: combine horizontal chase with turret-like attacks
|
||||||
|
"""
|
||||||
|
# Follow the player horizontally (x axis)
|
||||||
|
if abs(player.pos.x - self.pos.x) > 50:
|
||||||
|
direction = 1 if player.pos.x > self.pos.x else -1
|
||||||
|
self.pos.x += direction * self.speed
|
||||||
|
self.direction = direction
|
||||||
|
|
||||||
|
# Attack the player if within range
|
||||||
|
distance_to_player = vec(
|
||||||
|
player.pos.x - self.pos.x, player.pos.y - self.pos.y
|
||||||
|
).length()
|
||||||
|
|
||||||
|
if distance_to_player <= self.attack_range:
|
||||||
|
self.attack_timer += 1 / FPS
|
||||||
|
|
||||||
|
if self.attack_timer >= self.attack_interval:
|
||||||
|
self.attack_timer = 0
|
||||||
|
self.attack(player)
|
||||||
|
|
||||||
|
self.detected_player = distance_to_player <= self.detection_radius
|
||||||
|
|||||||
Reference in New Issue
Block a user