Files
armorpaint/base/sources/iron_tilesheet.c
T
2026-03-02 13:23:58 +01:00

101 lines
2.4 KiB
C

#include "iron_tilesheet.h"
#include "iron_gc.h"
#include <math.h>
#include <string.h>
tilesheet_data_t *tilesheet_datas = NULL;
i32 tilesheet_datas_count = 0;
f32 sys_real_delta(void);
f32 math_floor(f32 x);
tilesheet_t *tilesheet_create(char *scene_name, char *tilesheet_ref, char *tilesheet_action_ref) {
tilesheet_t *t = gc_alloc(sizeof(tilesheet_t));
t->ready = false;
for (i32 i = 0; i < tilesheet_datas_count; ++i) {
tilesheet_data_t *ts = &tilesheet_datas[i];
if (strcmp(ts->name, tilesheet_ref) == 0) {
t->raw = ts;
tilesheet_play(t, tilesheet_action_ref, NULL);
t->ready = true;
break;
}
}
return t;
}
void tilesheet_play(tilesheet_t *self, char *action_ref, void (*on_action_complete)(void)) {
self->on_action_complete = on_action_complete;
for (i32 i = 0; i < self->raw->actions_count; ++i) {
tilesheet_action_t *a = &self->raw->actions[i];
if (strcmp(a->name, action_ref) == 0) {
self->action = a;
break;
}
}
tilesheet_set_frame(self, self->action->start);
self->paused = false;
self->time = 0.0f;
}
void tilesheet_pause(tilesheet_t *self) {
self->paused = true;
}
void tilesheet_resume(tilesheet_t *self) {
self->paused = false;
}
void tilesheet_set_frame_offset(tilesheet_t *self, i32 frame) {
tilesheet_set_frame(self, self->action->start + frame);
self->paused = false;
}
i32 tilesheet_get_frame_offset(tilesheet_t *self) {
return self->frame - self->action->start;
}
void tilesheet_update(tilesheet_t *self) {
if (!self->ready || self->paused) {
return;
}
self->time += sys_real_delta();
f32 frame_time = 1.0f / self->raw->framerate;
i32 frames_to_advance = 0;
while (self->time >= frame_time) {
self->time -= frame_time;
frames_to_advance++;
}
if (frames_to_advance != 0) {
tilesheet_set_frame(self, self->frame + frames_to_advance);
}
}
void tilesheet_set_frame(tilesheet_t *self, i32 f) {
self->frame = f;
// Action end
if (self->frame > self->action->end) {
if (self->on_action_complete != NULL) {
self->on_action_complete();
}
if (self->action->loop) {
tilesheet_set_frame(self, self->action->start);
}
else {
self->paused = true;
}
return;
}
i32 tx = self->frame % self->raw->tiles_x;
i32 ty = (i32)math_floor((f32)self->frame / self->raw->tiles_x);
self->tile_x = tx * (1.0f / self->raw->tiles_x);
self->tile_y = ty * (1.0f / self->raw->tiles_y);
}