diff options
Diffstat (limited to 'kon/konplatformer.c')
| -rw-r--r-- | kon/konplatformer.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/kon/konplatformer.c b/kon/konplatformer.c new file mode 100644 index 0000000..9d22c67 --- /dev/null +++ b/kon/konplatformer.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: MIT */ +/* + * konplatformer.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 "konplatformer.h" + +#define STEP (1.0 / 120.0) +#define MAX_FRAME 0.25 + +/*** platformer ***/ + +void kon_platformerInit(kon_platformer_t *p, kon_box2_t box) +{ + kon_platformer_t zero = {0}; + + *p = zero; + p->box = box; + p->runSpeed = 120.0f; + p->groundAccel = 18.0f; + p->airAccel = 8.0f; + p->gravity = 700.0f; + p->jumpSpeed = 260.0f; + p->jumpCut = 60.0f; + p->maxFall = 400.0f; + p->coyoteTime = 0.08f; + p->bufferTime = 0.1f; +} + +int kon_platformerStep(kon_platformer_t *p, const kon_tilemap_t *map, const uint8_t *solid, int solidCount, float dt) +{ + float run = (float)p->moveX * p->runSpeed; + float ease = (p->onGround ? p->groundAccel : p->airAccel) * dt; + int flags; + + if (ease > 1.0f) ease = 1.0f; + p->velocity.x += (run - p->velocity.x) * ease; + p->velocity.y += p->gravity * dt; + if (p->velocity.y > p->maxFall) p->velocity.y = p->maxFall; + + if (p->jumpHeld && !p->jumpWas) p->buffer = p->bufferTime; + p->jumpWas = p->jumpHeld; + if (p->buffer > 0.0f) p->buffer -= dt; + if (p->coyote > 0.0f) p->coyote -= dt; + + if (p->buffer > 0.0f && p->coyote > 0.0f) { + p->velocity.y = -p->jumpSpeed; + p->buffer = 0.0f; + p->coyote = 0.0f; + } + if (!p->jumpHeld && p->velocity.y < -p->jumpCut) p->velocity.y = -p->jumpCut; + + flags = kon_tilemapMove(map, &p->box, p->velocity.x * dt, p->velocity.y * dt, solid, solidCount); + + if (flags & (KON_HIT_LEFT | KON_HIT_RIGHT)) p->velocity.x = 0.0f; + if (flags & (KON_HIT_UP | KON_HIT_DOWN)) p->velocity.y = 0.0f; + p->onGround = (flags & KON_HIT_DOWN) != 0; + if (p->onGround) p->coyote = p->coyoteTime; + return flags; +} + +void kon_platformerUpdate(kon_platformer_t *p, const kon_tilemap_t *map, const uint8_t *solid, int solidCount, double dt) +{ + if (!(dt > 0.0)) return; + if (dt > MAX_FRAME) dt = MAX_FRAME; + + p->leftover += (float)dt; + while (p->leftover >= (float)STEP) { + kon_platformerStep(p, map, solid, solidCount, (float)STEP); + p->leftover -= (float)STEP; + } +} |
