Make stairs work

This commit is contained in:
2025-11-11 22:12:08 -06:00
parent 4f8f6a47cb
commit 9f23533069
10 changed files with 103 additions and 48 deletions

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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,

View File

@@ -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.
*

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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);
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);

View File

@@ -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

View File

@@ -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()