diff --git a/assets/enemy.aseprite b/assets/enemy.aseprite new file mode 100644 index 0000000..c975f4f Binary files /dev/null and b/assets/enemy.aseprite differ diff --git a/assets/enemy.png b/assets/enemy.png new file mode 100644 index 0000000..dc0673b Binary files /dev/null and b/assets/enemy.png differ diff --git a/compile_commands.json b/compile_commands.json index ad11660..6ce5881 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -29,13 +29,28 @@ "arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-Isrc/utils", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include/stb", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/utils/texture_manager.c.o", "src/utils/texture_manager.c"], "file": "src/utils/texture_manager.c" }, +{ + "directory": "/home/jens/Development/cex/colossus_march", + "arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-Isrc/utils", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include/stb", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/utils/pool.c.o", "src/utils/pool.c"], + "file": "src/utils/pool.c" +}, { "directory": "/home/jens/Development/cex/colossus_march", "arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-Isrc/utils", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include/stb", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/main.c.o", "src/main.c"], "file": "src/main.c" }, +{ + "directory": "/home/jens/Development/cex/colossus_march", + "arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-Isrc/utils", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include/stb", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/stb_impl.c.o", "src/stb_impl.c"], + "file": "src/stb_impl.c" +}, { "directory": "/home/jens/Development/cex/colossus_march", "arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-Isrc/utils", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include/stb", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/sprite.c.o", "src/sprite.c"], "file": "src/sprite.c" +}, +{ + "directory": "/home/jens/Development/cex/colossus_march", + "arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-Isrc/utils", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include", "-I", "/home/jens/.xmake/packages/s/stb/2025.03.14/67005fc11486400896028eb775a57270/include/stb", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/entity.c.o", "src/entity.c"], + "file": "src/entity.c" }] diff --git a/src/entity.c b/src/entity.c new file mode 100644 index 0000000..9cfad87 --- /dev/null +++ b/src/entity.c @@ -0,0 +1,85 @@ +#include "entity.h" + +#include +#include + +#include "raymath.h" +#include "sprite.h" +#include "texture_manager.h" + +static void update_enemy(Entity* self, Player* player) +{ + float dt = GetFrameTime(); + + Vector2 dir = Vector2Subtract(player->pos, self->pos); + self->pos = Vector2Add( + Vector2Scale(Vector2Normalize(dir), ENEMY_SPEED * dt), self->pos); +} + +void entity_update(Entity* self, Player* player) +{ + switch (self->type) { + case ENEMY: + update_enemy(self, player); + break; + default: + abort(); + } +} + +Entity entity_enemy_new(Vector2 pos, Arena* arena, TextureManager* tm) +{ + Entity entity = {0}; + entity.name = "Enemy"; + + Sprite* sprite = + sprite_new("assets/enemy.png", NULL, NULL, &RED, arena, tm); + entity.sprite = sprite; + entity.pos = pos; + entity.type = ENEMY; + + return entity; +} + +EntityManager entity_manager_init() +{ + EntityManager em = {0}; + + arrsetcap(em.entities, ENTITY_INITAL_CAP); + + return em; +} + +void entity_draw(Entity* self) +{ + sprite_draw(self->sprite, self->pos); +} + +void entity_manager_add(EntityManager* self, Entity entity) +{ + arrpush(self->entities, entity); +} + +void entity_manager_remove(EntityManager* self, size index) +{ + arrdel(self->entities, index); +} + +void entity_manager_update(EntityManager* self, Player* player) +{ + for (size i = 0; i < arrlen(self->entities); i++) { + entity_update(&self->entities[i], player); + } +} + +void entity_manager_draw(EntityManager* self) +{ + for (size i = 0; i < arrlen(self->entities); i++) { + entity_draw(&self->entities[i]); + } +} + +void entity_manager_destroy(EntityManager* self) +{ + arrfree(self->entities); +} diff --git a/src/entity.h b/src/entity.h new file mode 100644 index 0000000..1dad25c --- /dev/null +++ b/src/entity.h @@ -0,0 +1,38 @@ +#pragma once + +#include "game.h" +#include "raylib.h" +#include "sprite.h" +#include "texture_manager.h" + +#define ENTITY_INITAL_CAP 128 + +#define ENEMY_SPEED 20 + +typedef enum EntityType { + ENEMY +} EntityType; + +typedef struct Entity { + EntityType type; + const char* name; // use something else? + + Sprite* sprite; + Vector2 pos; +} Entity; + +typedef struct EntityManager { + Entity* entities; +} EntityManager; + +void entity_update(Entity* self, Player* player); +void entity_draw(Entity* self); + +Entity entity_enemy_new(Vector2 pos, Arena* arena, TextureManager* tm); + +EntityManager entity_manager_init(); +void entity_manager_add(EntityManager* self, Entity entity); +void entity_manager_remove(EntityManager* self, size index); +void entity_manager_update(EntityManager* self, Player* player); +void entity_manager_draw(EntityManager* self); +void entity_manager_destroy(EntityManager* self); diff --git a/src/screens/game.c b/src/screens/game.c index 23903fe..ba5d7ea 100644 --- a/src/screens/game.c +++ b/src/screens/game.c @@ -3,6 +3,7 @@ #include #include +#include "entity.h" #include "game_defs.h" #include "pool.h" #include "raylib.h" @@ -22,6 +23,7 @@ static Player player; static Camera2D cam; static Texture2D noise_terrain_texture; static TextureManager tm; +static EntityManager em; static bool paused = false; static bool game_over = false; @@ -84,14 +86,25 @@ void game_screen_init() bullet_pool = pool_init(sizeof(Bullet), 10, &screen_arena); - tm = tm_init(); - bullet_texture = tm_load_texture(&tm, "assets/bullet.png"); + tm = texture_manager_init(); + em = entity_manager_init(); + + bullet_texture = texture_manager_load_texture(&tm, "assets/bullet.png"); + + for (size i = 0; i < 40; i++) { + Entity enemy = entity_enemy_new( + (Vector2){GetRandomValue(0, 600), GetRandomValue(0, 800)}, + &screen_arena, + &tm); + entity_manager_add(&em, enemy); + } paused = 0; game_over = 0; Image noise_image = GenImagePerlinNoise(2000, 2000, 0, 0, 2); - noise_terrain_texture = tm_load_texture_from_image(&tm, noise_image); + noise_terrain_texture = + texture_manager_load_texture_from_image(&tm, "noise", noise_image); Sprite* player_sprite = sprite_new("assets/ball.png", NULL, @@ -132,6 +145,8 @@ void game_screen_update() process_input(dt); + entity_manager_update(&em, &player); + // Update Animation // TODO: make it scalable animation_update(player.sprite->animation, dt); @@ -144,6 +159,9 @@ void game_screen_draw() // Draw Terrain DrawTexture(noise_terrain_texture, -400, -400, WHITE); + // Draw Entities + entity_manager_draw(&em); + // Draw player sprite_draw(player.sprite, player.pos); @@ -161,6 +179,6 @@ void game_screen_draw() void game_screen_cleanup() { - tm_free(&tm); + texture_manager_free(&tm); arena_reset(&screen_arena); }; diff --git a/src/sprite.c b/src/sprite.c index 940ecf2..7711c01 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -42,7 +42,7 @@ Sprite* sprite_new(const char* path, { assert(path && "path must not be empty"); - Texture2D tex = tm_load_texture(tm, path); + Texture2D tex = texture_manager_load_texture(tm, path); return sprite_from_texture(tex, anchor, source, color, arena); } diff --git a/src/utils/texture_manager.c b/src/utils/texture_manager.c index 1358df5..32f92f9 100644 --- a/src/utils/texture_manager.c +++ b/src/utils/texture_manager.c @@ -6,38 +6,59 @@ #include "defs.h" #include "raylib.h" -TextureManager tm_init() +TextureManager texture_manager_init() { TextureManager tm = {0}; tm.textures = NULL; + tm.tex_hash = NULL; // setting default cap of textures arrsetcap(tm.textures, 64); + shdefault(tm.tex_hash, -1); return tm; } -Texture2D tm_load_texture(TextureManager* tm, const char* path) +Texture2D texture_manager_load_texture(TextureManager* tm, const char* path) { - Texture2D tex = LoadTexture(path); - arrpush(tm->textures, tex); + size texture_idx = shget(tm->tex_hash, path); - return tex; + if (texture_idx == -1) { + Texture2D tex = LoadTexture(path); + arrpush(tm->textures, tex); + + // save index to texture + texture_idx = arrlen(tm->textures) - 1; + shput(tm->tex_hash, path, texture_idx); + } + + return tm->textures[texture_idx]; } -Texture2D tm_load_texture_from_image(TextureManager* tm, Image image) +Texture2D texture_manager_load_texture_from_image(TextureManager* tm, + const char* name, + Image image) { - Texture2D tex = LoadTextureFromImage(image); - arrpush(tm->textures, tex); + size texture_idx = shget(tm->tex_hash, name); - return tex; + if (texture_idx == -1) { + Texture2D tex = LoadTextureFromImage(image); + arrpush(tm->textures, tex); + + // save index to texture + texture_idx = arrlen(tm->textures) - 1; + shput(tm->tex_hash, name, texture_idx); + } + + return tm->textures[texture_idx]; } -void tm_free(TextureManager* tm) +void texture_manager_free(TextureManager* tm) { for (size i = 0; i < arrlen(tm->textures); i++) { UnloadTexture(tm->textures[i]); } arrfree(tm->textures); + shfree(tm->tex_hash); } diff --git a/src/utils/texture_manager.h b/src/utils/texture_manager.h index e6db766..5b0b004 100644 --- a/src/utils/texture_manager.h +++ b/src/utils/texture_manager.h @@ -1,13 +1,22 @@ #pragma once +#include "defs.h" #include "raylib.h" +typedef struct TMEntry { + const char* key; + i32 value; +} TMEntry; + typedef struct TextureManager { Texture2D* textures; + TMEntry* tex_hash; } TextureManager; -TextureManager tm_init(); -Texture2D tm_load_texture(TextureManager* tm, const char* path); -Texture2D tm_load_texture_from_image(TextureManager* tm, Image image); -void tm_free(TextureManager* tm); +TextureManager texture_manager_init(); +Texture2D texture_manager_load_texture(TextureManager* tm, const char* path); +Texture2D texture_manager_load_texture_from_image(TextureManager* tm, + const char* name, + Image image); +void texture_manager_free(TextureManager* tm);