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;