From 9f2353306996e22b2154b3f8ab1ea68216c0bae1 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Tue, 11 Nov 2025 22:12:08 -0600 Subject: [PATCH] Make stairs work --- assets/map/map/0_0_0.json | 3 +- src/rpg/entity/entity.c | 50 ++++++++++++++++++++++++---------- src/rpg/entity/entitydir.c | 10 +++++++ src/rpg/entity/entitydir.h | 8 ++++++ src/rpg/world/chunk.h | 6 ++-- src/rpg/world/region.h | 14 ---------- src/rpg/world/tile.c | 29 ++++++++++++++++---- src/rpg/world/tile.h | 21 ++++++++++---- src/rpg/world/worldpos.h | 2 +- tools/assetstool/processmap.py | 8 ++++-- 10 files changed, 103 insertions(+), 48 deletions(-) delete mode 100644 src/rpg/world/region.h diff --git a/assets/map/map/0_0_0.json b/assets/map/map/0_0_0.json index 3e6bb52..0ca639b 100644 --- a/assets/map/map/0_0_0.json +++ b/assets/map/map/0_0_0.json @@ -1,7 +1,7 @@ { "tiles": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -17,7 +17,6 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/rpg/entity/entity.c b/src/rpg/entity/entity.c index 7db871e..c081b59 100644 --- a/src/rpg/entity/entity.c +++ b/src/rpg/entity/entity.c @@ -76,20 +76,43 @@ void entityWalk(entity_t *entity, const entitydir_t direction) { } // Get tile under foot - tile_t tile = mapGetTile(newPos); - if(tile == TILE_NULL && newPos.z > 0) { - // Check one level down for walkable tile (stairs down) + tile_t tileCurrent = mapGetTile(entity->position); + tile_t tileNew = mapGetTile(newPos); + bool_t fall = false; + bool_t raise = false; + + // Are we walking up stairs? + if( + tileIsStairs(tileCurrent) && + (direction+TILE_STAIRS_SOUTH) == tileCurrent && + newPos.z < (MAP_CHUNK_DEPTH - 1) + ) { + tileNew = TILE_NULL;// Force check for stairs above. + worldpos_t abovePos = newPos; + abovePos.z += 1; + tile_t tileAbove = mapGetTile(abovePos); + + if(tileAbove != TILE_NULL && tileIsWalkable(tileAbove)) { + // We can go up the stairs. + raise = true; + } + } else if(tileNew == TILE_NULL && newPos.z > 0) { + // Falling down? worldpos_t belowPos = newPos; belowPos.z -= 1; - tile_t belowTile = mapGetTile(belowPos); - - if(belowTile == TILE_STAIRS_UP) { - tile = TILE_STAIRS_DOWN;// Mark current as stairs down + tile_t tileBelow = mapGetTile(belowPos); + if( + tileBelow != TILE_NULL && + tileIsStairs(tileBelow) && + (entityDirGetOpposite(direction)+TILE_STAIRS_SOUTH) == tileBelow + ) { + // We will fall to this tile. + fall = true; } } - // Tile walkable? - if(!tileIsWalkable(tile)) return; + // Can we walk here? + if(!raise && !fall && !tileIsWalkable(tileNew)) return;// Blocked // Entity in way? entity_t *other = ENTITIES; @@ -105,13 +128,10 @@ void entityWalk(entity_t *entity, const entitydir_t direction) { entity->animation = ENTITY_ANIM_WALK; entity->animTime = ENTITY_ANIM_WALK_DURATION;// TODO: Running vs walking - // We are comitting, we can run effects here. - if(tile == TILE_STAIRS_DOWN) { - // Moving down a level - entity->position.z -= 1; - } else if(tile == TILE_STAIRS_UP) { - // Moving up a level + if(raise) { entity->position.z += 1; + } else if(fall) { + entity->position.z -= 1; } } diff --git a/src/rpg/entity/entitydir.c b/src/rpg/entity/entitydir.c index 0af488d..e272877 100644 --- a/src/rpg/entity/entitydir.c +++ b/src/rpg/entity/entitydir.c @@ -8,6 +8,16 @@ #include "entitydir.h" #include "assert/assert.h" +entitydir_t entityDirGetOpposite(const entitydir_t dir) { + switch(dir) { + case ENTITY_DIR_NORTH: return ENTITY_DIR_SOUTH; + case ENTITY_DIR_SOUTH: return ENTITY_DIR_NORTH; + case ENTITY_DIR_EAST: return ENTITY_DIR_WEST; + case ENTITY_DIR_WEST: return ENTITY_DIR_EAST; + default: return dir; + } +} + void entityDirGetRelative( const entitydir_t from, worldunits_t *outX, diff --git a/src/rpg/entity/entitydir.h b/src/rpg/entity/entitydir.h index 20fa150..4332b76 100644 --- a/src/rpg/entity/entitydir.h +++ b/src/rpg/entity/entitydir.h @@ -20,6 +20,14 @@ typedef enum { ENTITY_DIR_RIGHT = ENTITY_DIR_EAST, } entitydir_t; +/** + * Gets the opposite direction of a given direction. + * + * @param dir The direction to get the opposite of. + * @return entitydir_t The opposite direction. + */ +entitydir_t entityDirGetOpposite(const entitydir_t dir); + /** * Asserts a given direction is valid. * diff --git a/src/rpg/world/chunk.h b/src/rpg/world/chunk.h index 74b8a40..695c692 100644 --- a/src/rpg/world/chunk.h +++ b/src/rpg/world/chunk.h @@ -8,10 +8,10 @@ #pragma once #include "rpg/world/tile.h" #include "worldpos.h" -#include "display/mesh/mesh.h" +#include "display/mesh/quad.h" -#define CHUNK_VERTEX_COUNT_MAX (6 * CHUNK_TILE_COUNT * 2) -#define CHUNK_MESH_COUNT_MAX 12 +#define CHUNK_VERTEX_COUNT_MAX (QUAD_VERTEX_COUNT * CHUNK_TILE_COUNT * 2) +#define CHUNK_MESH_COUNT_MAX 14 typedef struct chunk_s { chunkpos_t position; diff --git a/src/rpg/world/region.h b/src/rpg/world/region.h deleted file mode 100644 index 0b72c09..0000000 --- a/src/rpg/world/region.h +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct { - vec2 min; - vec2 max; -} region_t; \ No newline at end of file diff --git a/src/rpg/world/tile.c b/src/rpg/world/tile.c index 3e1cac1..d4c706b 100644 --- a/src/rpg/world/tile.c +++ b/src/rpg/world/tile.c @@ -8,9 +8,28 @@ #include "tile.h" bool_t tileIsWalkable(const tile_t tile) { - return ( - tile == TILE_WALKABLE || - tile == TILE_STAIRS_UP || - tile == TILE_STAIRS_DOWN - ); + switch(tile) { + case TILE_WALKABLE: + case TILE_STAIRS_NORTH: + case TILE_STAIRS_SOUTH: + case TILE_STAIRS_EAST: + case TILE_STAIRS_WEST: + return true; + + default: + return false; + } +} + +bool_t tileIsStairs(const tile_t tile) { + switch(tile) { + case TILE_STAIRS_NORTH: + case TILE_STAIRS_SOUTH: + case TILE_STAIRS_EAST: + case TILE_STAIRS_WEST: + return true; + + default: + return false; + } } \ No newline at end of file diff --git a/src/rpg/world/tile.h b/src/rpg/world/tile.h index 367ddfc..4f68193 100644 --- a/src/rpg/world/tile.h +++ b/src/rpg/world/tile.h @@ -6,15 +6,18 @@ */ #pragma once -#include "dusk.h" - +#include "rpg/entity/entitydir.h" typedef uint8_t tile_t; #define TILE_NULL 0 #define TILE_WALKABLE 1 -#define TILE_STAIRS_UP 2 -#define TILE_STAIRS_DOWN 3 +#define TILE_STAIRS_SOUTH (2 + ENTITY_DIR_SOUTH) +#define TILE_STAIRS_EAST (2 + ENTITY_DIR_EAST) +#define TILE_STAIRS_WEST (2 + ENTITY_DIR_WEST) +#define TILE_STAIRS_NORTH (2 + ENTITY_DIR_NORTH) +#define TILE_TEST 6 + /** * Returns whether or not the given tile is walkable. @@ -22,4 +25,12 @@ typedef uint8_t tile_t; * @param tile The tile to check. * @return bool_t True if walkable, false if not. */ -bool_t tileIsWalkable(const tile_t tile); \ No newline at end of file +bool_t tileIsWalkable(const tile_t tile); + +/** + * Returns whether or not the given tile is a stairs tile. + * + * @param tile The tile to check. + * @return bool_t True if stairs, false if not. + */ +bool_t tileIsStairs(const tile_t tile); \ No newline at end of file diff --git a/src/rpg/world/worldpos.h b/src/rpg/world/worldpos.h index f4e9318..ba73555 100644 --- a/src/rpg/world/worldpos.h +++ b/src/rpg/world/worldpos.h @@ -10,7 +10,7 @@ #define CHUNK_WIDTH 16 #define CHUNK_HEIGHT 16 -#define CHUNK_DEPTH 8 +#define CHUNK_DEPTH 4 #define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) #define MAP_CHUNK_WIDTH 3 diff --git a/tools/assetstool/processmap.py b/tools/assetstool/processmap.py index 82a908d..6851449 100644 --- a/tools/assetstool/processmap.py +++ b/tools/assetstool/processmap.py @@ -8,7 +8,7 @@ from assethelpers import getAssetRelativePath CHUNK_WIDTH = 16 CHUNK_HEIGHT = 16 -CHUNK_DEPTH = 8 +CHUNK_DEPTH = 4 CHUNK_TILE_COUNT = CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH TILE_WIDTH = 16.0 TILE_HEIGHT = 16.0 @@ -17,6 +17,7 @@ TILE_DEPTH = 11.36 def processTile(tileIndex, x=0, y=0, z=0): vertices = [] indices = [] + tileType = tileIndex # Placement X, Y, Z px = x * TILE_WIDTH @@ -59,7 +60,8 @@ def processTile(tileIndex, x=0, y=0, z=0): return { 'vertices': vertices, - 'indices': indices + 'indices': indices, + 'tileType': tileType } def processChunk(path): @@ -88,7 +90,6 @@ def processChunk(path): for i, tile in enumerate(inData['tiles']): # Set to chunk - chunk['tiles'][i] = tile # Calculate x, y, z from i x = i % CHUNK_WIDTH @@ -104,6 +105,7 @@ def processChunk(path): baseModel['indices'].extend(quad_indices) baseModel['vertexCount'] = len(baseModel['vertices']) baseModel['indexCount'] = len(baseModel['indices']) + chunk['tiles'][i] = result['tileType'] # Generate binary buffer for efficient output buffer = bytearray()