commit e42269fa3745f6c6610263ee5bd8d58fcefd3ff0
parent 3418f76c8a1741b85df476212d4375f860c9c9bc
Author: amin <dev@aminmesbah.com>
Date:   Fri, 26 Apr 2019 01:01:43 +0000
Move between two rooms
FossilOrigin-Name: 0187b03d62d68adcc2c345b422673cb3f107029d259327c8404f09de952c5a18
Diffstat:
3 files changed, 89 insertions(+), 6 deletions(-)
diff --git a/src/game.c b/src/game.c
@@ -4,6 +4,8 @@
 
 // One tile is one square meter
 #define TILE_SIZE 1.0f
+// TODO: delete
+#define NUM_ROOMS 2
 
 #ifdef PLATFORM_HOTLOAD_GAME_CODE
 void game_load_opengl_symbols(void)
@@ -16,8 +18,13 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer)
 {
     struct GameState *game_state = game_memory->game_state;
 
+    game_state->player_pos_absolute = (struct AbsolutePos) {
+        .room_index = {0, 0},
+        .room_offset = {12.5f, 5.0f},
+    };
+
     // init player
-    game_state->player.pos = (v2) {12.5f, 5.0f};
+    game_state->player.pos = game_state->player_pos_absolute.room_offset;
 
     // In Knytt, the player is 9 by 14 texels and a tile is 24 by 24 texels.
     // These dimensions are relative to a square 'meter', one tile
@@ -85,6 +92,58 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer)
     }
 }
 
+internal struct AbsolutePos pos_recanonicalize(struct AbsolutePos p)
+{
+    struct AbsolutePos p_final = p;
+    v2i room_index_delta = {0};
+
+    if (p.room_offset.x < 0.0f)
+    {
+        room_index_delta.x -= 1;
+        p_final.room_offset.x = glmth_wrap(p.room_offset.x, 0.0f, ROOM_TILE_DIM_X);
+    }
+    else if (p.room_offset.x > ROOM_TILE_DIM_X)
+    {
+        room_index_delta.x += 1;
+        p_final.room_offset.x = glmth_wrap(p.room_offset.x, 0.0f, ROOM_TILE_DIM_X);
+    }
+
+    if (p.room_offset.y < 0.0f)
+    {
+        room_index_delta.y -= 1;
+        p_final.room_offset.y = glmth_wrap(p.room_offset.y, 0.0f, ROOM_TILE_DIM_Y);
+    }
+    else if (p.room_offset.y > ROOM_TILE_DIM_Y)
+    {
+        room_index_delta.y += 1;
+        p_final.room_offset.y = glmth_wrap(p.room_offset.y, 0.0f, ROOM_TILE_DIM_Y);
+    }
+
+    p_final.room_index = glmth_v2i_a(p.room_index, room_index_delta);
+    return p_final;
+}
+
+struct RoomSearchResult
+{
+    bool room_found;
+    size_t room_array_index;
+};
+
+internal struct RoomSearchResult get_room_at_index(struct Room *rooms[NUM_ROOMS], u32 num_rooms, v2i room_i)
+{
+    struct RoomSearchResult result = {0};
+    for (size_t i = 0; i < num_rooms; i++)
+    {
+        struct Room *r = rooms[i];
+        if (r->index.x == room_i.x && r->index.y == room_i.y)
+        {
+            result.room_found = true;
+            result.room_array_index = i;
+        }
+    }
+    return result;
+}
+
 struct WallCollision
 {
     bool collision_occurred;
@@ -320,8 +379,15 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
         },
     };
 
-    u32 *tiles = knytt_hanging_fly_village.tiles;
-    tiles = collision_test_zone.tiles;
+    // TODO: This is, of course, just temporary. Delete it.
+    struct Room *rooms[NUM_ROOMS] = {&collision_test_zone, &knytt_hanging_fly_village};
+
+    v2i current_room_i = game_state->player_pos_absolute.room_index;
+    struct RoomSearchResult r = get_room_at_index(rooms, NUM_ROOMS, current_room_i);
+    assert(r.room_found);
+    struct Room *current_room = rooms[r.room_array_index];
+    assert(current_room);
+    u32 *tiles = current_room->tiles;
 
     // render tiles
     {
@@ -377,7 +443,8 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
                     if (player_is_in_tile && solid)
                     {
                         color = (v3) {0.8f, 0.4f, 0.4f};
-                        assert(false);
+                        // TODO: re-enable this
+                        //assert(false);
                     }
                 }
 
@@ -610,8 +677,11 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
             }
         }
 #undef RENDER_COLLISION_DEBUG_QUAD
-        glmth_clamp(&player->pos.x, 0.0f, ROOM_TILE_DIM_X);
-        glmth_clamp(&player->pos.y, 0.0f, ROOM_TILE_DIM_Y);
+
+        game_state->player_pos_absolute.room_offset = player->pos;
+        struct AbsolutePos new_canonical_p = pos_recanonicalize(game_state->player_pos_absolute);
+        game_state->player_pos_absolute = new_canonical_p;
+        player->pos = game_state->player_pos_absolute.room_offset;
     }
 
     // render player
diff --git a/src/game.h b/src/game.h
@@ -39,10 +39,17 @@ struct Room
     u32 tiles[ROOM_TILE_DIM_Y * ROOM_TILE_DIM_X];
 };
 
+struct AbsolutePos
+{
+    v2i room_index;
+    v2 room_offset;
+};
+
 struct GameState
 {
     struct RendererState renderer;
     struct Entity player;
+    struct AbsolutePos player_pos_absolute;
 };
 
 internal void game_init(struct GameMemory *game_memory, v2u framebuffer);
diff --git a/src/glmth.h b/src/glmth.h
@@ -187,6 +187,12 @@ internal inline f32 glmth_v2_dot(v2 vec1, v2 vec2)
     return dot_product;
 }
 
+internal inline v2i glmth_v2i_a(v2i vec1, v2i vec2)
+{
+    v2i r = {vec1.x + vec2.x, vec1.y + vec2.y};
+    return r;
+}
+
 internal inline v3 glmth_v3_cross(v3 vec1, v3 vec2)
 {
     // cross product, a.k.a. outer product or vector product