diff options
| author | KonAki <konaki@anokonaki.org> | 2026-10-12 03:25:20 +0800 |
|---|---|---|
| committer | KonAki <konaki@anokonaki.org> | 2026-10-12 03:25:20 +0800 |
| commit | ca1f5cd724644aee01d01b4d12d52f8893e01e54 (patch) | |
| tree | 676cc0d8d3a32f3192c6d6397860e7597d5cb8d9 /kon | |
| parent | dbe7d0e0eeeabf6a4df16ef98d0a1f8d53b62d8b (diff) | |
split platformer out of 2d so 2d is only camera and animation
Diffstat (limited to 'kon')
| -rw-r--r-- | kon/kon2d.c | 66 | ||||
| -rw-r--r-- | kon/kon2d.h | 37 | ||||
| -rw-r--r-- | kon/konplatformer.c | 92 | ||||
| -rw-r--r-- | kon/konplatformer.h | 67 |
4 files changed, 159 insertions, 103 deletions
diff --git a/kon/kon2d.c b/kon/kon2d.c index 2cc9fdd..8ce56d8 100644 --- a/kon/kon2d.c +++ b/kon/kon2d.c @@ -27,72 +27,6 @@ #include <math.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; - } -} - /*** camera ***/ static float clampAxis(float value, float view, float bounds) diff --git a/kon/kon2d.h b/kon/kon2d.h index 7a58dc6..fce4bb2 100644 --- a/kon/kon2d.h +++ b/kon/kon2d.h @@ -27,43 +27,6 @@ #define KON2D_H #include "konsofren.h" -#include "koncollide.h" -#include "kontile.h" - -/*** platformer ***/ - -/* a box that runs and jumps through a tilemap. the game sets moveX and jumpHeld every frame, calls kon_platformerUpdate and reads - box, velocity and onGround back. everything is in map pixels and seconds. kon_platformerInit fills in the tuning values, - change them afterwards as you like */ -typedef struct kon_platformer { - kon_box2_t box; - kon_vec2_t velocity; - int onGround; - - int moveX; /* -1 left, 0 stand, 1 right */ - int jumpHeld; - - float runSpeed; - float groundAccel, airAccel; /* how fast velocity.x closes in on the run speed, per second */ - float gravity; - float jumpSpeed; - float jumpCut; /* letting go of jump early slows the rise to this speed */ - float maxFall; - float coyoteTime; /* seconds after leaving a ledge a jump still works */ - float bufferTime; /* seconds before landing a jump press is remembered */ - - /* private */ - float coyote, buffer, leftover; - int jumpWas; -} kon_platformer_t; - -void kon_platformerInit(kon_platformer_t *p, kon_box2_t box); - -/* one step of dt seconds, dt should be small and steady. returns the KON_HIT_ flags of the move */ -int kon_platformerStep(kon_platformer_t *p, const kon_tilemap_t *map, const uint8_t *solid, int solidCount, float dt); - -/* takes the frame time and runs steps of 1/120 of a second, so the jump feels the same at any frame rate */ -void kon_platformerUpdate(kon_platformer_t *p, const kon_tilemap_t *map, const uint8_t *solid, int solidCount, double dt); /*** camera ***/ 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; + } +} diff --git a/kon/konplatformer.h b/kon/konplatformer.h new file mode 100644 index 0000000..710f0e0 --- /dev/null +++ b/kon/konplatformer.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: MIT */ +/* + * konplatformer.h + * + * 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. + */ + +#ifndef KONPLATFORMER_H +#define KONPLATFORMER_H + +#include "koncollide.h" +#include "kontile.h" + +/*** platformer ***/ + +/* a box that runs and jumps through a tilemap. the game sets moveX and jumpHeld every frame, calls kon_platformerUpdate and reads + box, velocity and onGround back. everything is in map pixels and seconds. kon_platformerInit fills in the tuning values, + change them afterwards as you like */ +typedef struct kon_platformer { + kon_box2_t box; + kon_vec2_t velocity; + int onGround; + + int moveX; /* -1 left, 0 stand, 1 right */ + int jumpHeld; + + float runSpeed; + float groundAccel, airAccel; /* how fast velocity.x closes in on the run speed, per second */ + float gravity; + float jumpSpeed; + float jumpCut; /* letting go of jump early slows the rise to this speed */ + float maxFall; + float coyoteTime; /* seconds after leaving a ledge a jump still works */ + float bufferTime; /* seconds before landing a jump press is remembered */ + + /* private */ + float coyote, buffer, leftover; + int jumpWas; +} kon_platformer_t; + +void kon_platformerInit(kon_platformer_t *p, kon_box2_t box); + +/* one step of dt seconds, dt should be small and steady. returns the KON_HIT_ flags of the move */ +int kon_platformerStep(kon_platformer_t *p, const kon_tilemap_t *map, const uint8_t *solid, int solidCount, float dt); + +/* takes the frame time and runs steps of 1/120 of a second, so the jump feels the same at any frame rate */ +void kon_platformerUpdate(kon_platformer_t *p, const kon_tilemap_t *map, const uint8_t *solid, int solidCount, double dt); + +#endif |
