diff --git a/Dusk.gb b/Dusk.gb deleted file mode 100644 index a2c2711..0000000 Binary files a/Dusk.gb and /dev/null differ diff --git a/data/map.tmj b/data/map.tmj index 0ded389..0a5dc76 100644 --- a/data/map.tmj +++ b/data/map.tmj @@ -270,6 +270,7 @@ }], "height":32, "id":1, + "locked":true, "name":"Base Layer", "opacity":1, "startx":384, @@ -394,6 +395,7 @@ }], "height":32, "id":5, + "locked":true, "name":"Overlay Base Layer", "opacity":1, "startx":400, @@ -407,20 +409,19 @@ { "draworder":"topdown", "id":3, - "locked":true, "name":"Object Layer 1", "objects":[ { "id":3, "template":"templates\/NPC.tx", - "x":6434.3106060606, - "y":6672.13636363636 + "x":6551.3106060606, + "y":6829.13636363636 }, { "id":4, "template":"templates\/NPC.tx", - "x":6737, - "y":6672.91666666667 + "x":6649.66666666667, + "y":6741.58333333334 }, { "gid":257, @@ -431,8 +432,14 @@ "type":"player_spawn", "visible":true, "width":16, - "x":6743.33333333333, - "y":6989.33333333333 + "x":6591.33333333333, + "y":6787 + }, + { + "id":7, + "template":"templates\/NPC.tx", + "x":6627, + "y":6828.33333333333 }], "opacity":1, "type":"objectgroup", @@ -441,7 +448,7 @@ "y":0 }], "nextlayerid":6, - "nextobjectid":7, + "nextobjectid":8, "orientation":"orthogonal", "renderorder":"right-down", "tiledversion":"1.11.1", diff --git a/data/overworld.tsx b/data/overworld.tsx index d1617f7..cbfff52 100644 --- a/data/overworld.tsx +++ b/data/overworld.tsx @@ -1,4 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <tileset version="1.10" tiledversion="1.11.1" name="overworld" tilewidth="16" tileheight="16" tilecount="256" columns="16"> <image source="tilemap.png" width="256" height="256"/> + <tile id="54"> + <objectgroup draworder="index" id="3"> + <object id="3" x="5.04743" y="5.92885" width="7.93676" height="6.0751"/> + </objectgroup> + </tile> + <tile id="81"> + <objectgroup draworder="index" id="2"> + <object id="1" x="3.18182" y="0.181818"> + <polygon points="-0.09375,-0.09375 -1.44602,6.42898 6.09091,13 12.9148,13.0057 12.8523,-0.125"/> + </object> + </objectgroup> + </tile> </tileset> diff --git a/src/dusk/entity/entity.h b/src/dusk/entity/entity.h index 1630fb1..2ce559d 100644 --- a/src/dusk/entity/entity.h +++ b/src/dusk/entity/entity.h @@ -8,6 +8,7 @@ #pragma once #include "player.h" #include "npc.h" +#include "util/fixed.h" #define ENTITY_COUNT_MAX 32 @@ -32,7 +33,8 @@ typedef enum { typedef struct _entity_t { uint32_t id;// Completely unique ID for this entity. - float_t x, y; + fixed248_t x, y; + fixed248_t vx, vy; entitytype_t type; entitydir_t dir; diff --git a/src/dusk/entity/player.c b/src/dusk/entity/player.c index c7e37ad..1086081 100644 --- a/src/dusk/entity/player.c +++ b/src/dusk/entity/player.c @@ -17,8 +17,8 @@ void playerInit() { entityInit(ent, ENTITY_TYPE_PLAYER); ent->id = PLAYER_ENTITY_ID; - ent->x = WORLD_PLAYER_SPAWN_X; - ent->y = WORLD_PLAYER_SPAWN_Y; + ent->x = fx248Fromui32(WORLD_PLAYER_SPAWN_X); + ent->y = fx248Fromui32(WORLD_PLAYER_SPAWN_Y); } void playerNPCInit(entity_t *entity) { @@ -32,47 +32,47 @@ void playerNPCUpdate(entity_t *entity) { if(inputIsDown(INPUT_BIND_UP)) { if(inputIsDown(INPUT_BIND_LEFT)) { - entity->x -= PLAYER_MOVE_SPEED_XY; - entity->y -= PLAYER_MOVE_SPEED_XY; + fx248Subfx248(&entity->x, PLAYER_MOVE_SPEED_XY); + fx248Subfx248(&entity->y, PLAYER_MOVE_SPEED_XY); if(entity->dir != ENTITY_DIR_NORTH && entity->dir != ENTITY_DIR_WEST) { entity->dir = ENTITY_DIR_NORTH; } } else if(inputIsDown(INPUT_BIND_RIGHT)) { - entity->x += PLAYER_MOVE_SPEED_XY; - entity->y -= PLAYER_MOVE_SPEED_XY; + fx248Addfx248(&entity->x, PLAYER_MOVE_SPEED_XY); + fx248Subfx248(&entity->y, PLAYER_MOVE_SPEED_XY); if(entity->dir != ENTITY_DIR_NORTH && entity->dir != ENTITY_DIR_EAST) { entity->dir = ENTITY_DIR_NORTH; } } else { - entity->y -= PLAYER_MOVE_SPEED; + fx248Subfx248(&entity->y, PLAYER_MOVE_SPEED); entity->dir = ENTITY_DIR_NORTH; } } else if(inputIsDown(INPUT_BIND_DOWN)) { if(inputIsDown(INPUT_BIND_LEFT)) { - entity->x -= PLAYER_MOVE_SPEED_XY; - entity->y += PLAYER_MOVE_SPEED_XY; + fx248Subfx248(&entity->x, PLAYER_MOVE_SPEED_XY); + fx248Addfx248(&entity->y, PLAYER_MOVE_SPEED_XY); if(entity->dir != ENTITY_DIR_SOUTH && entity->dir != ENTITY_DIR_WEST) { entity->dir = ENTITY_DIR_SOUTH; } } else if(inputIsDown(INPUT_BIND_RIGHT)) { - entity->x += PLAYER_MOVE_SPEED_XY; - entity->y += PLAYER_MOVE_SPEED_XY; + fx248Addfx248(&entity->x, PLAYER_MOVE_SPEED_XY); + fx248Addfx248(&entity->y, PLAYER_MOVE_SPEED_XY); if(entity->dir != ENTITY_DIR_SOUTH && entity->dir != ENTITY_DIR_EAST) { entity->dir = ENTITY_DIR_SOUTH; } } else { - entity->y += PLAYER_MOVE_SPEED; + fx248Addfx248(&entity->y, PLAYER_MOVE_SPEED); entity->dir = ENTITY_DIR_SOUTH; } } else if(inputIsDown(INPUT_BIND_LEFT)) { - entity->x -= PLAYER_MOVE_SPEED; + fx248Subfx248(&entity->x, PLAYER_MOVE_SPEED); entity->dir = ENTITY_DIR_WEST; } else if(inputIsDown(INPUT_BIND_RIGHT)) { - entity->x += PLAYER_MOVE_SPEED; + fx248Addfx248(&entity->x, PLAYER_MOVE_SPEED); entity->dir = ENTITY_DIR_EAST; } } \ No newline at end of file diff --git a/src/dusk/entity/player.h b/src/dusk/entity/player.h index 1b496ac..54ebe11 100644 --- a/src/dusk/entity/player.h +++ b/src/dusk/entity/player.h @@ -7,6 +7,7 @@ #pragma once #include "dusk.h" +#include "util/fixed.h" typedef struct _entity_t entity_t; @@ -15,8 +16,8 @@ typedef struct { } playerentity_t; #define PLAYER_ENTITY_ID (UINT32_MAX-1) -#define PLAYER_MOVE_SPEED 1.0f -#define PLAYER_MOVE_SPEED_XY (PLAYER_MOVE_SPEED * 0.70710678118f) +#define PLAYER_MOVE_SPEED FIXED248(1, 0) +#define PLAYER_MOVE_SPEED_XY FIXED248(0, 70) /** * Initializes the player and all player-related entities. diff --git a/src/dusk/util/CMakeLists.txt b/src/dusk/util/CMakeLists.txt index 59462e2..acbc06d 100644 --- a/src/dusk/util/CMakeLists.txt +++ b/src/dusk/util/CMakeLists.txt @@ -6,5 +6,6 @@ # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE + fixed.c memory.c ) \ No newline at end of file diff --git a/src/dusk/util/fixed.c b/src/dusk/util/fixed.c new file mode 100644 index 0000000..d925d02 --- /dev/null +++ b/src/dusk/util/fixed.c @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "fixed.h" + +fixed248_t fx248Fromi32(const int32_t b) { + return (fixed248_t)b << FIXED248_FRACTION_BITS; +} + +fixed248_t fx248Fromui32(const uint32_t b) { + return (fixed248_t)b << FIXED248_FRACTION_BITS; +} + +fixed248_t fx248Fromf32(const float_t b) { + return (fixed248_t)(b * (1 << FIXED248_FRACTION_BITS)); +} + +int32_t fx248Toi32(const fixed248_t a) { + return (int32_t)(a >> FIXED248_FRACTION_BITS); +} + +uint32_t fx248Tou32(const fixed248_t a) { + return (uint32_t)(a >> FIXED248_FRACTION_BITS); +} + +float_t fx248Tof32(const fixed248_t a) { + return (float_t)(a / (1 << FIXED248_FRACTION_BITS)); +} + +void fx248Addfx248(fixed248_t *a, const fixed248_t b) { + *a += b; +} + +void fx248Addi32(fixed248_t *a, const int32_t b) { + *a += (fixed248_t)b << FIXED248_FRACTION_BITS; +} + +void fx248Addui32(fixed248_t *a, const uint32_t b) { + *a += (fixed248_t)b << FIXED248_FRACTION_BITS; +} + +void fx248Subfx248(fixed248_t *a, const fixed248_t b) { + *a -= b; +} + +void fx248Subi32(fixed248_t *a, const int32_t b) { + *a -= (fixed248_t)b << FIXED248_FRACTION_BITS; +} + +void fx248Subui32(fixed248_t *a, const uint32_t b) { + *a -= (fixed248_t)b << FIXED248_FRACTION_BITS; +} + +void fx248Subf32(fixed248_t *a, const float_t b) { + *a -= (fixed248_t)(b * (1 << FIXED248_FRACTION_BITS)); +} + +int32_t fx248Floor(const fixed248_t a) { + return (int32_t)(a >> FIXED248_FRACTION_BITS); +} + +int32_t fx248Ceil(const fixed248_t a) { + return (int32_t)(( + a + ((1 << FIXED248_FRACTION_BITS) - 1) + ) >> FIXED248_FRACTION_BITS); +} + +int32_t fx248Round(const fixed248_t a) { + return (int32_t)( + (a + (1 << (FIXED248_FRACTION_BITS - 1)) + ) >> FIXED248_FRACTION_BITS); +} + +uint32_t fx248Flooru32(const fixed248_t a) { + return (uint32_t)(a >> FIXED248_FRACTION_BITS); +} + +uint32_t fx248Ceilu32(const fixed248_t a) { + return (uint32_t)(( + a + ((1 << FIXED248_FRACTION_BITS) - 1) + ) >> FIXED248_FRACTION_BITS); +} + +uint32_t fx248Roundu32(const fixed248_t a) { + return (uint32_t)( + (a + (1 << (FIXED248_FRACTION_BITS - 1)) + ) >> FIXED248_FRACTION_BITS); +} \ No newline at end of file diff --git a/src/dusk/util/fixed.h b/src/dusk/util/fixed.h new file mode 100644 index 0000000..eb73a4d --- /dev/null +++ b/src/dusk/util/fixed.h @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef uint32_t fixed248_t; + +#define FIXED248_FRACTION_BITS 8 +#define FIXED248_HIGH_MULTIPLIER (1 << FIXED248_FRACTION_BITS) +#define FIXED248(i, f) ((fixed248_t)( \ + ((i) << FIXED248_FRACTION_BITS) + \ + (((f) * FIXED248_HIGH_MULTIPLIER) / 100) \ +)) + +/** + * Convert an int32_t value to a fixed248_t value. + * + * @param b The int32_t value to convert. + * @return The converted fixed248_t value. + */ +fixed248_t fx248Fromi32(const int32_t b); + +/** + * Convert a uint32_t value to a fixed248_t value. + * + * @param b The uint32_t value to convert. + * @return The converted fixed248_t value. + */ +fixed248_t fx248Fromui32(const uint32_t b); + +/** + * Convert a float_t value to a fixed248_t value. + * + * @param b The float_t value to convert. + * @return The converted fixed248_t value. + */ +fixed248_t fx248Fromf32(const float_t b); + +/** + * Convert a fixed248_t value to an int32_t value. + * + * @param a The fixed248_t value to convert. + * @return The converted int32_t value. + */ +int32_t fx248Toi32(const fixed248_t a); + +/** + * Convert a fixed248_t value to a uint32_t value. + * + * @param a The fixed248_t value to convert. + * @return The converted uint32_t value. + */ +uint32_t fx248Tou32(const fixed248_t a); + +/** + * Convert a fixed248_t value to a float_t value. + * + * @param a The fixed248_t value to convert. + * @return The converted float_t value. + */ +float_t fx248Tof32(const fixed248_t a); + +/** + * Add a fixed248_t value to another fixed248_t value. + * + * @param a Pointer to the first fixed248_t value (will be modified). + * @param b The fixed248_t value to add to the first value. + */ +void fx248Addfx248(fixed248_t *a, const fixed248_t b); + +/** + * Add an int32_t value to a fixed248_t value. + * + * @param a Pointer to the fixed248_t value (will be modified). + * @param b The int32_t value to add to the fixed248_t value. + */ +void fx248Addi32(fixed248_t *a, const int32_t b); + +/** + * Add a uint32_t value to a fixed248_t value. + * + * @param a Pointer to the fixed248_t value (will be modified). + * @param b The uint32_t value to add to the fixed248_t value. + */ +void fx248Addui32(fixed248_t *a, const uint32_t b); + +/** + * Add a float_t value to a fixed248_t value. + * + * @param a Pointer to the fixed248_t value (will be modified). + * @param b The float_t value to add to the fixed248_t value. + */ +void fx248Addf32(fixed248_t *a, const float_t b); + +/** + * Subtract a fixed248_t value from another fixed248_t value. + * + * @param a Pointer to the first fixed248_t value (will be modified). + * @param b The fixed248_t value to subtract from the first value. + */ +void fx248Subfx248(fixed248_t *a, const fixed248_t b); + +/** + * Subtract an int32_t value from a fixed248_t value. + * + * @param a Pointer to the fixed248_t value (will be modified). + * @param b The int32_t value to subtract from the fixed248_t value. + */ +void fx248Subi32(fixed248_t *a, const int32_t b); + +/** + * Subtract a uint32_t value from a fixed248_t value. + * + * @param a Pointer to the fixed248_t value (will be modified). + * @param b The uint32_t value to subtract from the fixed248_t value. + */ +void fx248Subui32(fixed248_t *a, const uint32_t b); + +/** + * Subtract a float_t value from a fixed248_t value. + * + * @param a Pointer to the fixed248_t value (will be modified). + * @param b The float_t value to subtract from the fixed248_t value. + */ +void fx248Subf32(fixed248_t *a, const float_t b); + +/** + * Convert a fixed248_t value to an int32_t value, rounding towards zero. + * + * @param a The fixed248_t value to convert. + * @return The converted int32_t value. + */ +int32_t fx248Floor(const fixed248_t a); + +/** + * Convert a fixed248_t value to an int32_t value, rounding towards positive + * infinity. + * + * @param a The fixed248_t value to convert. + * @return The converted int32_t value. + */ +int32_t fx248Ceil(const fixed248_t a); + +/** + * Convert a fixed248_t value to an int32_t value, rounding to the nearest + * integer. + * + * @param a The fixed248_t value to convert. + * @return The converted int32_t value. + */ +int32_t fx248Round(const fixed248_t a); + +/** + * Convert a fixed248_t value to a uint32_t value, rounding towards zero. + * + * @param a The fixed248_t value to convert. + * @return The converted uint32_t value. + */ +uint32_t fx248Flooru32(const fixed248_t a); + +/** + * Convert a fixed248_t value to a uint32_t value, rounding towards positive + * infinity. + * + * @param a The fixed248_t value to convert. + * @return The converted uint32_t value. + */ +uint32_t fx248Ceilu32(const fixed248_t a); + +/** + * Convert a fixed248_t value to a uint32_t value, rounding to the nearest + * integer. + * + * @param a The fixed248_t value to convert. + * @return The converted uint32_t value. + */ +uint32_t fx248Roundu32(const fixed248_t a); \ No newline at end of file diff --git a/src/dusk/world/chunk.c b/src/dusk/world/chunk.c index a7e2363..7b5e691 100644 --- a/src/dusk/world/chunk.c +++ b/src/dusk/world/chunk.c @@ -195,7 +195,7 @@ void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) { } // Load tile data into chunk - printf("Loading chunk at (%u, %u)\n", x, y); + // printf("Loading chunk at (%u, %u)\n", x, y); memoryCopy( chunk->tilesBase, chunkData->layerBase, @@ -248,8 +248,8 @@ void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) { entity->id = data->id; // Positions are chunk-relative. - entity->x = (chunk->x * CHUNK_WIDTH * TILE_WIDTH) + data->x; - entity->y = (chunk->y * CHUNK_HEIGHT * TILE_HEIGHT) + data->y; + entity->x = fx248Fromui32((chunk->x * CHUNK_WIDTH * TILE_WIDTH) + data->x); + entity->y = fx248Fromui32((chunk->y * CHUNK_HEIGHT * TILE_HEIGHT)+data->y); // Next entity data++; diff --git a/src/dusk/world/overworld.c b/src/dusk/world/overworld.c index 88305b6..27e868f 100644 --- a/src/dusk/world/overworld.c +++ b/src/dusk/world/overworld.c @@ -47,8 +47,8 @@ void overworldUpdate() { entity->type == ENTITY_TYPE_PLAYER, "First entity must be player" ); - OVERWORLD_CAMERA_X = (uint32_t)floorf(entity->x); - OVERWORLD_CAMERA_Y = (uint32_t)floorf(entity->y); + OVERWORLD_CAMERA_X = fx248Flooru32(entity->x); + OVERWORLD_CAMERA_Y = fx248Flooru32(entity->y); uint16_t x, y; if(OVERWORLD_CAMERA_X < RENDER_WIDTH / 2) { diff --git a/src/duskraylib/display/draw/drawoverworld.c b/src/duskraylib/display/draw/drawoverworld.c index 051d359..c935169 100644 --- a/src/duskraylib/display/draw/drawoverworld.c +++ b/src/duskraylib/display/draw/drawoverworld.c @@ -114,8 +114,8 @@ void drawOverworldDraw(void) { void drawOverworldDrawEntity(const entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); - uint32_t x = (uint32_t)floorf(entity->x); - uint32_t y = (uint32_t)floorf(entity->y); + uint32_t x = fx248Tou32(entity->x); + uint32_t y = fx248Tou32(entity->y); uint32_t row = 0; uint32_t col = entity->dir;