From d53b5eab49d4922240af9d2e9ac6530deba546d8 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Mon, 3 Mar 2025 00:57:36 -0600 Subject: [PATCH] Getting tile data from overworld --- src/dusk/overworld/CMakeLists.txt | 1 + src/dusk/overworld/entity.c | 51 +++++++++++++++---- src/dusk/overworld/overworld.c | 31 ++++++++++- src/dusk/overworld/overworld.h | 42 ++++++++++++++- src/dusk/overworld/tile.c | 19 +++++++ src/dusk/overworld/tile.h | 11 +++- src/duskgl/display/shader/data/map.c | 4 +- src/duskgl/display/shader/data/map.glsl | 7 ++- .../display/shader/fragments/packed.glsl | 22 +++++++- .../display/shader/mapshader/map_frag.glsl | 11 ++-- 10 files changed, 176 insertions(+), 23 deletions(-) create mode 100644 src/dusk/overworld/tile.c diff --git a/src/dusk/overworld/CMakeLists.txt b/src/dusk/overworld/CMakeLists.txt index 2a7b70f..3d0218f 100644 --- a/src/dusk/overworld/CMakeLists.txt +++ b/src/dusk/overworld/CMakeLists.txt @@ -9,6 +9,7 @@ target_sources(${DUSK_TARGET_NAME} entity.c overworld.c player.c + tile.c ) # Subdirs \ No newline at end of file diff --git a/src/dusk/overworld/entity.c b/src/dusk/overworld/entity.c index a073ac4..c1f1595 100644 --- a/src/dusk/overworld/entity.c +++ b/src/dusk/overworld/entity.c @@ -8,7 +8,7 @@ #include "entity.h" #include "assert/assert.h" #include "util/memory.h" -#include "overworlddefs.h" +#include "overworld.h" entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = { { NULL, NULL }, @@ -68,27 +68,58 @@ void entityMove(entity_t *ent, const facingdir_t dir) { entityTurn(ent, dir); - // Move + uint8_t targetX = ent->x, targetY = ent->y; switch(dir) { case FACING_DIRECTION_EAST: - ent->x++; - ent->subX = -OVERWORLD_ENTITY_WIDTH; + if(ent->x >= OVERWORLD.mapWidth - 1) return; + targetX++; break; case FACING_DIRECTION_WEST: - ent->x--; - ent->subX = OVERWORLD_ENTITY_WIDTH; + if(ent->x == 0) return; + targetX--; break; case FACING_DIRECTION_NORTH: - ent->y++; - ent->subY = -OVERWORLD_ENTITY_HEIGHT; + if(ent->y >= OVERWORLD.mapHeight - 1) return; + targetY++; break; case FACING_DIRECTION_SOUTH: - ent->y--; - ent->subY = OVERWORLD_ENTITY_HEIGHT; + if(ent->y == 0) return; + targetY--; break; default: assertUnreachable("Invalid facing direction"); } + + // Check tile at target + uint8_t i = 0; + tileid_t tileId; + for(i = 0; i < OVERWORLD.mapLayerCount; i++) { + tileId = overworldTileGet(0, targetX, targetY); + if(tileIsSolid(tileId)) return; + } + + // Check for entity at target + entity_t *atPos = overworldEntityGetAtPosition(targetX, targetY); + if(atPos != NULL) return; + + // Commit to move + ent->x = targetX; + ent->y = targetY; + + switch(dir) { + case FACING_DIRECTION_EAST: + ent->subX = -OVERWORLD_ENTITY_WIDTH; + break; + case FACING_DIRECTION_WEST: + ent->subX = OVERWORLD_ENTITY_WIDTH; + break; + case FACING_DIRECTION_NORTH: + ent->subY = -OVERWORLD_ENTITY_HEIGHT; + break; + case FACING_DIRECTION_SOUTH: + ent->subY = OVERWORLD_ENTITY_HEIGHT; + break; + } } bool entityIsMoving(const entity_t *ent) { diff --git a/src/dusk/overworld/overworld.c b/src/dusk/overworld/overworld.c index fdf4a03..0539288 100644 --- a/src/dusk/overworld/overworld.c +++ b/src/dusk/overworld/overworld.c @@ -17,7 +17,7 @@ void overworldInit() { // Test OVERWORLD.mapWidth = 16; OVERWORLD.mapHeight = 16; - OVERWORLD.mapLayerCount = 2; + OVERWORLD.mapLayerCount = 1; memset(&OVERWORLD.tileIds, 0x01, sizeof(OVERWORLD.tileIds)); @@ -44,4 +44,33 @@ void overworldUpdate() { while(i < OVERWORLD.entityCount) { entityUpdate(OVERWORLD.entities + i++); } +} + +uint32_t overworldTileGetIndex( + const uint8_t layer, + const uint8_t x, + const uint8_t y +) { + return ( + (layer * OVERWORLD.mapWidth * OVERWORLD.mapHeight) + + (y * OVERWORLD.mapWidth) + + x + ); +} + +tileid_t overworldTileGet( + const uint8_t layer, + const uint8_t x, + const uint8_t y +) { + return OVERWORLD.tileIds[overworldTileGetIndex(layer, x, y)]; +} + +entity_t * overworldEntityGetAtPosition(const uint8_t x, const uint8_t y) { + uint8_t i = 0; + while(i < OVERWORLD.entityCount) { + entity_t * entity = OVERWORLD.entities + i++; + if(entity->x == x && entity->y == y) return entity; + } + return NULL; } \ No newline at end of file diff --git a/src/dusk/overworld/overworld.h b/src/dusk/overworld/overworld.h index 4fb6c48..6f19894 100644 --- a/src/dusk/overworld/overworld.h +++ b/src/dusk/overworld/overworld.h @@ -45,4 +45,44 @@ void overworldUpdate(); /** * Platform level render method. Refer to sceneRender for information. */ -void overworldRender(); \ No newline at end of file +void overworldRender(); + +/** + * Returns the index of the tile at the given position. + * + * @param layer The layer to get the tile from. + * @param x The x position of the tile. + * @param y The y position of the tile. + * @return The index of the tile at the given position. + */ +uint32_t overworldTileGetIndex( + const uint8_t layer, + const uint8_t x, + const uint8_t y +); + +/** + * Returns the tile at the given position. + * + * @param layer The layer to get the tile from. + * @param x The x position of the tile. + * @param y The y position of the tile. + * @return The tile id at the given position. + */ +tileid_t overworldTileGet( + const uint8_t layer, + const uint8_t x, + const uint8_t y +); + +/** + * Returns the entity at the given position. + * + * @param x The x position of the entity. + * @param y The y position of the entity. + * @return The entity at the given position. + */ +entity_t * overworldEntityGetAtPosition( + const uint8_t x, + const uint8_t y +); \ No newline at end of file diff --git a/src/dusk/overworld/tile.c b/src/dusk/overworld/tile.c new file mode 100644 index 0000000..2b5a548 --- /dev/null +++ b/src/dusk/overworld/tile.c @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "tile.h" + +bool_t tileIsSolid(const tileid_t id) { + switch(id) { + case TILE_ID_NULL: + case TILE_ID_GRASS: + return false; + + default: + return true; + } +} \ No newline at end of file diff --git a/src/dusk/overworld/tile.h b/src/dusk/overworld/tile.h index 70f6aa2..d49c546 100644 --- a/src/dusk/overworld/tile.h +++ b/src/dusk/overworld/tile.h @@ -14,4 +14,13 @@ typedef struct { uint32_t nothing; } tiledata_t; -#define TILE_ID_NULL 0 \ No newline at end of file +#define TILE_ID_NULL 0 +#define TILE_ID_GRASS 1 + +/** + * Returns whether or not the tile is solid. + * + * @param id The tile id to check. + * @return Whether or not the tile is solid. + */ +bool_t tileIsSolid(const tileid_t id); \ No newline at end of file diff --git a/src/duskgl/display/shader/data/map.c b/src/duskgl/display/shader/data/map.c index ed1a14d..3141f5f 100644 --- a/src/duskgl/display/shader/data/map.c +++ b/src/duskgl/display/shader/data/map.c @@ -25,8 +25,8 @@ void mapInit() { void mapUpdate() { // Copy tile ids. memoryCopyRangeSafe( - &MAP_DATA.tileIds, - &OVERWORLD.tileIds[0], + MAP_DATA.tileIds, + OVERWORLD.tileIds, &OVERWORLD.tileIds[ OVERWORLD.mapWidth * OVERWORLD.mapHeight * OVERWORLD.mapLayerCount ], diff --git a/src/duskgl/display/shader/data/map.glsl b/src/duskgl/display/shader/data/map.glsl index 619c522..1cfd4fb 100644 --- a/src/duskgl/display/shader/data/map.glsl +++ b/src/duskgl/display/shader/data/map.glsl @@ -7,8 +7,10 @@ #include "../fragments/packed.glsl" #include "../fragments/quad.glsl" +#define MAP_TILE_PACKED_SIZE 16 + layout(std140) uniform b_Map { - uvec4 mapTileIds[OVERWORLD_TILE_COUNT_MAX / PACKED_U8_PER_UVEC4]; + uvec4 mapTileIds[OVERWORLD_TILE_COUNT_MAX / MAP_TILE_PACKED_SIZE]; uint mapSize; uvec3 _padding0; }; @@ -42,5 +44,6 @@ uint mapGetLayer(uint instanceIndex) { } uint mapGetTileId(uint instanceIndex) { - + uvec4 v4 = mapTileIds[packedArrayGetU8IndexFromUVEC4Array(instanceIndex)]; + return packedArrayGetU8FromUVEC4ArrayValue(instanceIndex, v4); } \ No newline at end of file diff --git a/src/duskgl/display/shader/fragments/packed.glsl b/src/duskgl/display/shader/fragments/packed.glsl index a40ff22..1feb15a 100644 --- a/src/duskgl/display/shader/fragments/packed.glsl +++ b/src/duskgl/display/shader/fragments/packed.glsl @@ -4,13 +4,33 @@ // https://opensource.org/licenses/MIT #define PACKED_U8_PER_UI 4 -#define PACKED_U8_PER_UVEC4 PACKED_U8_PER_UI / 4 +#define PACKED_U8_PER_UVEC4 PACKED_U8_PER_UI * 4 uint packedGetU8(uint position, uint data) { return (data >> (position * 8u)) & 0xFFu; } +uint packedGetU8FromVEC4(uint position, vec4 data) { + return packedGetU8(position, uint(data[position / 4u])); +} + int packedGetI8(uint position, uint data) { int shift = int(position * 8u); return int(data << (24 - shift)) >> 24; +} + +uint packedArrayGetU8IndexFromUVEC4Array(uint u8ArrayIndex) { + // Given a uint8_t array is uploaded, this will return the index to get the + // appropriate uvec4 from a uvec4 array that will be at the right index. + return u8ArrayIndex / uint(PACKED_U8_PER_UVEC4); +} + +uint packedArrayGetU8FromUVEC4ArrayValue(uint u8ArrayIndex, uvec4 data) { + // Given a value from a uint8_t array, this will return the value at the + // appropriate index. You must first get the uvec4 from the array using + // packedArrayGetU8IndexFromUVEC4Array. + uint subIndex = (u8ArrayIndex % uint(PACKED_U8_PER_UVEC4)) / uint(PACKED_U8_PER_UI); + uint shiftAmount = (u8ArrayIndex % uint(PACKED_U8_PER_UI)) * 8u; + uint value = (data[subIndex] >> shiftAmount) & 0xFFu; + return value; } \ No newline at end of file diff --git a/src/duskgl/display/shader/mapshader/map_frag.glsl b/src/duskgl/display/shader/mapshader/map_frag.glsl index a35781f..eae047c 100644 --- a/src/duskgl/display/shader/mapshader/map_frag.glsl +++ b/src/duskgl/display/shader/mapshader/map_frag.glsl @@ -16,12 +16,13 @@ out vec4 FragColor; void main() { uint layer = mapGetLayer(v_InstanceIndex); + uint tileId = mapGetTileId(v_InstanceIndex); - if(layer == 0u) { - FragColor = vec4(1, 0, 0, 0.5); + if(tileId == 0u) { + FragColor = vec4(1, 0, 0, 1); + } else if(tileId == 1u) { + FragColor = vec4(0, 1, 0, 1); } else { - FragColor = vec4(0, 1, 0, 0.5); + FragColor = vec4(0, 0, 1, 1); } - - // FragColor = vec4(1, 0, 0, 1); } \ No newline at end of file