diff options
| author | KonAki <konaki@anokonaki.org> | 2026-10-12 03:03:51 +0800 |
|---|---|---|
| committer | KonAki <konaki@anokonaki.org> | 2026-10-12 03:03:51 +0800 |
| commit | dbe7d0e0eeeabf6a4df16ef98d0a1f8d53b62d8b (patch) | |
| tree | 2b211e3e455f489da9499a786e0aef2632bfc1c0 /examples/platform.c | |
| parent | b77cac581ac41d069f20a24e07211cc200c653eb (diff) | |
platform example uses the 2d module and scrolls
Diffstat (limited to 'examples/platform.c')
| -rw-r--r-- | examples/platform.c | 97 |
1 files changed, 39 insertions, 58 deletions
diff --git a/examples/platform.c b/examples/platform.c index 869e820..1ac48fb 100644 --- a/examples/platform.c +++ b/examples/platform.c @@ -1,7 +1,7 @@ /* - * platform: a box that runs and jumps around a tilemap, and a ray that follows the mouse + * 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 tile,font obj/platform + * build: ./build.sh -d -m 2d,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 @@ -13,15 +13,17 @@ #include "konprogram.h" #include "kontile.h" +#include "kon2d.h" -#if !defined(KON_MODULE_TILE) || !defined(KON_MODULE_FONT) -#error "build with: ./build.sh -d -m tile,font obj/platform" +#if !defined(KON_MODULE_2D) || !defined(KON_MODULE_TILE) || !defined(KON_MODULE_FONT) +#error "build with: ./build.sh -d -m 2d,font obj/platform" #endif #define TILE 16 #define COLUMNS 40 #define ROWS 22 -#define STEP (1.0 / 120.0) +#define VIEW_WIDTH 320 +#define VIEW_HEIGHT 176 #define COL_BACKGROUND 0xFF1B1826u #define COL_TILE 0xFF4A4468u @@ -61,13 +63,10 @@ typedef struct state { uint16_t tiles[COLUMNS * ROWS]; uint8_t solid[2]; - kon_box2_t player; - kon_vec2_t velocity; - int onGround; - double leftover, coyote; - int left, right, jumpHeld; - float gravity, jump; + kon_platformer_t player; + kon_camera2_t camera; + int left, right; int mouseX, mouseY; int rayHit; kon_hit2_t hit; @@ -86,7 +85,7 @@ static int event(kon_program_t *program, const kon_event_t *ev, void *user) if (ev->key == KON_KEY_LEFT || ev->key == KON_KEY_A) state->left = down; else if (ev->key == KON_KEY_RIGHT || ev->key == KON_KEY_D) state->right = down; - else if (ev->key == KON_KEY_SPACE || ev->key == KON_KEY_UP) state->jumpHeld = down; + else if (ev->key == KON_KEY_SPACE || ev->key == KON_KEY_UP) state->player.jumpHeld = down; else return 0; } else { return 0; @@ -94,46 +93,24 @@ static int event(kon_program_t *program, const kon_event_t *ev, void *user) return 1; } -static void step(state_t *state, float dt) -{ - float run = (float)(state->right - state->left) * 120.0f; - int flags; - - state->velocity.x += (run - state->velocity.x) * (state->onGround ? 18.0f : 8.0f) * dt; - state->velocity.y += state->gravity * dt; - - if (state->coyote > 0.0) state->coyote -= dt; - if (state->jumpHeld && state->coyote > 0.0) { - state->velocity.y = -state->jump; - state->coyote = 0.0; - } - /* letting go early cuts the jump short */ - if (!state->jumpHeld && state->velocity.y < -60.0f) state->velocity.y = -60.0f; - - flags = kon_tilemapMove(&state->map, &state->player, state->velocity.x * dt, state->velocity.y * dt, state->solid, 2); - - if (flags & (KON_HIT_LEFT | KON_HIT_RIGHT)) state->velocity.x = 0.0f; - if (flags & (KON_HIT_UP | KON_HIT_DOWN)) state->velocity.y = 0.0f; - state->onGround = (flags & KON_HIT_DOWN) != 0; - if (state->onGround) state->coyote = 0.08; -} - static void update(kon_program_t *program, double dt, void *user) { state_t *state = user; - kon_vec2_t from = KON_VEC2(state->player.x + state->player.w * 0.5f, state->player.y + state->player.h * 0.5f); - kon_vec2_t dir = KON_VEC2((float)state->mouseX - from.x, (float)state->mouseY - from.y); - float length = kon_vec2Length(dir); + kon_box2_t *box = &state->player.box; + kon_vec2_t from = KON_VEC2(box->x + box->w * 0.5f, box->y + box->h * 0.5f); + kon_vec2_t dir; + float length; int row, column; (void)program; - state->leftover += dt; - while (state->leftover >= STEP) { - step(state, (float)STEP); - state->leftover -= STEP; - } + state->player.moveX = state->right - state->left; + kon_platformerUpdate(&state->player, &state->map, state->solid, 2, dt); + kon_camera2Follow(&state->camera, from.x, from.y, (float)dt); /* the ray against every solid tile, nothing clever, the nearest one wins */ + dir = KON_VEC2((float)(state->mouseX + kon_camera2X(&state->camera)) - from.x, + (float)(state->mouseY + kon_camera2Y(&state->camera)) - from.y); + length = kon_vec2Length(dir); state->rayHit = 0; if (length < 1.0f) return; dir = kon_vec2Scale(dir, 1.0f / length); @@ -154,27 +131,31 @@ static void update(kon_program_t *program, double dt, void *user) static void draw(kon_program_t *program, kon_framebuffer_t *game, void *user) { state_t *state = user; + kon_box2_t *box = &state->player.box; + int camX = kon_camera2X(&state->camera), camY = kon_camera2Y(&state->camera); int row, column, ex, ey; - int fromX = (int)(state->player.x + state->player.w * 0.5f), fromY = (int)(state->player.y + state->player.h * 0.5f); + int fromX = (int)(box->x + box->w * 0.5f) - camX, fromY = (int)(box->y + box->h * 0.5f) - camY; kon_clearFramebuffer(game, COL_BACKGROUND); for (row = 0; row < ROWS; row++) { for (column = 0; column < COLUMNS; column++) { + int x = column * TILE - camX, y = row * TILE - camY; + if (!state->solid[kon_tilemapAt(&state->map, column, row)]) continue; - kon_fillRectangle(game, column * TILE, row * TILE, TILE, TILE, COL_TILE); - if (!state->solid[kon_tilemapAt(&state->map, column, row - 1)]) kon_fillRectangle(game, column * TILE, row * TILE, TILE, 2, COL_TILE_TOP); + kon_fillRectangle(game, x, y, TILE, TILE, COL_TILE); + if (!state->solid[kon_tilemapAt(&state->map, column, row - 1)]) kon_fillRectangle(game, x, y, TILE, 2, COL_TILE_TOP); } } - ex = state->rayHit ? (int)state->hit.point.x : state->mouseX; - ey = state->rayHit ? (int)state->hit.point.y : state->mouseY; + ex = state->rayHit ? (int)state->hit.point.x - camX : state->mouseX; + ey = state->rayHit ? (int)state->hit.point.y - camY : state->mouseY; kon_drawLine(game, fromX, fromY, ex, ey, COL_RAY); if (state->rayHit) kon_fillCircle(game, ex, ey, 2, COL_HIT); - kon_fillRectangle(game, (int)state->player.x, (int)state->player.y, (int)state->player.w, (int)state->player.h, COL_PLAYER); + kon_fillRectangle(game, (int)box->x - camX, (int)box->y - camY, (int)box->w, (int)box->h, COL_PLAYER); - if (program->font) kon_drawText(game, program->font, 24, 40, "arrows or a d to run, space to jump", COL_DIM); + if (program->font) kon_drawText(game, program->font, 8, 16, "arrows or a d to run, space to jump", COL_DIM); } static int init(kon_program_t *program, void *user) @@ -192,12 +173,12 @@ static int init(kon_program_t *program, void *user) for (column = 0; column < COLUMNS; column++) state->tiles[row * COLUMNS + column] = level[row][column] == '#'; } - state->player = KON_BOX2(40, 280, 10, 14); - state->gravity = 700.0f; - state->jump = 260.0f; + kon_platformerInit(&state->player, KON_BOX2(40, 280, 10, 14)); + kon_camera2Init(&state->camera, VIEW_WIDTH, VIEW_HEIGHT, COLUMNS * TILE, ROWS * TILE); + kon_camera2Snap(&state->camera, 45.0f, 287.0f); - kon_debugVar(program->debug, "gravity", KON_VAR_FLOAT, &state->gravity); - kon_debugVar(program->debug, "jump", KON_VAR_FLOAT, &state->jump); + kon_debugVar(program->debug, "gravity", KON_VAR_FLOAT, &state->player.gravity); + kon_debugVar(program->debug, "jump", KON_VAR_FLOAT, &state->player.jumpSpeed); return 1; } @@ -207,8 +188,8 @@ int main(void) kon_programConfig_t config = {0}; config.title = "platform"; - config.gameWidth = 640; - config.gameHeight = 352; + config.gameWidth = VIEW_WIDTH; + config.gameHeight = VIEW_HEIGHT; config.windowWidth = 1280; config.windowHeight = 704; config.user = &state; |
