diff options
Diffstat (limited to 'kon/konrpg.c')
| -rw-r--r-- | kon/konrpg.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/kon/konrpg.c b/kon/konrpg.c new file mode 100644 index 0000000..f56c098 --- /dev/null +++ b/kon/konrpg.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: MIT */ +/* + * konrpg.c + * + * Copyright (c) 2026 KonAki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "konrpg.h" + +/*** directions ***/ + +void kon_dirDelta(kon_dir_t dir, int *dx, int *dy) +{ + *dx = 0; + *dy = 0; + switch (dir) { + case KON_DIR_DOWN: *dy = 1; break; + case KON_DIR_LEFT: *dx = -1; break; + case KON_DIR_RIGHT: *dx = 1; break; + case KON_DIR_UP: *dy = -1; break; + } +} + +kon_dir_t kon_dirOpposite(kon_dir_t dir) +{ + switch (dir) { + case KON_DIR_DOWN: return KON_DIR_UP; + case KON_DIR_LEFT: return KON_DIR_RIGHT; + case KON_DIR_RIGHT: return KON_DIR_LEFT; + case KON_DIR_UP: break; + } + return KON_DIR_DOWN; +} + +/*** actors ***/ + +void kon_actorInit(kon_actor_t *actor, int column, int row, kon_dir_t facing) +{ + kon_actor_t zero = {0}; + + *actor = zero; + actor->column = actor->fromColumn = column; + actor->row = actor->fromRow = row; + actor->facing = facing; + actor->progress = 1.0f; + actor->speed = 4.0f; +} + +int kon_actorWalk(kon_actor_t *actor, const kon_tilemap_t *map, const uint8_t *solid, int solidCount, kon_dir_t dir, kon_blockFn blocked, void *user) +{ + int dx, dy, column, row, id; + + if (!map || actor->moving) return 0; + actor->facing = dir; + kon_dirDelta(dir, &dx, &dy); + column = actor->column + dx; + row = actor->row + dy; + + if (column < 0 || row < 0 || column >= map->columns || row >= map->rows) return 0; + id = kon_tilemapAt(map, column, row); + if (solid && id < solidCount && solid[id]) return 0; + if (blocked && blocked(column, row, user)) return 0; + + actor->fromColumn = actor->column; + actor->fromRow = actor->row; + actor->column = column; + actor->row = row; + actor->moving = 1; + actor->progress = actor->carry * actor->speed; + if (actor->progress >= 1.0f) actor->progress = 0.999f; + actor->carry = 0.0f; + return 1; +} + +int kon_actorUpdate(kon_actor_t *actor, float dt) +{ + if (!actor->moving) { + actor->carry = 0.0f; + return 0; + } + if (!(dt > 0.0f) || !(actor->speed > 0.0f)) return 0; + + actor->progress += actor->speed * dt; + if (actor->progress < 1.0f) return 0; + + actor->carry = (actor->progress - 1.0f) / actor->speed; + actor->progress = 1.0f; + actor->moving = 0; + return 1; +} + +void kon_actorPixel(const kon_actor_t *actor, const kon_tilemap_t *map, float *x, float *y) +{ + float t = actor->moving ? actor->progress : 1.0f; + float fromX = (float)(actor->fromColumn * map->tileWidth), fromY = (float)(actor->fromRow * map->tileHeight); + float toX = (float)(actor->column * map->tileWidth), toY = (float)(actor->row * map->tileHeight); + + *x = fromX + (toX - fromX) * t; + *y = fromY + (toY - fromY) * t; +} + +void kon_actorFront(const kon_actor_t *actor, int *column, int *row) +{ + int dx, dy; + + kon_dirDelta(actor->facing, &dx, &dy); + *column = actor->column + dx; + *row = actor->row + dy; +} + +/*** events ***/ + +int kon_eventAt(const kon_tileEvent_t *events, int count, int column, int row, int trigger) +{ + int i; + + for (i = 0; i < count; i++) { + if (events[i].column != column || events[i].row != row) continue; + if (trigger >= 0 && (int)events[i].trigger != trigger) continue; + return i; + } + return -1; +} + +int kon_eventBlocks(int column, int row, void *user) +{ + const kon_eventList_t *list = user; + int i; + + for (i = 0; i < list->count; i++) { + if (list->events[i].blocks && list->events[i].column == column && list->events[i].row == row) return 1; + } + return 0; +} |
