summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-12 03:25:20 +0800
committerKonAki <konaki@anokonaki.org>2026-10-12 03:25:20 +0800
commitca1f5cd724644aee01d01b4d12d52f8893e01e54 (patch)
tree676cc0d8d3a32f3192c6d6397860e7597d5cb8d9
parentdbe7d0e0eeeabf6a4df16ef98d0a1f8d53b62d8b (diff)
split platformer out of 2d so 2d is only camera and animation
-rw-r--r--README.md3
-rwxr-xr-xbuild.sh6
-rw-r--r--examples/platform.c7
-rw-r--r--kon/kon2d.c66
-rw-r--r--kon/kon2d.h37
-rw-r--r--kon/konplatformer.c92
-rw-r--r--kon/konplatformer.h67
7 files changed, 168 insertions, 110 deletions
diff --git a/README.md b/README.md
index b0923b2..9a8da19 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,8 @@ The engine modules are a `.h` and a `.c` pair, they depend on each other a bit,
| font | konfont |
| toml | kontoml |
| tile | tilemaps and sprite sheets |
-| 2d | platformer body with coyote time and jump buffering, a scrolling camera, frame animation (adds tile) |
+| 2d | what any 2D game needs: a scrolling camera, frame animation, drawing frames of a sprite sheet |
+| platformer | a box that runs and jumps through a tilemap, with coyote time and jump buffering (adds tile) |
| 3d | first person kit: mouse look body, walls from a tilemap, editable hill terrain (adds tile) |
| sector | maps made of rooms (vertices, floors, ceilings, walls) with entities like doors and buttons, in a text format |
| world | one place to move bodies through sector maps, terrain, tilemaps and your own boxes, cylinders, spheres and planes (needs 3d, sector) |
diff --git a/build.sh b/build.sh
index 3512228..5d1c4f8 100755
--- a/build.sh
+++ b/build.sh
@@ -12,7 +12,7 @@ developer=0
usage()
{
echo "usage: build.sh [-d] [-D] [-p platform] [-m module,...] [-o objdir] [target ...]"
- echo "modules: font toml tile pack ui debug assets image audio mic model 2d 3d sector world"
+ echo "modules: font toml tile pack ui debug assets image audio mic model 2d platformer 3d sector world"
echo "platforms: native linux bsd windows"
echo "targets: all run clean tools pack examples"
exit 1
@@ -77,7 +77,7 @@ addobj()
for m in $modules; do
DEFS="$DEFS -DKON_MODULE_$(echo "$m" | tr 'a-z' 'A-Z')"
case $m in
- font|toml|tile|pack|ui|debug|2d|3d|sector|world) addobj "kon$m" ;;
+ font|toml|tile|pack|ui|debug|2d|platformer|3d|sector|world) addobj "kon$m" ;;
assets) addobj konassets ;;
model) addobj konmodel; addobj konassets ;;
image) addobj stb_image ;;
@@ -106,7 +106,7 @@ need()
case " $modules " in *" debug "*) need font; need assets ;; esac
case " $modules " in *" ui "*) need font ;; esac
case " $modules " in *" world "*) need 3d; need sector; need tile ;; esac
-case " $modules " in *" 2d "*) need tile ;; esac
+case " $modules " in *" platformer "*) need tile ;; esac
case " $modules " in *" 3d "*) need tile ;; esac
case " $modules " in *" model "*) need assets ;; esac
case " $DEFS " in *" -DKON_MODULE_ASSETS "*) need pack ;; esac
diff --git a/examples/platform.c b/examples/platform.c
index 1ac48fb..b6f65ea 100644
--- a/examples/platform.c
+++ b/examples/platform.c
@@ -1,7 +1,7 @@
/*
* platform: a box that runs and jumps around a tilemap with a camera that follows it, and a ray that follows the mouse
*
- * build: ./build.sh -d -m 2d,font obj/platform
+ * build: ./build.sh -d -m 2d,platformer,font obj/platform
* run: obj/platform
*
* left and right or a and d run, space or up jumps. the line from the box to the mouse stops at the first solid tile
@@ -14,9 +14,10 @@
#include "konprogram.h"
#include "kontile.h"
#include "kon2d.h"
+#include "konplatformer.h"
-#if !defined(KON_MODULE_2D) || !defined(KON_MODULE_TILE) || !defined(KON_MODULE_FONT)
-#error "build with: ./build.sh -d -m 2d,font obj/platform"
+#if !defined(KON_MODULE_2D) || !defined(KON_MODULE_PLATFORMER) || !defined(KON_MODULE_TILE) || !defined(KON_MODULE_FONT)
+#error "build with: ./build.sh -d -m 2d,platformer,font obj/platform"
#endif
#define TILE 16
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