a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit 95ca73881d3574d11836b15c9f57c5612e2be527
parent 4d4daf18edfc2abab152ec4b2bb816f39e7a459d
Author: amin <dev@aminmesbah.com>
Date:   Sat, 11 May 2019 20:58:16 +0000

Fix chunks spanning [-1, 0] room index boundary

Now we can successfully traverse the boundary between positive and
negative room indices.

FossilOrigin-Name: a69aee9835c126cc7a6343332e74d766b0887f80a2129b83489fd5ada4928b71
Diffstat:
Msrc/game.c | 6++----
Msrc/game.h | 2++
Msrc/intrinsics.h | 22++++++++++++++++++++++
Msrc/world.c | 18++++++++++--------
Msrc/world.h | 2+-
5 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -64,7 +64,7 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer) //world_room_set(game_state->world, collision_test_zone, &game_state->world_allocator); //world_room_set(game_state->world, knytt_hanging_fly_village, &game_state->world_allocator); - i32 s = 0; + i32 s = -100; i32 f = 100; for (i32 x = s; x < f; x++) { @@ -221,9 +221,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga math_print(current_room_i); printf("Current Actual Room: "); math_print(r->index); - printf("Expected Chunk Index: "); - math_print(c_i); - printf("Actual Chunk Index: "); + printf("Chunk Index: "); math_print(c->index); } diff --git a/src/game.h b/src/game.h @@ -17,6 +17,8 @@ #include "world.h" #include "platform.h" +static_assert(-1 == ~0, "Implementation doesn't use two's complement"); + // One tile is one square meter #define TILE_SIZE 1.0f diff --git a/src/intrinsics.h b/src/intrinsics.h @@ -5,3 +5,25 @@ static_assert(__has_builtin(__builtin_clz), "No builtin clz intrinsic"); #define intr_clz(x) __builtin_clz((x)) + +internal inline i32 intr_mod(i32 x, i32 y) +{ + // NOTE(amin): There are multiple valid definitions of an operation that + // gets the remainder of an integer division: `x / y`. Such an operation + // must satisfy this equation: + // + // x == (quotient * y) + remainder + // + // The value computed for `remainder` will differ (when x or y is negative) + // based on the method of computing `quotient`. + // + // C's `%` operator is based on truncated integer division. This operation + // is often called 'rem' in other languages. + // + // Python's `%` operator is based on floored integer division. This + // operation is often called 'mod' in other languages. + // + // Here we implement 'mod'. + i32 result = ((x % y) + y) % y; + return result; +} diff --git a/src/world.c b/src/world.c @@ -31,15 +31,12 @@ internal struct AbsolutePos world_pos_recanonicalize(struct AbsolutePos p) internal inline v2i world_room_get_chunk_index(v2i room_i) { - // NOTE(amin): integer division here is intentional. We want a square of - // CHUNK_NUM_ROOMS rooms to all have the same chunk index. + // NOTE(amin): truncated integer division here is intentional. We want a + // square of CHUNK_NUM_ROOMS rooms to all have the same chunk index. - // TODO: Figure out the difference between % in c and % in python that - // gives this expression the desired behavior in the latter and not in the - // former. v2i chunk_i = { - (room_i.x - (room_i.x % CHUNK_ROOMS_PER_SIDE)) / CHUNK_ROOMS_PER_SIDE, - (room_i.y - (room_i.y % CHUNK_ROOMS_PER_SIDE)) / CHUNK_ROOMS_PER_SIDE, + (room_i.x - (intr_mod(room_i.x, CHUNK_ROOMS_PER_SIDE))) / CHUNK_ROOMS_PER_SIDE, + (room_i.y - (intr_mod(room_i.y, CHUNK_ROOMS_PER_SIDE))) / CHUNK_ROOMS_PER_SIDE, }; return chunk_i; } @@ -126,7 +123,12 @@ internal struct WorldChunk* world_chunk_get_or_create(struct World *world, v2i c internal size_t world_room_get_index_within_chunk(v2i room_i) { - static_assert(-1 == ~0, "implementation doesn't use two's complement"); + // TODO: assert that no chunk ever spans the [-1, 0] room index boundary. + + // NOTE(amin): Because we are using only the lower bits here, we will get + // index collisions if both positive and negative numbers appear in the + // same chunk. For example with two's complement, the first 7 bits of 127 + // and -1 are identical. v2u room_i_lower_bits = { room_i.x & CHUNK_MASK_FOR_INTERNAL_ROOM_INDEX, room_i.y & CHUNK_MASK_FOR_INTERNAL_ROOM_INDEX, diff --git a/src/world.h b/src/world.h @@ -13,7 +13,7 @@ static_assert( ); // TODO: Tune chunk size -#define CHUNK_ROOMS_PER_SIDE 2 +#define CHUNK_ROOMS_PER_SIDE 4 static_assert( math_is_pow_2(CHUNK_ROOMS_PER_SIDE), "Must be a power of 2 for the chunk mask to work"