a-game

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

commit c9251221fc319bf126f25bf9b706b943a76ad6a2
parent dd1e59ec2efc9f5403dacbc0891276461618de6b
Author: amin <dev@aminmesbah.com>
Date:   Tue, 30 Apr 2019 03:49:51 +0000

Add a stack allocator and store rooms on the heap

FossilOrigin-Name: a13f61e35a13d77932938f63607a60c2b8168a677557da6c1a7cf104bd1452a8
Diffstat:
Msrc/am_math.h | 6++++++
Msrc/game.c | 99++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/game.h | 14+++++++++++++-
Asrc/memory.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/memory.h | 6++++++
Msrc/platform_linux.c | 2+-
6 files changed, 124 insertions(+), 48 deletions(-)

diff --git a/src/am_math.h b/src/am_math.h @@ -570,6 +570,12 @@ internal inline bool math_v2_ge(v2 v, v2 compare) return is_ge; } +internal inline bool math_is_pow_2(u64 n) +{ + bool is_pow_2 = (n & (n - 1)) == 0; + return is_pow_2; +} + internal inline void math_v2_print(v2 v) { printf("( %f, %f )\n", v.x, v.y); diff --git a/src/game.c b/src/game.c @@ -1,9 +1,7 @@ #include "game.h" #include "glad.c" #include "shader.c" - -// TODO: delete -#define NUM_ROOMS 2 +#include "memory.c" #ifdef PLATFORM_HOTLOAD_GAME_CODE void game_load_opengl_symbols(void) @@ -27,6 +25,53 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer) // These dimensions are relative to a square 'meter', one tile game_state->player.dimensions = (v2) {0.375f, 0.583f}; + mem_st_init( + &game_state->world_allocator, + game_memory->buffer + sizeof(struct GameState), + game_memory->buffer_size - sizeof(struct GameState)); + + + game_state->world = mem_st_alloc_struct(&game_state->world_allocator, struct World); + + + struct Room knytt_hanging_fly_village = { + .index = {0, 0}, + .tiles = { + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }, + }; + + struct Room collision_test_zone = { + .index = {0, 1}, + .tiles = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, + 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, + + 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, + 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, + 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, + 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }; + + game_state->world->rooms[0] = collision_test_zone; + game_state->world->rooms[1] = knytt_hanging_fly_village; + game_state->world->num_rooms = 2; + // set up and load tiles { GLfloat quad_vertices[] = { @@ -126,12 +171,12 @@ struct RoomSearchResult size_t room_array_index; }; -internal struct RoomSearchResult get_room_at_index(struct Room *rooms[NUM_ROOMS], u32 num_rooms, v2i room_i) +internal struct RoomSearchResult get_room_at_index(struct Room *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]; + struct Room *r = &rooms[i]; if (r->index.x == room_i.x && r->index.y == room_i.y) { result.room_found = true; @@ -345,49 +390,11 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga // Screen origin is in the upper left m4 projection = math_projection_ortho(0.0f, framebuffer.width, framebuffer.height, 0.0f, -1.0f, 0.0f); - struct Room knytt_hanging_fly_village = { - .index = {0, 0}, - .tiles = { - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - }, - }; - - struct Room collision_test_zone = { - .index = {0, 1}, - .tiles = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, - 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, - 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, - 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, - - 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, - 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, - 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, - 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }, - }; - - // 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.room; - struct RoomSearchResult r = get_room_at_index(rooms, NUM_ROOMS, current_room_i); + struct RoomSearchResult r = get_room_at_index(game_state->world->rooms, game_state->world->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; + struct Room current_room = game_state->world->rooms[r.room_array_index]; + u32 *tiles = current_room.tiles; // render tiles { diff --git a/src/game.h b/src/game.h @@ -1,5 +1,6 @@ #include <assert.h> #include <math.h> +#include <stdalign.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> @@ -10,6 +11,7 @@ #include "types.h" #include "am_math.h" #include "shader.h" +#include "memory.h" #include "platform.h" // One tile is one square meter @@ -48,11 +50,21 @@ struct Room u32 tiles[ROOM_TILE_COUNT]; }; +// TODO: delete +#define MAX_ROOMS 120 + +struct World +{ + struct Room rooms[MAX_ROOMS]; + u32 num_rooms; +}; + struct GameState { struct RendererState renderer; struct Entity player; - struct Room *rooms; + struct StackAllocator world_allocator; + struct World *world; }; internal void game_init(struct GameMemory *game_memory, v2u framebuffer); diff --git a/src/memory.c b/src/memory.c @@ -0,0 +1,45 @@ +#define mem_st_alloc_struct(allocator, type) mem_st_alloc((allocator), sizeof(type), alignof(type)) + +// TODO: test that alignment is working properly +internal inline uintptr_t mem_align_address(uintptr_t address, size_t alignment) +{ + assert(math_is_pow_2(alignment)); + // This works since we've asserted alignment is a power of 2 + size_t mask = alignment - 1; + uintptr_t result = (address + mask) & ~mask; + return result; +} + +internal void mem_st_init(struct StackAllocator *allocator, void *backing_buffer, size_t backing_buffer_bytes) +{ + allocator->size = backing_buffer_bytes; + allocator->base = backing_buffer; + allocator->used = 0; +} + +internal void* mem_st_alloc(struct StackAllocator *allocator, size_t bytes, size_t alignment) +{ + size_t worst_case_bytes = bytes + alignment - 1; + assert(allocator->used + worst_case_bytes <= allocator->size); + + allocator->used += worst_case_bytes; + uintptr_t current_head = (uintptr_t)allocator->base + allocator->used; + void *address = (void *)mem_align_address(current_head, alignment); + return address; +} + +internal size_t mem_st_get_marker(struct StackAllocator *allocator) +{ + size_t marker = allocator->used; + return marker; +} + +internal void mem_st_free_to_marker(struct StackAllocator *allocator, size_t marker) +{ + allocator->used = marker; +} + +internal void mem_st_free_all(struct StackAllocator *allocator) +{ + allocator->used = 0; +} diff --git a/src/memory.h b/src/memory.h @@ -0,0 +1,6 @@ +struct StackAllocator +{ + u8 *base; + size_t size; + size_t used; +}; diff --git a/src/platform_linux.c b/src/platform_linux.c @@ -280,7 +280,7 @@ internal struct GameCode load_game_code(char *source_lib_path) // In this case, we are protected by POSIX, which specifies that // function and data pointers must be the same size. We will only ever // be using dlsym on POSIX-compliant platforms. - _Static_assert( + static_assert( sizeof(void *) == sizeof(void(*)()), "Object pointer must be the same size as function pointer" );