forked from NotAShelf/rogged
render: use tileset atlas for all entity and tile rendering; anims
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Idb42cff72368e26d8d44db79ba9c413a6a6a6964
This commit is contained in:
parent
2f5c959500
commit
5b640dcefd
7 changed files with 556 additions and 90 deletions
66
src/enemy.c
66
src/enemy.c
|
|
@ -5,6 +5,7 @@
|
|||
#include "movement.h"
|
||||
#include "rng/rng.h"
|
||||
#include "settings.h"
|
||||
#include "tileset/tileset.h"
|
||||
#include <string.h>
|
||||
|
||||
// Forward declaration
|
||||
|
|
@ -25,6 +26,12 @@ void enemy_spawn(Enemy enemies[], int *count, Map *map, Player *p, int floor) {
|
|||
if (floor >= 4)
|
||||
max_type = 3;
|
||||
|
||||
// Get the player's starting room (first room) to exclude from enemy spawn
|
||||
Room *start_room = NULL;
|
||||
if (map->room_count > 0) {
|
||||
start_room = &map->rooms[0];
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_enemies; i++) {
|
||||
// Find random floor position
|
||||
int ex, ey;
|
||||
|
|
@ -35,6 +42,14 @@ void enemy_spawn(Enemy enemies[], int *count, Map *map, Player *p, int floor) {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Don't spawn in the starting room
|
||||
if (start_room != NULL) {
|
||||
if (ex >= start_room->x && ex < start_room->x + start_room->w && ey >= start_room->y &&
|
||||
ey < start_room->y + start_room->h) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't spawn on other enemies
|
||||
if (is_enemy_at(enemies, *count, ex, ey)) {
|
||||
continue;
|
||||
|
|
@ -125,6 +140,27 @@ void enemy_spawn(Enemy enemies[], int *count, Map *map, Player *p, int floor) {
|
|||
}
|
||||
e.cooldown = e.speed;
|
||||
|
||||
// Initialize animation state
|
||||
e.anim_state = ENEMY_ANIM_IDLE;
|
||||
e.anim_frame = 0;
|
||||
e.anim_timer = 0;
|
||||
e.facing_right = (e.position.x < p->position.x) ? 1 : 0;
|
||||
// Set sprite tile ID based on enemy type
|
||||
switch (e.type) {
|
||||
case ENEMY_GOBLIN:
|
||||
e.sprite_tile_id = SPRITE_ENEMY_GOBLIN;
|
||||
break;
|
||||
case ENEMY_SKELETON:
|
||||
e.sprite_tile_id = SPRITE_ENEMY_SKELETON;
|
||||
break;
|
||||
case ENEMY_ORC:
|
||||
e.sprite_tile_id = SPRITE_ENEMY_ORC;
|
||||
break;
|
||||
default:
|
||||
e.sprite_tile_id = SPRITE_ENEMY_GOBLIN;
|
||||
break;
|
||||
}
|
||||
|
||||
enemies[i] = e;
|
||||
(*count)++;
|
||||
}
|
||||
|
|
@ -275,6 +311,9 @@ void enemy_act(Enemy *e, Player *p, Map *map, Enemy *all_enemies, int enemy_coun
|
|||
|
||||
// Attack if adjacent to player
|
||||
if (can_see && can_see_entity(map, e->position.x, e->position.y, p->position.x, p->position.y, 1)) {
|
||||
e->anim_state = ENEMY_ANIM_ATTACK;
|
||||
e->anim_timer = 12;
|
||||
e->facing_right = (e->position.x < p->position.x) ? 1 : 0;
|
||||
combat_enemy_attack(e, p);
|
||||
propagate_alert(e, all_enemies, enemy_count);
|
||||
return;
|
||||
|
|
@ -282,14 +321,30 @@ void enemy_act(Enemy *e, Player *p, Map *map, Enemy *all_enemies, int enemy_coun
|
|||
|
||||
// Move toward player if visible
|
||||
if (can_see) {
|
||||
int old_x = e->position.x;
|
||||
int old_y = e->position.y;
|
||||
enemy_move_toward_player(e, p, map, all_enemies, enemy_count);
|
||||
if (e->position.x != old_x || e->position.y != old_y) {
|
||||
e->anim_state = ENEMY_ANIM_WALK;
|
||||
e->anim_timer = 8;
|
||||
e->facing_right = (e->position.x < p->position.x) ? 1 : 0;
|
||||
}
|
||||
propagate_alert(e, all_enemies, enemy_count);
|
||||
return;
|
||||
}
|
||||
|
||||
// If alert but can't see player, move toward last known position
|
||||
if (e->alert) {
|
||||
int old_x = e->position.x;
|
||||
int old_y = e->position.y;
|
||||
enemy_move_to_last_known(e, map, all_enemies, enemy_count);
|
||||
if (e->position.x != old_x || e->position.y != old_y) {
|
||||
e->anim_state = ENEMY_ANIM_WALK;
|
||||
e->anim_timer = 8;
|
||||
if (e->position.x != old_x) {
|
||||
e->facing_right = (e->position.x < old_x) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -304,6 +359,17 @@ void enemy_update_all(Enemy enemies[], int count, Player *p, Map *map) {
|
|||
if (!e->alive)
|
||||
continue;
|
||||
|
||||
// Update animation timer
|
||||
if (e->anim_timer > 0) {
|
||||
e->anim_timer--;
|
||||
if (e->anim_timer <= 0) {
|
||||
e->anim_state = ENEMY_ANIM_IDLE;
|
||||
e->anim_frame = 0;
|
||||
} else if (e->anim_state == ENEMY_ANIM_WALK) {
|
||||
e->anim_frame = (e->anim_timer / 4) % 2;
|
||||
}
|
||||
}
|
||||
|
||||
e->cooldown -= e->speed;
|
||||
if (e->cooldown <= 0) {
|
||||
enemy_act(e, p, map, enemies, count);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue