From 9a306df7e5b1c810bf3378e2c1bd11cadc0d3837 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Wed, 18 Jun 2025 14:06:03 -0500 Subject: [PATCH] Change entity to use fixed_t --- Dusk.gb | Bin 32768 -> 0 bytes data/map.tmj | 23 ++- data/overworld.tsx | 12 ++ src/dusk/entity/entity.h | 4 +- src/dusk/entity/player.c | 28 +-- src/dusk/entity/player.h | 5 +- src/dusk/util/CMakeLists.txt | 1 + src/dusk/util/fixed.c | 92 ++++++++++ src/dusk/util/fixed.h | 182 ++++++++++++++++++++ src/dusk/world/chunk.c | 6 +- src/dusk/world/overworld.c | 4 +- src/duskraylib/display/draw/drawoverworld.c | 4 +- 12 files changed, 329 insertions(+), 32 deletions(-) delete mode 100644 Dusk.gb create mode 100644 src/dusk/util/fixed.c create mode 100644 src/dusk/util/fixed.h diff --git a/Dusk.gb b/Dusk.gb deleted file mode 100644 index a2c2711da22490c4376187e3dcba59228ccfe55d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 zcmeI!Z%7+=7zglQ?#`&yL{rx;({)}hqlENLR?CpAJ5pQBwlcC8)og<{g@IBA3KJS@ zR?WIH?7J$gtRSmh84TY9Tj(F8kPreM@wy2MTS4IhOBTyIqE>sR&f6~+t(&+)8SKrz z54k_T-#yRWb004kHSO6kw|-bK@v9QuuNUe}e4)5kilvP0+h{yYHpb7pO{APR9aR~3 zSLd&3yLBt5I)ZG`i@2|23kd z%x3`0_~djTawWjYgCf<*;%{c}FZ)j#_>swyirizqeJLI^5*4=NYs3l&dfGjp0)SM#21crv04ohJFATaFcp{wbV3 zr+0iZbcbK=yUi~gdAF*{$*_L9T<4ed<2N0w-MZ4Zzo#VOGm_q+9};o{8{@1?xu|Sr zRT2?|Z9ih0AUty!6Sjn?(TaawUe_$+(UgspXXGnfjoq`-cxrteXYIY zd<8A?wZ$~#=1`>{VEq!4gIvdR8g;g8C0X5r5g27 zF*&Wbl&hfqr_?fc*Gcc$Q_1E=pNnQ|Hj8+7C$0vKL zjvcR~+hVR>#8q#koA}3N{3A(!(DFythFt}^9%?Soi2+Kamb<-fpWE*a&@XVYs{RsR zU1u*AK_9eeNZiI-hhW8(aoK-!Ovk!pl~!_~h*2S9bBs^nL>E zl4@+X?$~{iUa8i>><%Z22=wXh=uS3;vNh-Yp=>^o{LsN9zcJR9UJdm2XtO4ME+!ST z{U_8)y}gcZ`4JbBGW1j)N2Rs8xKqKG*~nK`)<#AW$)+S5%ChIZqH^t=FFl<~6c*xN z1WG3jG4?ZAC2;0ow(*8<7oUku@0m>XW>*6u|Cw)aD9hgPCam9Yc_WauHG>{&Yqff8 zjxBl&421O<7#P%}jf|1ME*s~gZ>=$n9@z{{qwm_yA@;TxU`zh`n%O=@pZ$;Xj2rQ{ z>uyYLZn^(i5MpRyZQe5ab0Al8TYsdV_n!*nLjVF0fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## oAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1pcMKpRo0>%m4rY 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 @@ + + + + + + + + + + + + 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;