From a2c225bf64b83c330b920b5844b5102b03207ef5 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 28 Jul 2024 09:24:07 +0900 Subject: [PATCH] vmSprite changes for DALK Gaiden * SetFind(2) lets the sprite to participate in hit testing even if it is not visible. * SetAnime() respects frame_s and frame_e parameters. Sprites animate only when `current` is within the range of [frame_s, frame_e]. * SetCurrent() resets animation state. --- src/hll/vmSprite.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/hll/vmSprite.c b/src/hll/vmSprite.c index cda19a0..9e3d803 100644 --- a/src/hll/vmSprite.c +++ b/src/hll/vmSprite.c @@ -35,12 +35,21 @@ struct child_surface { }; struct animation { + int frame_s; + int frame_e; int nr_frames; int current_frame; + uint64_t time_origin; int total_frame_time; int frame_times[]; }; +enum findability { + NOT_FINDABLE = 0, + FINDABLE_WHEN_VISIBLE = 1, + ALWAYS_FINDABLE = 2 +}; + struct vm_sprite { struct sprite sp; int surface; @@ -48,7 +57,7 @@ struct vm_sprite { Rectangle rect; int current; int id; - bool findable; + enum findability findability; struct animation *anime; struct id_pool children; }; @@ -77,7 +86,11 @@ static void update_animation(void) struct vm_sprite *sp = id_pool_get(&pool, id); if (!sp || !sp->anime) continue; - int t = now % sp->anime->total_frame_time; + if (sp->current < sp->anime->frame_s || sp->current > sp->anime->frame_e) { + sp->anime->current_frame = 0; + continue; + } + int t = (now - sp->anime->time_origin) % sp->anime->total_frame_time; int frame; for (frame = 0; t >= sp->anime->frame_times[frame]; frame++) t -= sp->anime->frame_times[frame]; @@ -158,6 +171,7 @@ static cJSON *vm_sprite_to_json(struct sprite *_sp, bool verbose) cJSON_AddNumberToObject(sprite, "type", sp->type); cJSON_AddItemToObjectCS(sprite, "rect", rectangle_to_json(&sp->rect, verbose)); cJSON_AddNumberToObject(sprite, "current", sp->current); + cJSON_AddNumberToObject(sprite, "findability", sp->findability); cJSON_AddItemToObjectCS(sprite, "children", children = cJSON_CreateArray()); for (int id = id_pool_get_first(&sp->children); id >= 0; id = id_pool_get_next(&sp->children, id)) { @@ -278,6 +292,9 @@ static int vmSprite_SetCurrent(int sprite, int current) return 0; if (sp->current != current) { sp->current = current; + if (sp->anime) { + sp->anime->time_origin = SDL_GetTicks64(); + } vm_sprite_dirty(sp); } return 1; @@ -357,7 +374,7 @@ static void vmSprite_SetFind(int sprite, int find) { struct vm_sprite *sp = id_pool_get(&pool, sprite); if (sp) - sp->findable = !!find; + sp->findability = find; } static void vmSprite_SetID(int sprite, int id) @@ -377,8 +394,11 @@ static int vmSprite_SetAnime(int sprite, int frame_s, int frame_e, struct page * free(sp->anime); int nr_frames = array->nr_vars; struct animation *a = xmalloc(sizeof(struct animation) + nr_frames * sizeof(int)); + a->frame_s = frame_s; + a->frame_e = frame_e; a->nr_frames = nr_frames; a->current_frame = 0; + a->time_origin = SDL_GetTicks64(); a->total_frame_time = 0; for (int i = 0; i < a->nr_frames; i++) { a->total_frame_time += a->frame_times[i] = array->values[i].i; @@ -502,7 +522,9 @@ static int vmSprite_FindPos(int x, int y) Point p = { .x = x, .y = y }; for (int id = id_pool_get_first(&pool); id >= 0; id = id_pool_get_next(&pool, id)) { struct vm_sprite *sp = id_pool_get(&pool, id); - if (!sp || !sp->findable) + if (!sp || sp->findability == NOT_FINDABLE) + continue; + if (sp->findability == FINDABLE_WHEN_VISIBLE && sp->sp.hidden) continue; if (!SDL_PointInRect(&p, &sp->rect)) continue; @@ -575,7 +597,7 @@ static int vmSprite_GetShow(int sprite) static int vmSprite_GetFind(int sprite) { struct vm_sprite *sp = id_pool_get(&pool, sprite); - return sp ? sp->findable : 0; + return sp ? sp->findability : 0; } static int vmSprite_GetID(int sprite)