Multiple Knights with y-depth sorting using insertion sort, texture ids

This commit is contained in:
Joseph Ferano 2024-01-05 17:17:39 +07:00
parent ba44c72d09
commit 070f23a467
2 changed files with 103 additions and 71 deletions

View File

@ -1,5 +1,10 @@
#pragma once #pragma once
#define TEX_GROUND 0
#define TEX_KNIGHT 1
#define TEX_MOUSE_CURSOR 2
#define TEX_TARGET_RETICLE 3
#define ANIM_KNIGHT_IDLE 0 #define ANIM_KNIGHT_IDLE 0
#define ANIM_KNIGHT_RUN 1 #define ANIM_KNIGHT_RUN 1
#define ANIM_KNIGHT_ATTACK_SIDE1 2 #define ANIM_KNIGHT_ATTACK_SIDE1 2

169
main.c
View File

@ -6,7 +6,7 @@
#define TEXTURES_BUF_SIZE 16 #define TEXTURES_BUF_SIZE 16
#define TARGET_FPS 60 #define TARGET_FPS 60
#define MAX_KNIGHTS 256 #define MAX_KNIGHTS 1024
#define DEBUG_MODE_ENABLED #define DEBUG_MODE_ENABLED
@ -46,11 +46,13 @@ typedef struct {
int frame_count; int frame_count;
// Rectangle* sprite_rects; // Rectangle* sprite_rects;
Point camera_position; Point camera_position;
Knight *selected_knight; int selected_knight;
PointOption *target_points; PointOption *target_points;
Knight *knights; Knight *knights;
SpriteAnimationPlayback* anim_playbacks; SpriteAnimationPlayback* anim_playbacks;
int anim_playbacks_count;
int entity_count;
} GameState; } GameState;
typedef struct { typedef struct {
@ -69,16 +71,16 @@ Assets Init() {
Assets assets = {0}; Assets assets = {0};
assets.textures = malloc(sizeof(Texture2D) * TEXTURES_BUF_SIZE); assets.textures = malloc(sizeof(Texture2D) * TEXTURES_BUF_SIZE);
assets.textures[0] = LoadTexture("assets/Terrain/Ground/Tilemap_Flat.png"); assets.textures[TEX_GROUND] = LoadTexture("assets/Terrain/Ground/Tilemap_Flat.png");
assets.textures[1] = assets.textures[TEX_KNIGHT] =
LoadTexture("assets/Factions/Knights/Troops/Warrior/Blue/Warrior_Blue.png"); LoadTexture("assets/Factions/Knights/Troops/Warrior/Blue/Warrior_Blue.png");
assets.textures[2] = LoadTexture("assets/UI/Pointers/01.png"); assets.textures[TEX_MOUSE_CURSOR] = LoadTexture("assets/UI/Pointers/01.png");
assets.textures[3] = LoadTexture("assets/UI/Pointers/02.png"); assets.textures[TEX_TARGET_RETICLE] = LoadTexture("assets/UI/Pointers/02.png");
return assets; return assets;
} }
void Update(GameState *game, Camera2D *cam, float dt) { void Update(GameState *game, Camera2D *cam, float dt) {
if (IsMouseButtonPressed(0)) { if (0 && IsMouseButtonPressed(0)) {
Point mouse_pos = GetScreenToWorld2D(GetMousePosition(), *cam); Point mouse_pos = GetScreenToWorld2D(GetMousePosition(), *cam);
// TODO: This kind of sucks that we're doing all the math here to calculate // 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 // the position of the collider, we need a helper that calculates origin offset
@ -89,16 +91,17 @@ void Update(GameState *game, Camera2D *cam, float dt) {
knight_colrect_select.height, knight_colrect_select.height,
}; };
if (CheckCollisionPointRec(mouse_pos, mouse_select_area)) { if (CheckCollisionPointRec(mouse_pos, mouse_select_area)) {
game->selected_knight = &game->knights[0]; // game->selected_knight = &game->knights[0];
} else { } else {
game->selected_knight = NULL; game->selected_knight = -1;
} }
} }
if (IsMouseButtonPressed(1)) { if (IsMouseButtonPressed(1)) {
Point mouse_pos = GetScreenToWorld2D(GetMousePosition(), *cam); Point mouse_pos = GetScreenToWorld2D(GetMousePosition(), *cam);
if (game->selected_knight != NULL) { if (game->selected_knight != -1) {
game->target_points[0] = (PointOption){ .tag = SOME, .some.point = mouse_pos }; game->target_points[game->selected_knight] =
(PointOption){ .tag = SOME, .some.point = mouse_pos };
} }
} }
@ -119,41 +122,28 @@ void Update(GameState *game, Camera2D *cam, float dt) {
cam_vel = Vector2Normalize(cam_vel); cam_vel = Vector2Normalize(cam_vel);
game->camera_position = Vector2Scale(cam_vel, cam_move_speed); game->camera_position = Vector2Scale(cam_vel, cam_move_speed);
cam->offset = Vector2Add(cam->offset, game->camera_position); cam->offset = Vector2Add(cam->offset, game->camera_position);
if (IsKeyPressed(KEY_SPACE) && game->knights[0].state != KNIGHT_ATTACKING) { if (IsKeyPressed(KEY_SPACE) && game->selected_knight != -1) {
game->knights[0].state = KNIGHT_ATTACKING; int k_idx = game->selected_knight;
PlayAnimation(ANIM_KNIGHT_ATTACK_SIDE1, knight_anims, &game->anim_playbacks[0]); if (game->knights[k_idx].state != KNIGHT_ATTACKING) {
game->knights[k_idx].state = KNIGHT_ATTACKING;
PlayAnimation(ANIM_KNIGHT_ATTACK_SIDE1, knight_anims, &game->anim_playbacks[k_idx]);
}
} }
if (IsKeyPressed(KEY_F1)) { if (IsKeyPressed(KEY_F1)) {
global_debug_mode = !global_debug_mode; global_debug_mode = !global_debug_mode;
} }
// 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 // Process animation data
TickSpriteAnimations(game->anim_playbacks, 1); TickSpriteAnimations(game->anim_playbacks, game->entity_count);
// Handle knight movement if they are moving somewhere // Handle knight movement if they are moving somewhere
// for (int i = 0; i < MAX_KNIGHTS; i++) { for (int i = 0; i < game->entity_count; i++) {
for (int i = 0; i < 1; i++) {
Vector2 input_vel = {0}; Vector2 input_vel = {0};
Knight *knight = &game->knights[i]; Knight *knight = &game->knights[i];
if (game->target_points[0].tag == SOME) { if (game->target_points[i].tag == SOME) {
Vector2 target = game->target_points[0].some.point; Vector2 target = game->target_points[game->selected_knight].some.point;
if (Vector2DistanceSqr(target, knight->position) < 2.5f) { if (Vector2DistanceSqr(target, knight->position) < 2.5f) {
game->target_points[0].tag = NONE; game->target_points[i].tag = NONE;
} else { } else {
input_vel.x = knight->position.x - target.x < 0.0f ? 1 : -1; input_vel.x = knight->position.x - target.x < 0.0f ? 1 : -1;
knight->position = Vector2MoveTowards(knight->position, target, 4.0f); knight->position = Vector2MoveTowards(knight->position, target, 4.0f);
@ -183,9 +173,35 @@ void Update(GameState *game, Camera2D *cam, float dt) {
} }
} }
} }
// Sort the entities using Insertion Sort.
for (int i = 1; i < game->entity_count; i++) {
int j = i;
while (j > 0 && game->knights[j].position.y < game->knights[j - 1].position.y) {
// Swap position
Knight temp_k = game->knights[j - 1];
game->knights[j - 1] = game->knights[j];
game->knights[j] = temp_k;
// Swap animations
SpriteAnimationPlayback temp_a = game->anim_playbacks[j - 1];
game->anim_playbacks[j - 1] = game->anim_playbacks[j];
game->anim_playbacks[j] = temp_a;
// Swap target points
PointOption temp_p = game->target_points[j - 1];
game->target_points[j - 1] = game->target_points[j];
game->target_points[j] = temp_p;
// Swap selected knight
if (game->selected_knight == j) {
game->selected_knight = j - 1;
} else if (game->selected_knight == j - 1) {
game->selected_knight = j;
}
j--;
}
}
} }
void Draw(const GameState *game, Assets assets, Camera2D cam, float dt) { void Draw(GameState *game, Assets assets, Camera2D cam, float dt) {
(void)cam; (void)cam;
(void)dt; (void)dt;
ClearBackground((Color){100, 149, 237, 255}); ClearBackground((Color){100, 149, 237, 255});
@ -209,19 +225,19 @@ void Draw(const GameState *game, Assets assets, Camera2D cam, float dt) {
} }
Vector2 pos = {32 * col + topx, 32 * row + topy}; Vector2 pos = {32 * col + topx, 32 * row + topy};
Rectangle src_rect = {32 * atlas_col, 32 * atlas_row, 32, 32}; Rectangle src_rect = {32 * atlas_col, 32 * atlas_row, 32, 32};
D_DrawTextureRec(assets.textures[0], src_rect, pos, WHITE); D_DrawTextureRec(assets.textures[TEX_GROUND], src_rect, pos, WHITE);
} }
} }
if (game->target_points[0].tag == SOME) { if (game->target_points[game->selected_knight].tag == SOME) {
Vector2 marker_pos = game->target_points[0].some.point; Vector2 marker_pos = game->target_points[game->selected_knight].some.point;
marker_pos.x -= assets.textures[3].width / 2; marker_pos.x -= assets.textures[TEX_TARGET_RETICLE].width / 2;
marker_pos.y -= assets.textures[3].height / 2; marker_pos.y -= assets.textures[TEX_TARGET_RETICLE].height / 2;
D_DrawTextureV(assets.textures[3], marker_pos, WHITE); D_DrawTextureV(assets.textures[TEX_TARGET_RETICLE], 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++) { for (int i = 0; i < game->entity_count; i++) {
Knight *knight = &game->knights[i]; Knight *knight = &game->knights[i];
SpriteAnimationPlayback *playback = &game->anim_playbacks[i]; SpriteAnimationPlayback *playback = &game->anim_playbacks[i];
Rectangle src_rect = { Rectangle src_rect = {
@ -234,27 +250,28 @@ void Draw(const GameState *game, Assets assets, Camera2D cam, float dt) {
if (knight->look_dir == DIR_LEFT) { if (knight->look_dir == DIR_LEFT) {
src_rect.width = -abs((int)src_rect.width); src_rect.width = -abs((int)src_rect.width);
} }
// Vector2 pos = Vector2Subtract(game->knight.position, knight_origin);
Rectangle dest_rect = {knight->position.x, 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); Texture2D tex = assets.textures[TEX_KNIGHT];
D_DrawTexturePro(tex, src_rect, dest_rect, knight_origin, 0.0f, WHITE);
}
if (game->selected_knight) { if (game->selected_knight != -1) {
Vector2 kpos = game->knights[0].position; Vector2 kpos = game->knights[game->selected_knight].position;
Rectangle knight_col_area = { Rectangle knight_col_area = {
kpos.x + knight_colrect_select.x, kpos.x + knight_colrect_select.x,
kpos.y + knight_colrect_select.y, kpos.y + knight_colrect_select.y,
knight_colrect_select.width, knight_colrect_select.width,
knight_colrect_select.height, knight_colrect_select.height,
}; };
// Color color = game->selected_knight == NULL ? RED : GREEN; // Color color = game->selected_knight == NULL ? RED : GREEN;
DrawRectangleLinesEx(knight_col_area, 2.0f, GREEN); DrawRectangleLinesEx(knight_col_area, 2.0f, GREEN);
}
} }
Vector2 world = GetScreenToWorld2D(GetMousePosition(), cam); Vector2 world = GetScreenToWorld2D(GetMousePosition(), cam);
Vector2 pointer_pos = Vector2Subtract(world, (Vector2){24, 19}); Vector2 pointer_pos = Vector2Subtract(world, (Vector2){24, 19});
D_DrawTextureV(assets.textures[2], pointer_pos, WHITE); D_DrawTextureV(assets.textures[TEX_MOUSE_CURSOR], pointer_pos, WHITE);
DrawRectangle(1492, 4, 88, 30, WHITE);
DrawFPS(1500, 10); DrawFPS(1500, 10);
} }
@ -262,7 +279,10 @@ int main(void) {
const int screen_width = 1600; const int screen_width = 1600;
const int screen_height = 1080; const int screen_height = 1080;
printf("Knight Size: %ld \n", sizeof(Knight));
printf("SpriteAnimationPlayback Size: %ld \n", sizeof(SpriteAnimationPlayback)); printf("SpriteAnimationPlayback Size: %ld \n", sizeof(SpriteAnimationPlayback));
printf("Knight Size: %ld \n", sizeof(Point));
printf("Knight Size: %ld \n", sizeof(PointOption));
InitWindow(screen_width, screen_height, "raylib [core] example - basic window"); InitWindow(screen_width, screen_height, "raylib [core] example - basic window");
@ -280,20 +300,26 @@ int main(void) {
Camera2D cam = {0}; Camera2D cam = {0};
cam.zoom = 1.0f; cam.zoom = 1.0f;
GameState game = {0};
game.knights = malloc(sizeof(Knight) * MAX_KNIGHTS);
game.knights[0] = (Knight){0};
game.knights[0].position = (Vector2){400,150};
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));
Assets assets = Init(); Assets assets = Init();
PlayAnimation(ANIM_KNIGHT_IDLE, knight_anims, &game.anim_playbacks[0]); GameState game = {0};
// const int idle game.knights = calloc(MAX_KNIGHTS, sizeof(Knight));
game.anim_playbacks = calloc(MAX_KNIGHTS, sizeof(SpriteAnimationPlayback));
game.target_points = calloc(MAX_KNIGHTS, sizeof(PointOption));
const int entities = 1024;
for (int i = 0; i < entities; i++) {
int rand_x = GetRandomValue(360, 1250);
int rand_y = 100 + ((float)930 / (float)entities) * i;
game.knights[i].position = (Vector2){rand_x,rand_y};
PlayAnimation(ANIM_KNIGHT_IDLE, knight_anims, &game.anim_playbacks[i]);
int rand_frame = GetRandomValue(0, knight_anims[ANIM_KNIGHT_IDLE].total_frames);
game.anim_playbacks[i].current_frame = rand_frame;
}
game.entity_count = entities;
game.selected_knight = 0;
while (!WindowShouldClose()) { while (!WindowShouldClose()) {
game.frame_count++; game.frame_count++;
float dt = GetFrameTime(); float dt = GetFrameTime();
@ -311,10 +337,11 @@ int main(void) {
EndDrawing(); EndDrawing();
} }
free(game.knights);
free(game.anim_playbacks); free(game.anim_playbacks);
free(game.target_points); free(game.target_points);
for (int i = 0; i < TEXTURES_BUF_SIZE; i++) { for (int i = 0; i < TEXTURES_BUF_SIZE; i++) {
UnloadTexture(assets.textures[0]); UnloadTexture(assets.textures[i]);
} }
free(assets.textures); free(assets.textures);
CloseWindow(); CloseWindow();