diff --git a/.gitignore b/.gitignore index e239c13..4c2ce86 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.aseprite /.idea/ /sprites.o +/dod diff --git a/Makefile b/Makefile index 2410568..6d2561f 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ -CFLAGS=-g -Wall -Wextra -pedantic -O0 +CFLAGS=-g -fsanitize=address -Wall -Wextra -pedantic -O0 CC=gcc .PHONY: build clean run all -all: main +all: main dod main: main.c sprites.o sprites.h game_data.h ./lib/libraylib.a $(CC) $(CFLAGS) -Iinclude/ -lm main.c -o main sprites.o ./lib/libraylib.a @@ -11,6 +11,9 @@ main: main.c sprites.o sprites.h game_data.h ./lib/libraylib.a sprites.o: sprites.c sprites.h lib.h $(CC) $(CFLAGS) -c sprites.c -o sprites.o +dod: dod.c ./lib/libraylib.a + $(CC) $(CFLAGS) -Iinclude/ -lm dod.c -o dod ./lib/libraylib.a + run: all ./main diff --git a/dod.c b/dod.c new file mode 100644 index 0000000..9d2fcb8 --- /dev/null +++ b/dod.c @@ -0,0 +1,75 @@ +#include +#include + +#include "raylib.h" + +#define ENTITY_COUNT 10000000 +#define TEST_DOD + +typedef struct DoDState +{ + Vector2* positions; + Color* colors; + Vector2* outputs; +} DoDState; + +typedef struct ObjState +{ + Vector2 position; + Color color; + Vector2 output; +} ObjState; + +ObjState objects[ENTITY_COUNT]; + +Vector2 positions[ENTITY_COUNT]; +Color colors[ENTITY_COUNT]; +Vector2 outputs[ENTITY_COUNT]; + + +void AWESOME_FUNCTION(void) +{ +#ifdef TEST_DOD + for (int i = 0; i < ENTITY_COUNT; i++) + { + const Vector2 output = (Vector2){ + // positions[i] = (Vector2){ + positions[i].x * 2, + positions[i].y * 2, + }; + outputs[i] = output; + } +#else + for (int i = 0; i < ENTITY_COUNT; i++) + { + const Vector2 output = (Vector2){ + objects[i].position.x * objects[i].color.r, + objects[i].position.y * objects[i].color.b, + }; + objects[i].output = output; + } +#endif +} + +int main(void) +{ + // Populate the data + int r = rand(); + for (int i = 0; i < ENTITY_COUNT; i++) + { + positions[i].x = (float)r / RAND_MAX; + positions[i].y = (float)r / RAND_MAX; + + colors[i].r = r % 256; + colors[i].g = r % 256; + colors[i].b = r % 256; + colors[i].a = r % 256; + + objects[i].position = positions[i]; + objects[i].color = colors[i]; + } + + AWESOME_FUNCTION(); + + return 0; +} diff --git a/game_data.h b/game_data.h index 506e931..8910f00 100644 --- a/game_data.h +++ b/game_data.h @@ -9,78 +9,62 @@ #define ANIM_KNIGHT_ATTACK_BACK1 6 #define ANIM_KNIGHT_ATTACK_BACK2 7 -const u16 cell_size = 192; -SpriteSheet knight = { - .name = "blue_knight", - .texture = {0}, - // .anim_count = 8, - .size = { 1152, 1536 }, -}; +// SpriteSheet knight_spritesheet = { +// .name = "blue_knight", +// .texture = {0}, +// // .anim_count = 8, +// .size = { 1152, 1536 }, +// }; -const Vector2 knight_origin = {cell_size / 2, cell_size / 2}; -const Size knight_col_size = {75, 100}; +const u16 knight_sprite_size = 192; +const Vector2 knight_origin = {knight_sprite_size / 2, knight_sprite_size / 2 + 35}; +const Size knight_col_size = {85, 95}; // TODO: We probably want this as a helper function somewhere const Rectangle knight_colrect_select = { - knight_origin.x - knight_col_size.width / 2, - knight_origin.y - knight_col_size.height / 2, + -knight_col_size.width / 2, + -knight_col_size.height / 2 - 40, knight_col_size.width, knight_col_size.height, }; SpriteAnimation knight_idle = { - .name = "idle", .total_frames = 6, .loop = true, - .src_rect = { 0, cell_size * 0, cell_size, cell_size }, }; SpriteAnimation knight_run = { - .name = "run", .total_frames = 6, .loop = true, - .src_rect = { 0, cell_size * 1, cell_size, cell_size }, }; SpriteAnimation knight_attack_side1 = { - .name = "attack_side1", .total_frames = 6, .loop = false, - .src_rect = { 0, cell_size * 2, cell_size, cell_size }, }; SpriteAnimation knight_attack_side2 = { - .name = "attack_side2", .total_frames = 6, .loop = false, - .src_rect = { 0, cell_size * 3, cell_size, cell_size }, }; SpriteAnimation knight_attack_front1 = { - .name = "attack_front1", .total_frames = 6, .loop = false, - .src_rect = { 0, cell_size * 4, cell_size, cell_size }, }; SpriteAnimation knight_attack_front2 = { - .name = "attack_front2", .total_frames = 6, .loop = false, - .src_rect = { 0, cell_size * 5, cell_size, cell_size }, }; SpriteAnimation knight_attack_back1 = { - .name = "attack_back1", .total_frames = 6, .loop = false, - .src_rect = { 0, cell_size * 6, cell_size, cell_size }, }; SpriteAnimation knight_attack_back2 = { - .name = "attack_back2", .total_frames = 6, .loop = false, - .src_rect = { 0, cell_size * 7, cell_size, cell_size }, }; SpriteAnimation knight_anims[8]; diff --git a/lib.h b/lib.h index e147776..06f44e5 100644 --- a/lib.h +++ b/lib.h @@ -4,17 +4,15 @@ #include "include/raylib.h" typedef uint8_t u8; -// typedef char16_t c16; typedef uint16_t u16; -typedef int16_t i16; -typedef int32_t b32; +typedef int16_t i16; typedef int32_t i32; typedef uint32_t u32; typedef uint64_t u64; typedef float f32; typedef double f64; typedef uintptr_t uptr; -typedef char byte; +typedef char sbyte; typedef ptrdiff_t size; typedef size_t usize; @@ -35,18 +33,21 @@ typedef union { Rectangle rect; } RectU; -typedef struct PointOrNone { - enum {NONE, POINT} type; - union { - byte none; - Point point; - } value; -} PointOrNone; +#define OPTION(type, typeName) \ + struct { \ + enum {NONE, SOME} tag; \ + union { \ + u8 none; \ + type typeName; \ + } some; \ + } +typedef OPTION(Point, point) PointOption; void D_DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); void D_DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); void D_DrawTextureV(Texture2D texture, Vector2 position, Color tint); + #ifdef ENNIX_LIB_IMPLEMENTATION extern bool global_debug_mode; inline void D_DrawTextureV(Texture2D texture, Vector2 position, Color tint) { diff --git a/main.c b/main.c index d17ce64..73660de 100644 --- a/main.c +++ b/main.c @@ -6,9 +6,7 @@ #define TEXTURES_BUF_SIZE 16 #define TARGET_FPS 60 -#define ANIM_SPEED 8 -#define MAX_ANIMATION_PLAYBACKS 64 -#define MAX_KNIGHTS 64 +#define MAX_KNIGHTS 256 #define DEBUG_MODE_ENABLED @@ -46,11 +44,11 @@ typedef struct { typedef struct { int frame_count; - Knight knight; // Rectangle* sprite_rects; Point camera_position; Knight *selected_knight; - PointOrNone *target_points; + PointOption *target_points; + Knight *knights; SpriteAnimationPlayback* anim_playbacks; int anim_playbacks_count; } GameState; @@ -80,20 +78,18 @@ Assets Init() { } void Update(GameState *game, Camera2D *cam, float dt) { - TickSpriteAnimations(&knight_anims[0], game->anim_playbacks, 1); - if (IsMouseButtonPressed(0)) { Point mouse_pos = GetScreenToWorld2D(GetMousePosition(), *cam); // TODO: This kind of sucks that we're doing all the math here to calculate // the position of the collider, we need a helper that calculates origin offset Rectangle mouse_select_area = { - game->knight.position.x - knight_colrect_select.width / 2, - game->knight.position.y - knight_colrect_select.height / 2, + game->knights[0].position.x + knight_colrect_select.x, + game->knights[0].position.y + knight_colrect_select.y, knight_colrect_select.width, knight_colrect_select.height, }; if (CheckCollisionPointRec(mouse_pos, mouse_select_area)) { - game->selected_knight = &game->knight; + game->selected_knight = &game->knights[0]; } else { game->selected_knight = NULL; } @@ -102,35 +98,10 @@ void Update(GameState *game, Camera2D *cam, float dt) { if (IsMouseButtonPressed(1)) { Point mouse_pos = GetScreenToWorld2D(GetMousePosition(), *cam); if (game->selected_knight != NULL) { - game->target_points[0] = (PointOrNone){.type = POINT, .value.point = mouse_pos }; + game->target_points[0] = (PointOption){ .tag = SOME, .some.point = mouse_pos }; } } - // for (int i = 0; i < MAX_KNIGHTS; i++) { - Vector2 input_vel = {0}; - if (game->target_points[0].type == POINT) { - Vector2 target = game->target_points[0].value.point; - if (Vector2DistanceSqr(target, game->knight.position) < 0.5f) { - game->target_points[0].type = NONE; - } else { - input_vel.x = game->knight.position.x - target.x < 0.0f ? 1 : -1; - game->knight.position = Vector2MoveTowards(game->knight.position, target, 4.0f); - } - } - - // const float movement_speed = 250.0f * dt; - // if (IsKeyDown(KEY_RIGHT)) { - // input_vel.x = 1; - // } - // if (IsKeyDown(KEY_LEFT)) { - // input_vel.x = -1; - // } - // if (IsKeyDown(KEY_UP)) { - // input_vel.y = -1; - // } - // if (IsKeyDown(KEY_DOWN)) { - // input_vel.y = 1; - // } const float cam_move_speed = 1050.0f * dt; Vector2 cam_vel = {0}; if (IsKeyDown(KEY_D)) { @@ -148,32 +119,68 @@ void Update(GameState *game, Camera2D *cam, float dt) { cam_vel = Vector2Normalize(cam_vel); game->camera_position = Vector2Scale(cam_vel, cam_move_speed); cam->offset = Vector2Add(cam->offset, game->camera_position); - if (IsKeyPressed(KEY_SPACE) && game->knight.state != KNIGHT_ATTACKING) { - game->knight.state = KNIGHT_ATTACKING; - game->anim_playbacks[0].anim_id = ANIM_KNIGHT_ATTACK_SIDE1; - PlayAnimation(&game->anim_playbacks[0], game->anim_playbacks[0]); + if (IsKeyPressed(KEY_SPACE) && game->knights[0].state != KNIGHT_ATTACKING) { + game->knights[0].state = KNIGHT_ATTACKING; + PlayAnimation(ANIM_KNIGHT_ATTACK_SIDE1, knight_anims, &game->anim_playbacks[0]); } if (IsKeyPressed(KEY_F1)) { global_debug_mode = !global_debug_mode; } - if (game->knight.state == KNIGHT_ATTACKING) { - game->anim_playbacks[0].anim_id = ANIM_KNIGHT_ATTACK_SIDE1; - if (game->anim_playbacks[0].is_finished) { - game->knight.state = KNIGHT_IDLE; + // const float movement_speed = 250.0f * dt; + // if (IsKeyDown(KEY_RIGHT)) { + // input_vel.x = 1; + // } + // if (IsKeyDown(KEY_LEFT)) { + // input_vel.x = -1; + // } + // if (IsKeyDown(KEY_UP)) { + // input_vel.y = -1; + // } + // if (IsKeyDown(KEY_DOWN)) { + // input_vel.y = 1; + // } + + + + // Process animation data + TickSpriteAnimations(game->anim_playbacks, 1); + + // Handle knight movement if they are moving somewhere + // for (int i = 0; i < MAX_KNIGHTS; i++) { + for (int i = 0; i < 1; i++) { + Vector2 input_vel = {0}; + Knight *knight = &game->knights[i]; + if (game->target_points[0].tag == SOME) { + Vector2 target = game->target_points[0].some.point; + if (Vector2DistanceSqr(target, knight->position) < 2.5f) { + game->target_points[0].tag = NONE; + } else { + input_vel.x = knight->position.x - target.x < 0.0f ? 1 : -1; + knight->position = Vector2MoveTowards(knight->position, target, 4.0f); + } } - } else { - if (input_vel.x != 0) { - game->knight.look_dir = input_vel.x == -1 ? DIR_LEFT : DIR_RIGHT; - } - // game->knight.velocity = Vector2Normalize(input_vel); - // game->knight.velocity = Vector2Scale(game->knight.velocity, movement_speed); - // game->knight.position = Vector2Add(game->knight.position, game->knight.velocity); - if (input_vel.x != 0 || input_vel.y != 0) { - game->anim_playbacks[0].anim_id = ANIM_KNIGHT_RUN; - game->knight.state = KNIGHT_RUNNING; + + // Handle the attacking state, if not handle state transitions + if (knight->state == KNIGHT_ATTACKING) { + if (game->anim_playbacks[i].is_finished) { + knight->state = KNIGHT_IDLE; + PlayAnimation(ANIM_KNIGHT_IDLE, knight_anims, &game->anim_playbacks[i]); + } } else { - game->anim_playbacks[0].anim_id = ANIM_KNIGHT_IDLE; - game->knight.state = KNIGHT_IDLE; + if (input_vel.x != 0) { + knight->look_dir = input_vel.x == -1 ? DIR_LEFT : DIR_RIGHT; + } + if (input_vel.x != 0 || input_vel.y != 0) { + if (knight->state == KNIGHT_IDLE) { + PlayAnimation(ANIM_KNIGHT_RUN, knight_anims, &game->anim_playbacks[i]); + knight->state = KNIGHT_RUNNING; + } + } else { + if (knight->state == KNIGHT_RUNNING) { + PlayAnimation(ANIM_KNIGHT_IDLE, knight_anims, &game->anim_playbacks[i]); + knight->state = KNIGHT_IDLE; + } + } } } } @@ -206,31 +213,36 @@ void Draw(const GameState *game, Assets assets, Camera2D cam, float dt) { } } - if (game->target_points[0].type == POINT) { - Vector2 marker_pos = game->target_points[0].value.point; + if (game->target_points[0].tag == SOME) { + Vector2 marker_pos = game->target_points[0].some.point; marker_pos.x -= assets.textures[3].width / 2; - // marker_pos.y -= assets.textures[3].height / 2; + marker_pos.y -= assets.textures[3].height / 2; D_DrawTextureV(assets.textures[3], marker_pos, WHITE); } - for (int i = 0; i < game->anim_playbacks_count; i++) { + // for (int i = 0; i < game->anim_playbacks_count; i++) { + for (int i = 0; i < 1; i++) { + Knight *knight = &game->knights[i]; SpriteAnimationPlayback *playback = &game->anim_playbacks[i]; - SpriteAnimation *anim = &knight_anims[playback->anim_id]; - Rectangle src_rect = anim->src_rect; - src_rect.x = playback->current_frame * anim->src_rect.width; - src_rect.y = anim->src_rect.y; - if (game->knight.look_dir == DIR_LEFT) { + Rectangle src_rect = { + playback->current_frame * knight_sprite_size, + playback->row * knight_sprite_size, + knight_sprite_size, + knight_sprite_size, + }; + // TODO: This might be a nice place to optimize + if (knight->look_dir == DIR_LEFT) { src_rect.width = -abs((int)src_rect.width); } // Vector2 pos = Vector2Subtract(game->knight.position, knight_origin); - Rectangle dest_rect = {game->knight.position.x, game->knight.position.y, 192, 192}; + Rectangle dest_rect = {knight->position.x, knight->position.y, 192, 192}; D_DrawTexturePro(assets.textures[1], src_rect, dest_rect, knight_origin, 0.0f, WHITE); if (game->selected_knight) { - Vector2 kpos = game->knight.position; + Vector2 kpos = game->knights[0].position; Rectangle knight_col_area = { - kpos.x - knight_colrect_select.width / 2, - kpos.y - knight_colrect_select.height / 2, + kpos.x + knight_colrect_select.x, + kpos.y + knight_colrect_select.y, knight_colrect_select.width, knight_colrect_select.height, }; @@ -248,6 +260,8 @@ int main(void) { const int screen_width = 1600; const int screen_height = 1080; + printf("SpriteAnimationPlayback Size: %ld \n", sizeof(SpriteAnimationPlayback)); + InitWindow(screen_width, screen_height, "raylib [core] example - basic window"); int monitor = GetCurrentMonitor(); @@ -265,17 +279,18 @@ int main(void) { cam.zoom = 1.0f; GameState game = {0}; - game.anim_playbacks = malloc(sizeof(SpriteAnimationPlayback) * MAX_ANIMATION_PLAYBACKS); + game.knights = malloc(sizeof(Knight) * MAX_KNIGHTS); + game.knights[0] = (Knight){0}; + game.knights[0].position = (Vector2){100,100}; + game.anim_playbacks = malloc(sizeof(SpriteAnimationPlayback) * MAX_KNIGHTS); game.anim_playbacks_count = 1; // First one is idle game.anim_playbacks[0] = (SpriteAnimationPlayback){0}; game.target_points = calloc(MAX_KNIGHTS, sizeof(Point)); - game.knight = (Knight){0}; - game.knight.position = (Vector2){100,100}; Assets assets = Init(); - PlayAnimation(&game.anim_playbacks[0], game.anim_playbacks[0]); + PlayAnimation(ANIM_KNIGHT_IDLE, knight_anims, &game.anim_playbacks[0]); // const int idle while (!WindowShouldClose()) { game.frame_count++; diff --git a/sprites.c b/sprites.c index 951a3ac..67d6d6b 100644 --- a/sprites.c +++ b/sprites.c @@ -1,26 +1,25 @@ #include "sprites.h" #include "include/raylib.h" -void PlayAnimation(SpriteAnimationPlayback *playbacks, SpriteAnimationPlayback playback) { - playback.time_elapsed = 0.0f; - playback.current_frame = 0; - playback.is_finished = false; - playbacks[0] = playback; +inline void PlayAnimation(int animation, SpriteAnimation *anims, SpriteAnimationPlayback *playback) { + playback->time_elapsed = 0.0f; + playback->current_frame = 0; + playback->row = animation; + playback->is_finished = false; + playback->total_frames = anims[animation].total_frames; + playback->loop = anims[animation].loop; } -void TickSpriteAnimations(const SpriteAnimation *animations, - SpriteAnimationPlayback *playbacks, - int len) { +void TickSpriteAnimations(SpriteAnimationPlayback *playbacks, int len) { const f32 anim_speed = 1.0f / 10.0f; for (int i = 0; i < len; i++) { SpriteAnimationPlayback *playback = &playbacks[i]; - const SpriteAnimation *animation = &animations[playback->anim_id]; playback->time_elapsed += GetFrameTime(); if (playback->time_elapsed >= anim_speed) { playback->time_elapsed = 0.0f; playback->current_frame++; - if (playback->current_frame >= animation->total_frames) { - if (animation->loop) { + if (playback->current_frame >= playback->total_frames) { + if (playback->loop) { playback->current_frame = 0; } else { playback->is_finished = true; diff --git a/sprites.h b/sprites.h index cdd83f8..237296e 100644 --- a/sprites.h +++ b/sprites.h @@ -4,25 +4,26 @@ #include "lib.h" #include "include/raylib.h" -typedef struct { - Texture2D texture; - char *name; - Size size; -} SpriteSheet; +// typedef struct { +// Texture2D texture; +// char *name; +// Size size; +// } SpriteSheet; typedef struct { - char* name; + u8 loop; u8 total_frames; - bool loop; - Rectangle src_rect; } SpriteAnimation; typedef struct { - u16 anim_id; - u8 current_frame; - bool is_finished; f32 time_elapsed; + u8 row; + u8 total_frames; + u8 current_frame; + u8 loop; + // TODO: Maybe we can get rid of this one + u8 is_finished; } SpriteAnimationPlayback; -void PlayAnimation(SpriteAnimationPlayback *playbacks, SpriteAnimationPlayback playback); -void TickSpriteAnimations(const SpriteAnimation *animations, SpriteAnimationPlayback *playbacks, int len); +void PlayAnimation(int animation, SpriteAnimation *anims, SpriteAnimationPlayback *playback); +void TickSpriteAnimations(SpriteAnimationPlayback *playbacks, int len);