summaryrefslogtreecommitdiff
path: root/kon/konplatformer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kon/konplatformer.c')
-rw-r--r--kon/konplatformer.c92
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;
+ }
+}