diff options
| author | KonAki <konaki@anokonaki.org> | 2026-10-11 16:44:20 +0800 |
|---|---|---|
| committer | KonAki <konaki@anokonaki.org> | 2026-10-11 16:44:20 +0800 |
| commit | efbccda65737e4b89a6526fe7ba5405016ee9983 (patch) | |
| tree | d7f17b27cfacb42946c520e6135e6b408ca41ef0 /examples | |
| parent | 22348718dfdc48e417f53d5b4b4d471b622846e2 (diff) | |
sectorview: walk with the world module, door collider, jump
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/maps/house.kmap | 2 | ||||
| -rw-r--r-- | examples/sectorview.c | 107 |
2 files changed, 55 insertions, 54 deletions
diff --git a/examples/maps/house.kmap b/examples/maps/house.kmap index 45ee4a6..50912b6 100644 --- a/examples/maps/house.kmap +++ b/examples/maps/house.kmap @@ -39,7 +39,7 @@ edge 1 2 wallpaper entity spawn 4 1.6 2 0 entity light 4 2.6 2 0 color=ffe0a0 radius=8 entity button 7.8 1.2 1 270 target=door1 -entity door 8 0 2 90 name=door1 speed=2 +entity door 8 0 2 90 name=door1 speed=2 width=4 height=2.6 # a picture placed by its four corners: bottom left, bottom right, top right, top left as seen from the front. # this one stands in the garden and faces the window diff --git a/examples/sectorview.c b/examples/sectorview.c index 2816461..beafc36 100644 --- a/examples/sectorview.c +++ b/examples/sectorview.c @@ -1,10 +1,11 @@ /* * sectorview: walk around a map made of rooms and picture quads * - * build: ./build.sh -d -m 3d,sector,font obj/sectorview + * build: ./build.sh -d -m 3d,sector,world,font obj/sectorview * run: obj/sectorview (from the folder with examples/) * - * click to grab the mouse, tab lets go. w and s walk, a and d strafe, e presses a button close to you. + * click to grab the mouse, tab lets go. w and s walk, a and d strafe, space jumps, e presses a button close to you. + * the door is a box in the world that the program lifts, nothing else about it is built in * the map is examples/maps/house.kmap, it is plain text so change it and run again. try moving the watcher */ @@ -16,9 +17,10 @@ #include "konprogram.h" #include "kon3d.h" #include "konsector.h" +#include "konworld.h" -#if !defined(KON_MODULE_3D) || !defined(KON_MODULE_SECTOR) || !defined(KON_MODULE_FONT) -#error "build with: ./build.sh -d -m 3d,sector,font obj/sectorview" +#if !defined(KON_MODULE_3D) || !defined(KON_MODULE_SECTOR) || !defined(KON_MODULE_WORLD) || !defined(KON_MODULE_FONT) +#error "build with: ./build.sh -d -m 3d,sector,world,font obj/sectorview" #endif #define MAP_PATH "examples/maps/house.kmap" @@ -26,7 +28,8 @@ #define MAX_ENTITIES 64 #define EYE 0.7f #define RADIUS 0.2f -#define STEP 0.35f +#define HEIGHT 1.0f +#define JUMP 6.0f #define REACH 1.6f #define COL_SKY 0xFF1B1826u @@ -40,9 +43,11 @@ typedef struct state { kon_material_t materials[MAX_TEXTURES]; kon_image *marker; kon_fp_t input; /* only used for the mouse and keys, the position is ours */ + kon_world_t world; + kon_body_t body; kon_vec3_t eye; - float feet; - int sector; + float feet; /* what the eyes follow, it catches up with the body after a step */ + int door[MAX_ENTITIES]; /* the collider of a door entity, -1 for the others */ float open[MAX_ENTITIES]; /* how far a door is open, 0 to 1 */ int opening[MAX_ENTITIES]; char note[64]; @@ -94,39 +99,16 @@ static kon_image *makeTexture(const char *name) return makeChecker(palette[pick][0], palette[pick][1]); } -/*** moving ***/ +/*** doors ***/ -/* the point is fine to stand on when it is inside the map, the step up to it is small and there is room for the head */ -static int canStand(const state_t *state, float x, float z, float feet, int hint) +/* a door is a box across its opening, facing the way the entity does. opening it lifts the box until it is over the head */ +static void doorShape(const kon_entity_t *e, kon_vec3_t *min, kon_vec3_t *max) { - int s = kon_sectorAt(state->map, x, z, hint); + float width = kon_entityFloat(e, "width", 1.2f) * 0.5f, height = kon_entityFloat(e, "height", 2.2f); + int alongZ = fabsf(sinf(e->angle)) > 0.7f; - if (s < 0) return 0; - if (state->map->sectors[s].floor > feet + STEP) return 0; - return state->map->sectors[s].ceiling - state->map->sectors[s].floor > EYE + 0.2f; -} - -static int canStandBody(const state_t *state, float x, float z) -{ - static const float dx[4] = { -1, 1, 1, -1 }, dz[4] = { -1, -1, 1, 1 }; - int i; - - for (i = 0; i < 4; i++) { - if (!canStand(state, x + dx[i] * RADIUS, z + dz[i] * RADIUS, state->feet, state->sector)) return 0; - } - return 1; -} - -static void walk(state_t *state, float dx, float dz) -{ - if (canStandBody(state, state->eye.x + dx, state->eye.z + dz)) { - state->eye.x += dx; - state->eye.z += dz; - } else if (canStandBody(state, state->eye.x + dx, state->eye.z)) { - state->eye.x += dx; - } else if (canStandBody(state, state->eye.x, state->eye.z + dz)) { - state->eye.z += dz; - } + *min = KON_VEC3(e->position.x - (alongZ ? 0.1f : width), e->position.y, e->position.z - (alongZ ? width : 0.1f)); + *max = KON_VEC3(e->position.x + (alongZ ? 0.1f : width), e->position.y + height, e->position.z + (alongZ ? width : 0.1f)); } /*** program ***/ @@ -137,12 +119,16 @@ static int event(kon_program_t *program, const kon_event_t *ev, void *user) int i, n, ids[8]; if (kon_fpEvent(&state->input, program, ev)) return 1; + if (ev->type == KON_EVENT_KEY_DOWN && ev->key == KON_KEY_SPACE) { + kon_bodyJump(&state->body, JUMP); + return 1; + } if (ev->type != KON_EVENT_KEY_DOWN || ev->key != KON_KEY_E) return 0; /* the map only says what is where, what a button does is decided here: it opens whatever it points at */ for (i = 0; i < state->map->entityCount && i < MAX_ENTITIES; i++) { const kon_entity_t *button = &state->map->entities[i]; - float dx = button->position.x - state->eye.x, dz = button->position.z - state->eye.z; + float dx = button->position.x - state->body.position.x, dz = button->position.z - state->body.position.z; if (strcmp(button->kind, "button") != 0 || dx * dx + dz * dz > REACH * REACH) continue; n = kon_entityTargets(state->map, button->target, ids, 8); @@ -163,26 +149,29 @@ static void update(kon_program_t *program, double dt, void *user) float step = state->input.speed * (float)dt; float dx = (fx * (float)state->input.forward - fz * (float)state->input.strafe) * step; float dz = (fz * (float)state->input.forward + fx * (float)state->input.strafe) * step; - int i, s; + int i; state->time += dt; if (kon_debugConsoleOpen(program->debug) && kon_isMouseCaptured(program->window)) kon_setMouseCapture(program->window, false); state->input.yaw += (float)state->input.turn * state->input.turnSpeed * (float)dt; - walk(state, dx, dz); - s = kon_sectorAt(state->map, state->eye.x, state->eye.z, state->sector); - if (s >= 0) { - state->sector = s; - state->feet += (state->map->sectors[s].floor - state->feet) * (1.0f - expf(-12.0f * (float)dt)); - } - state->eye.y = state->feet + EYE; - for (i = 0; i < state->map->entityCount && i < MAX_ENTITIES; i++) { float speed = kon_entityFloat(&state->map->entities[i], "speed", 1.0f) * (float)dt; if (state->opening[i] && state->open[i] < 1.0f) state->open[i] = fminf(1.0f, state->open[i] + speed); if (!state->opening[i] && state->open[i] > 0.0f) state->open[i] = fmaxf(0.0f, state->open[i] - speed); + if (state->door[i] >= 0) { + kon_collider_t *c = kon_worldCollider(&state->world, state->door[i]); + kon_vec3_t min, max; + + doorShape(&state->map->entities[i], &min, &max); + c->min.y = min.y + state->open[i] * (max.y - min.y); + } } + + kon_worldMove(&state->world, &state->body, dx, dz, dt); + state->feet += (state->body.position.y - state->feet) * (1.0f - expf(-16.0f * (float)dt)); + if (state->body.onGround == 0) state->feet = state->body.position.y; } static void draw(kon_program_t *program, kon_framebuffer_t *game, void *user) @@ -194,6 +183,7 @@ static void draw(kon_program_t *program, kon_framebuffer_t *game, void *user) char line[96]; int i; + state->eye = KON_VEC3(state->body.position.x, state->feet + EYE, state->body.position.z); camera.position = state->eye; camera.target = KON_VEC3(state->eye.x + sinf(state->input.yaw) * cosf(state->input.pitch), state->eye.y + sinf(state->input.pitch), state->eye.z - cosf(state->input.yaw) * cosf(state->input.pitch)); @@ -219,7 +209,7 @@ static void draw(kon_program_t *program, kon_framebuffer_t *game, void *user) kon_fillRectangle(game, game->width / 2 - 3, game->height / 2, 7, 1, COL_NOTE); kon_fillRectangle(game, game->width / 2, game->height / 2 - 3, 1, 7, COL_NOTE); if (program->font) { - snprintf(line, sizeof(line), "room %d click to look, e presses buttons", state->sector); + snprintf(line, sizeof(line), "room %d click to look, e presses buttons, space jumps", state->body.sector); kon_drawText(game, program->font, 8, 16, line, COL_DIM); if (state->note[0]) kon_drawText(game, program->font, 8, 30, state->note, COL_NOTE); } @@ -258,16 +248,26 @@ static int init(kon_program_t *program, void *user) break; } } - state->sector = -1; + kon_worldInit(&state->world); + state->world.sectors = state->map; + for (i = 0; i < MAX_ENTITIES; i++) state->door[i] = -1; + for (i = 0; i < state->map->entityCount && i < MAX_ENTITIES; i++) { + kon_vec3_t min, max; + + if (strcmp(state->map->entities[i].kind, "door") != 0) continue; + doorShape(&state->map->entities[i], &min, &max); + state->door[i] = kon_worldAdd(&state->world, kon_colliderBox(min, max)); + } + + kon_bodyInit(&state->body, 0, 0, 0, RADIUS, HEIGHT); if (state->map->entityCount > 0) { const kon_entity_t *e = &state->map->entities[spawn]; - state->eye = e->position; + state->body.position = KON_VEC3(e->position.x, e->position.y, e->position.z); state->input.yaw = e->angle; - state->sector = kon_sectorAt(state->map, e->position.x, e->position.z, -1); } - if (state->sector < 0) state->sector = 0; - state->feet = state->map->sectors[state->sector].floor; + kon_worldPlace(&state->world, &state->body); + state->feet = state->body.position.y; return 1; } @@ -280,6 +280,7 @@ static void shutdown(kon_program_t *program, void *user) for (i = 0; i < state->map->textureCount; i++) kon_freeFramebuffer(state->images[i]); kon_freeFramebuffer(state->marker); kon_sectorMeshFree(state->mesh); + kon_worldFree(&state->world); kon_sectorFree(state->map); } |
