summaryrefslogtreecommitdiff
path: root/src/game.c
diff options
context:
space:
mode:
authortalha <->2024-08-15 10:46:43 +0500
committertalha <->2024-08-15 10:46:43 +0500
commit0453b8f50dc4d40083e02cc3d09b4bcaa33f1700 (patch)
treedc9956d8b3be69d76cd03dd4d9b1e0d16dae0a14 /src/game.c
parent0cb9fa1c023033c250fd0bf33c2cee49fc85f178 (diff)
Added functionality, updated c to cpp:HEADmain
- Added entity arrays - Added memory arenas - moved c files to cpp - refactored files to work with lsp (still unity build) but more painful
Diffstat (limited to 'src/game.c')
-rw-r--r--src/game.c1566
1 files changed, 0 insertions, 1566 deletions
diff --git a/src/game.c b/src/game.c
deleted file mode 100644
index 2e85043..0000000
--- a/src/game.c
+++ /dev/null
@@ -1,1566 +0,0 @@
-#include "raylib.h"
-#include "raymath.h"
-
-#if defined(PLATFORM_WEB)
- #include <emscripten/emscripten.h>
-#endif
-
-typedef enum {
- O = 0, // nothing
- //P = 1, // player
- t = 2, // tree
- T = 3, // troll area
- B = 4, // bandit area
- T_B = 5, // troll base
- B_B = 6, // bandit base
- //G = 7, // gate (exit)
-} MapSymbol;
-
-typedef enum {
- AA_IDLE = 0,
- AA_CHARGE = 1,
- AA_ATTACK = 2,
-} AttackAnimState;
-
-typedef enum {
- P_IDLE = 0,
- P_MOVE = 1,
- P_HIT = 2,
-} PlayerState;
-
-typedef enum {
- C_IDLE = 0,
- C_OBSERVE = 1,
- C_PATROL = 2,
- C_FOLLOW = 3,
- C_AGGRO = 4,
- C_HIT = 5,
- C_DEAD = 6
-} CharState;
-
-typedef enum {
- AI_NONE = 0,
- AI_IDLE = 1,
- AI_PATROL = 2,
- AI_DETECT = 3,
- AI_ATTACK = 4,
-} AIState;
-
-typedef enum {
- HA_IDLE = 0,
- HA_PLAY = 1,
-} HitAnimState;
-
-typedef enum {
- NONE = 0,
- PLAYER = 1,
- TROLL = 2,
- BANDIT = 3,
-} CharacterType;
-
-typedef enum {
- PT_NONE = 0,
- PT_ALLY = 1,
- PT_ATTACK = 2,
-} PotionType;
-
-typedef enum {
- PS_NONE = 0,
- PS_HELD = 1,
- PS_THROWN = 2,
- PS_SPREAD = 3,
-} PotionState;
-
-typedef enum {
- GS_GAME = 0,
- GS_UI = 1,
- GS_SUCCESS = 2,
- GS_OVER = 3,
-} GameplayState;
-
-typedef enum {
- PATROL_TOP = 0,
- PATROL_LEFT = 1,
- PATROL_DOWN = 2,
- PATROL_RIGHT = 3,
- PATROL_END = 4,
-} PatrolDir;
-
-typedef struct ScuffString {
- char *buffer;
- int len;
- int capacity;
-} String;
-
-struct Entity {
- int type; // EntityType
- int id; // Entity ID
-};
-
-typedef struct Entity AttackedEntity;
-typedef struct Entity AggroEntity;
-typedef struct Entity FriendEntity;
-
-struct Potion {
- int state;
- int type;
- float radius; // radius during which potion effects last
- int damage; // how much damage potion does
- int healing; // how much healing potion does
- float speed_multiplier; // how much enemy speed is effected inside potion radius
- float t_potion_throw_start;
- float t_potion_spread_start;
- float t_potion_spread_duration; // how long does the potion spread last
- Vector2 throw_dir;
- Vector2 position_start;
- Vector2 position_curr;
- Vector2 position_target;
- Color tint_color_spread;
- Color tint_color_effect;
- Texture2D *sprite;
-} Potion;
-
-typedef struct Potion FirePotion;
-typedef struct Potion FriendPotion;
-
-typedef struct Player {
- int entity_id;
- int state; // PlayerState
- int tile_id; // MapSymbol
- int health;
- float move_speed;
- Vector2 position;
- Vector2 target_position;
- Vector2 move_dir;
- Color tint_color;
- Rectangle render_rect;
- Texture2D *sprite;
- // attack state
- bool is_attack;
- float throw_dist;
- Vector2 attack_dir;
- float potion_throw_speed;
- float potion_throw_dist;
- struct Potion *active_potion;
- FirePotion fire_potion;
- FriendPotion friend_potion;
- //
- // Animation
- //
- int anim_hit_state;
- float anim_hit_speed;
- double t_anim_hit_start;
- float t_anim_hit_duration;
-} Player;
-
-struct Character {
- bool isburning;
- int entity_type; // TROLL / BANDIT
- int entity_id;
- int state; // CharState
- int tile_id; // MapSymbol
- int home_tile_id; // MapSymbol
- int ai_state;
- int health;
- float speed_multiplier;
- float move_speed;
- float detection_threshold;
- float attack_threshold;
- // improved idle behavior
- PatrolDir patrol_dir;
- bool to_core_pos;
- Vector2 core_position; // this is the main position characters will stick to
- double t_idle_start; // time spent at core position, useful to rotate them out of positions
- float t_idle_duration; // max allowed duration they should be idle
-
- Vector2 position;
- Vector2 last_enemy_position;
- Vector2 move_dir;
- Vector2 target_position;
- Rectangle target_rect;
- Rectangle render_rect;
- Color tint_color_base;
- Color tint_color_active;
- Color tint_color;
- Texture2D* sprite;
- AggroEntity attackers[2];
- FriendEntity friends[2];
- //
- // Animation
- //
- // getting hit
- int anim_hit_state;
- float anim_hit_speed;
- double t_anim_hit_start;
- float t_anim_hit_duration;
- // getting burned
- double t_anim_burn_start;
-
- // attacking
- int anim_attack_state;
- float anim_attack_speed;
- float t_anim_charge_duration;
- float t_anim_attack_duration;
- double t_anim_charge_start;
- double t_anim_attack_start;
-};
-
-typedef struct Character Troll;
-typedef struct Character Bandit;
-
-typedef struct State {
- int gameplay_state;
- // how much scaling to apply from original asset resolution
- float render_scale;
- Vector2 pixels_per_gridbox;
- Vector2 mouse_position;
- // @note: normally when we place a texture, the coordinates
- // are the top left coordinates. This will cause a disconnect
- // when moving the player with a point and click motion.
- // To fix that we calculate a new position so the player_coordinates
- // are in the center. This will make it so when the player clicks on the
- // ground somewhere, the character sprite will be properly centered on that point.
-
- Player player;
- Troll _troll;
- Troll trolls[5];
- int troll_arr_sz;
- Bandit _bandit;
- Bandit bandits[5];
- int bandit_arr_sz;
- Vector2 bandit_position;
- // player movement
- // @todo
- // direction player is being hit from, incorporate that into the gameplay code
- // For now, just update the player_move_dir to the player_hit_dir
- // Vector2 player_hit_dir;
- // float player_move_delta; // amount player will move
- // target position player will move to
- // 1. the player can move intentionally, in which case carry forward from player position target
- // 2. the player can move from feedback of being hit, NOT IMPLEMENTED YET
-
- // game sprites
- Texture2D *grass_sprite;
-
- Texture2D *troll_weapon_sprite;
- Texture2D *bandit_sprite;
- Texture2D *bandit_weapon_sprite;
-
- Texture2D *troll_area_floor_sprite;
- Texture2D *bandit_area_floor_sprite;
-
- Texture2D *troll_base_sprite;
- Texture2D *bandit_base_sprite;
-
- // key sprites and stuff
- int key_picked_count;
- bool key_should_render[2];
- Texture2D *key_sprite;
- Vector2 key_positions[2];
- Rectangle key_render_rects[2];
- // gate stuff
- bool is_gate_open;
- Vector2 gate_position;
- Rectangle gate_render_rect;
- Texture2D *active_gate_sprite;
- Texture2D *gate_closed_sprite;
- Texture2D *gate_open_sprite;
-
- String *action_log;
-} State;
-
-//----------------------------------------------------------------------------------
-// Global Variables Definition
-//----------------------------------------------------------------------------------
-const int screenWidth = 1280;
-const int screenHeight = 1024;
-State mega_state = {};
-// layer ground
-int floor_grid_map[8][8] = {{O, O, O, O, O, O, O, O},
- {O, O, O, O, T, T, T, T},
- {B, B, B, B, T, T, T, T},
- {B, B, B, B, T, T, T, T},
- {B, B, B, B, T, T, T, T},
- {B, B, B, B, T, T, T, T},
- {B, B, B, B, T, T, T, T},
- {B, B, B, B, T, T, T, T}};
-// vegetation grid
-int floor_cover_grid_map[8][8] = {{O, O, O, O, O, O, O, O},
- {O, O, O, O, O, O, O, O},
- {O, O, O, O, O, O, O, O},
- {O, O, O, O, O, O, O, O},
- {O, O, O, O, O, O, O, T_B},
- {O, B_B, O, O, O, O, O, O},
- {O, O, O, O, O, O, O, O},
- {O, O, O, O, O, O, O, O}};
-Vector2 grid_dims = {8, 8};
-//----------------------------------------------------------------------------------
-// Module functions declaration
-//----------------------------------------------------------------------------------
-void CenterRectAroundTL(Rectangle *to_center, Vector2 position);
-void UpdateDrawFrame(); // Update and Draw one frame
-void CenterRectAroundTL(Rectangle *to_center, Vector2 position)
-{
- to_center->x = position.x - ((float)to_center->width)/2.0f;
- to_center->y = position.y - ((float)to_center->height)/2.0f;
-}
-
-
-int main(void)
-{
- InitWindow(screenWidth, screenHeight, "blaidville prototype");
- SetTargetFPS(60);
- SetExitKey(0);
- Texture2D grass_sprite = LoadTexture("./assets/dungeon/floor/grass/grass_flowers_blue_1_new.png");
- Texture2D player_sprite = LoadTexture("./assets/player/base/human_male.png");
- Texture2D troll_sprite = LoadTexture("./assets/monster/hill_giant_old.png");
- Texture2D bandit_sprite = LoadTexture("./assets/monster/unique/maurice_new.png");
- Texture2D troll_area_floor_sprite = LoadTexture("./assets/dungeon/floor/dirt_northeast_new.png");
- Texture2D bandit_area_floor_sprite = LoadTexture("./assets/dungeon/floor/dirt_east_new.png");
- Texture2D bandit_base_sprite = LoadTexture("./assets/dungeon/floor/hive_3.png");
- Texture2D troll_base_sprite = LoadTexture("./assets/dungeon/floor/dirt_2_old.png");
- Texture2D troll_weapon_sprite = LoadTexture("./assets/item/weapon/club_old.png");
- Texture2D fire_potion_sprite = LoadTexture("./assets/item/potion/ruby_old.png");
- Texture2D friend_potion_sprite = LoadTexture("./assets/item/potion/emerald.png");
- Texture2D key_sprite = LoadTexture("./assets/item/misc/key.png");
- Texture2D gate_closed_sprite = LoadTexture("./assets/dungeon/gateways/bazaar_gone.png");
- Texture2D gate_open_sprite = LoadTexture("./assets/dungeon/gateways/bazaar_portal.png");
-
- mega_state.render_scale = 2.0f;
-
- mega_state.key_sprite = &key_sprite;
- mega_state.key_positions[0] = (Vector2){200, 700};
- mega_state.key_positions[1] = (Vector2){1200, 600};
- mega_state.key_render_rects[0] = (Rectangle){.width=key_sprite.width, .height=key_sprite.height};
- mega_state.key_render_rects[1] = (Rectangle){.width=key_sprite.width, .height=key_sprite.height};
- CenterRectAroundTL(&mega_state.key_render_rects[0], mega_state.key_positions[0]);
- CenterRectAroundTL(&mega_state.key_render_rects[1], mega_state.key_positions[1]);
- mega_state.key_should_render[0] = 1;
- mega_state.key_should_render[1] = 1;
-
- mega_state.grass_sprite = &grass_sprite;
- mega_state.bandit_sprite = &bandit_sprite;
- mega_state.gate_open_sprite = &gate_open_sprite;
- mega_state.gate_closed_sprite = &gate_closed_sprite;
- mega_state.active_gate_sprite = &gate_closed_sprite;
- mega_state.troll_area_floor_sprite = &troll_area_floor_sprite;
- mega_state.bandit_area_floor_sprite = &bandit_area_floor_sprite;
- mega_state.bandit_base_sprite = &bandit_base_sprite;
- mega_state.troll_base_sprite = &troll_base_sprite;
- mega_state.troll_weapon_sprite = &troll_weapon_sprite;
- mega_state.pixels_per_gridbox = (Vector2){screenWidth/grid_dims.x, screenHeight/grid_dims.y};
-
- // characters
- // player
- mega_state.player = (Player){
- .health = 45.0f,
- .position = (Vector2){50.0f, 50.0f},
- .move_speed = 2.0f,
- .sprite = &player_sprite,
- .tint_color = WHITE,
- .render_rect = (Rectangle){
- .x=0,.y=0,
- .width=0.5*player_sprite.width*mega_state.render_scale,
- .height=player_sprite.height*mega_state.render_scale
- },
- .throw_dist = 100.0f,
- .fire_potion = (FirePotion){
- .state=PS_NONE,.type=PT_ATTACK,.radius=40.0f,.damage=5,
- .speed_multiplier=0.5f, .sprite=&fire_potion_sprite,
- .t_potion_spread_duration = 5.0f,
- .tint_color_spread=(Color){200, 50, 50, 100}, .tint_color_effect=(Color){200, 50, 50, 255}
- },
- .friend_potion = (FriendPotion){
- .state=PS_HELD,.type=PT_ALLY,.radius=40.0f,
- .speed_multiplier=1.0f, .sprite=&friend_potion_sprite,
- .t_potion_spread_duration = 5.0f,
- .tint_color_spread=(Color){50, 200, 50, 100}, .tint_color_effect=(Color){50, 200, 50, 255}
- },
- .potion_throw_speed = 250.0f,
- .potion_throw_dist = 200.0f,
- .anim_hit_speed = 50.0f,
- .t_anim_hit_duration = 0.2f,
- };
- // troll
- Troll troll = {
- .state = C_IDLE,
- .entity_type = TROLL,
- .home_tile_id = T,
- .health = 50,
- .move_speed = 2.0f,
- .speed_multiplier = 1.0f,
- .tint_color_base = WHITE,
- .tint_color_active = WHITE,
- .tint_color = WHITE,
- .render_rect = (Rectangle){.x=0,.y=0,.width=troll_sprite.width*mega_state.render_scale,.height=troll_sprite.height*mega_state.render_scale},
- .sprite = &troll_sprite,
- .t_anim_charge_duration = 1.0f,
- .t_anim_attack_duration = 0.4,
- .anim_attack_speed = 100.0f,
- .anim_hit_speed = 20.0f,
- .t_anim_hit_duration = 0.2f,
- .t_idle_duration = 2.0f,
- .to_core_pos = true,
- };
- mega_state.troll_arr_sz = 5;
-
- mega_state.trolls[0] = troll;
- mega_state.trolls[0].entity_id = 0;
- mega_state.trolls[0].t_idle_duration = 4.0f;
- mega_state.trolls[0].position = (Vector2){750, 340};
- mega_state.trolls[0].core_position = mega_state.trolls[0].position;
-
- mega_state.trolls[1] = troll;
- mega_state.trolls[1].entity_id = 1;
- mega_state.trolls[1].position = (Vector2){1200, 300};
- mega_state.trolls[1].core_position = mega_state.trolls[1].position;
-
- mega_state.trolls[2] = troll;
- mega_state.trolls[2].entity_id = 2;
- mega_state.trolls[2].t_idle_duration = 3.5f;
- mega_state.trolls[2].position = (Vector2){800, 800};
- mega_state.trolls[2].core_position = mega_state.trolls[2].position;
-
- mega_state.trolls[3] = troll;
- mega_state.trolls[3].entity_id = 3;
- mega_state.trolls[3].t_idle_duration = 3.0f;
- mega_state.trolls[3].position = (Vector2){1130, 640};
- mega_state.trolls[3].core_position = mega_state.trolls[0].position;
-
- mega_state.trolls[4] = troll;
- mega_state.trolls[4].entity_id = 4;
- mega_state.trolls[4].t_idle_duration = 1.5f;
- mega_state.trolls[4].position = (Vector2){1000, 900};
- mega_state.trolls[4].core_position = mega_state.trolls[4].position;
-
- // bandit
- Bandit bandit = (Bandit){
- .state = C_IDLE,
- .ai_state = AI_NONE,
- .entity_type = BANDIT,
- .home_tile_id = B,
- .health = 40,
- .move_speed = 4.0f,
- .speed_multiplier = 1.0f,
- .tint_color_base = WHITE,
- .tint_color_active = WHITE,
- .tint_color = WHITE,
- .render_rect = (Rectangle){.x=0,.y=0,.width=bandit_sprite.width*mega_state.render_scale,.height=bandit_sprite.height*mega_state.render_scale},
- .sprite = &bandit_sprite,
- .t_anim_charge_duration = 0.5f,
- .t_anim_attack_duration = 0.2f,
- .anim_attack_speed = 50.0f,
- .anim_hit_speed = 50.0f,
- .t_anim_hit_duration = 0.2f,
- .t_idle_duration = 2.0f,
- .to_core_pos = true
- };
- mega_state.bandit_arr_sz = 5;
-
- mega_state.bandits[0] = bandit;
- mega_state.bandits[0].entity_id = 0;
- mega_state.bandits[0].position = (Vector2){264.0f, 900.0f};
- mega_state.bandits[0].core_position = mega_state.bandits[0].position;
-
- mega_state.bandits[1] = bandit;
- mega_state.bandits[1].entity_id = 1;
- mega_state.bandits[1].t_idle_duration = 4.0f;
- mega_state.bandits[1].position = (Vector2){164.0f, 600.0f};
- mega_state.bandits[1].core_position = mega_state.bandits[1].position;
-
- mega_state.bandits[2] = bandit;
- mega_state.bandits[2].entity_id = 2;
- mega_state.bandits[2].t_idle_duration = 3.0f;
- mega_state.bandits[2].position = (Vector2){264.0f, 400.0f};
- mega_state.bandits[2].core_position = mega_state.bandits[2].position;
-
- mega_state.bandits[3] = bandit;
- mega_state.bandits[3].entity_id = 3;
- mega_state.bandits[3].t_idle_duration = 2.5f;
- mega_state.bandits[3].position = (Vector2){400.0f, 800.0f};
- mega_state.bandits[3].core_position = mega_state.bandits[3].position;
-
- mega_state.bandits[4] = bandit;
- mega_state.bandits[4].entity_id = 4;
- mega_state.bandits[4].t_idle_duration = 1.0f;
- mega_state.bandits[4].position = (Vector2){400.0f, 600.0f};
- mega_state.bandits[4].core_position = mega_state.bandits[4].position;
-
- // @todo: action log to describe and dictate all the major events happen
- char *str_buffer = (char*)MemAlloc(512*sizeof(char));
- mega_state.player.active_potion = &mega_state.player.friend_potion;
- CenterRectAroundTL(&mega_state.trolls[0].render_rect, mega_state.trolls[0].position);
- CenterRectAroundTL(&mega_state.trolls[1].render_rect, mega_state.trolls[1].position);
-
- CenterRectAroundTL(&mega_state.bandits[0].render_rect, mega_state.bandits[0].position);
- CenterRectAroundTL(&mega_state.bandits[0].render_rect, mega_state.bandits[0].position);
- // no action log right now
- // mega_state.action_log = &(String){.buffer=str_buffer, .capacity=512, .len=0};
- mega_state.gameplay_state = GS_UI;
-
- mega_state.gate_position = (Vector2){.x=500.0f, .y=16.0f};
- mega_state.gate_render_rect = (Rectangle){.width=mega_state.gate_closed_sprite->width*1.5, .height=mega_state.gate_closed_sprite->height*1.5};
- CenterRectAroundTL(&mega_state.gate_render_rect, mega_state.gate_position);
-
- #if defined(PLATFORM_WEB)
- emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
- #else
- SetTargetFPS(60);
-
- while(!WindowShouldClose())
- {
- UpdateDrawFrame();
- }
- #endif
-
- CloseWindow();
-
- return 0;
-}
-
-void DrawMapFloorTiles()
-{
- Color BlackTint = {128,128,128,255};
- Texture2D grass = *mega_state.grass_sprite;
- float winc = (float)grass.width * mega_state.render_scale;
- float hinc = (float)grass.height * mega_state.render_scale;
- Vector2 grid_pos = {0, 0};
- for (int ypos=0; ypos<screenHeight; ypos+=hinc)
- {
- grid_pos.y = ((float)ypos) / ((float)mega_state.pixels_per_gridbox.y);
- for (int xpos=0; xpos<screenWidth; xpos+=winc)
- {
- grid_pos.x = ((float)xpos) / ((float)mega_state.pixels_per_gridbox.x);
- Vector2 pixel_pos = {xpos, ypos};
- int grid_ele = floor_grid_map[(int)grid_pos.y][(int)grid_pos.x];
- Texture2D render_tex;
- switch (grid_ele) {
- case (O):
- {
- render_tex = *mega_state.grass_sprite;
- } break;
- case (B):
- {
- render_tex = *mega_state.bandit_area_floor_sprite;
- } break;
- case (T):
- {
- render_tex = *mega_state.troll_area_floor_sprite;
- } break;
- default:
- {
- } break;
- }
- DrawTextureEx(render_tex, pixel_pos, 0, mega_state.render_scale, BlackTint);
- }
- }
-}
-
-void DrawFloorCoverTiles()
-{
- Color BlackTint = {128,128,128,255};
- Texture2D null_tex = *mega_state.player.sprite;
- float winc = (float)null_tex.width * mega_state.render_scale;
- float hinc = (float)null_tex.height * mega_state.render_scale;
-
- Vector2 grid_pos = {0, 0};
- for (int ypos=0; ypos<screenHeight; ypos+=hinc)
- {
- grid_pos.y = ((float)ypos) / ((float)mega_state.pixels_per_gridbox.y);
- for (int xpos=0; xpos<screenWidth; xpos+=winc)
- {
- grid_pos.x = ((float)xpos) / ((float)mega_state.pixels_per_gridbox.x);
- Vector2 pixel_pos = {xpos, ypos};
- int grid_ele = floor_cover_grid_map[(int)grid_pos.y][(int)grid_pos.x];
- Texture2D render_tex;
- switch (grid_ele) {
- case (B_B):
- {
- render_tex = *mega_state.bandit_base_sprite;
- } break;
- case (T_B):
- {
- render_tex = *mega_state.troll_base_sprite;
- } break;
- default:
- {
- render_tex = null_tex;
- } continue;
- }
- DrawTextureEx(render_tex, pixel_pos, 0, mega_state.render_scale, BlackTint);
- }
- }
-}
-
-Vector2 GetSpriteCenterPosition(Texture2D sprite, Vector2 position, float render_scale)
-{
- float centered_x = position.x - ((float)sprite.width)*render_scale/2.0f;
- float centered_y = position.y - ((float)sprite.height)*render_scale/2.0f;
-
- return (Vector2){.x = centered_x, .y = centered_y};
-}
-
-void DrawCharacters()
-{
- DrawTextureEx(*mega_state.active_gate_sprite,
- (Vector2){mega_state.gate_render_rect.x, mega_state.gate_render_rect.y},
- 0, mega_state.render_scale*1.5, WHITE);
- // draw potion
- if (mega_state.player.active_potion->state == PS_THROWN)
- {
- DrawTextureEx(*mega_state.player.active_potion->sprite,
- mega_state.player.active_potion->position_curr,
- 0, 0.4*mega_state.render_scale, WHITE);
- }
- else if (mega_state.player.active_potion->state == PS_SPREAD)
- {
- Vector2 pos = mega_state.player.active_potion->position_curr;
- DrawCircle(pos.x, pos.y, mega_state.player.active_potion->radius, mega_state.player.active_potion->tint_color_spread);
- }
- if (mega_state.key_should_render[0] == 1)
- {
- DrawTextureEx(*mega_state.key_sprite,
- (Vector2){mega_state.key_positions[0].x, mega_state.key_positions[0].y}, 0,
- mega_state.render_scale/2.0f, WHITE);
- }
- if (mega_state.key_should_render[1] == 1)
- {
- DrawTextureEx(*mega_state.key_sprite,
- (Vector2){mega_state.key_positions[1].x, mega_state.key_positions[1].y}, 0,
- mega_state.render_scale/2.0f, WHITE);
- }
-
- Rectangle src_rect, dest_rect;
- // draw Troll
- // - troll weapon
- for (int i=0;i<mega_state.troll_arr_sz;i++)
- {
- Vector2 troll_weapon_centered = GetSpriteCenterPosition(*mega_state.troll_weapon_sprite, mega_state.trolls[i].position, 1.0f);
- // move to left hand
- troll_weapon_centered.x -= mega_state.trolls[i].sprite->width;
- src_rect = (Rectangle){.x=0, .y=0, .width=-mega_state.troll_weapon_sprite->width, .height=mega_state.troll_weapon_sprite->height};
- dest_rect = (Rectangle){.x=troll_weapon_centered.x, .y=troll_weapon_centered.y,
- .width=0.5f*mega_state.render_scale*mega_state.troll_weapon_sprite->width,
- .height=0.5f*mega_state.render_scale*mega_state.troll_weapon_sprite->height};
- DrawTexturePro(*mega_state.troll_weapon_sprite, src_rect, dest_rect,
- (Vector2){0,0}, 0, RAYWHITE);
- // - troll sprite
- DrawTextureEx(*mega_state.trolls[i].sprite,
- (Vector2){mega_state.trolls[i].render_rect.x, mega_state.trolls[i].render_rect.y},
- 0, mega_state.render_scale, mega_state.trolls[i].tint_color);
- // draw collision box
- //DrawRectangleLines(mega_state.troll.render_rect.x, mega_state.troll.render_rect.y,
- // mega_state.troll.render_rect.width, mega_state.troll.render_rect.height, RED);
- }
-
- // draw Bandit
- for (int i=0;i<mega_state.bandit_arr_sz;i++)
- {
- DrawTextureEx(*mega_state.bandits[i].sprite,
- (Vector2){mega_state.bandits[i].render_rect.x, mega_state.bandits[i].render_rect.y},
- 0, mega_state.render_scale, mega_state.bandits[i].tint_color);
- }
- // draw player
- float p_render_scale = 1.0f;
- Vector2 player_weapon_centered = GetSpriteCenterPosition(*mega_state.player.sprite, mega_state.player.position, p_render_scale);
- // move to left hand
- player_weapon_centered.x -= (mega_state.player.sprite->width*p_render_scale/2.0f) - 2.0f;
- player_weapon_centered.y += (12.0f);
- src_rect = (Rectangle){
- .x=0, .y=0,
- .width = mega_state.player.active_potion->sprite->width,
- .height = mega_state.player.active_potion->sprite->height
- };
-
- dest_rect = (Rectangle){.x=player_weapon_centered.x, .y=player_weapon_centered.y,
- .width=0.4f*mega_state.render_scale*mega_state.player.active_potion->sprite->width,
- .height=0.4f*mega_state.render_scale*mega_state.player.active_potion->sprite->height};
-
- DrawTexturePro(*mega_state.player.active_potion->sprite, src_rect, dest_rect,
- (Vector2){0,0}, 0, RAYWHITE);
- Vector2 player_center = GetSpriteCenterPosition(*mega_state.player.sprite, mega_state.player.position, mega_state.render_scale);
- DrawTextureEx(*mega_state.player.sprite, player_center, 0, mega_state.render_scale, mega_state.player.tint_color);
-
-}
-
-int GetTileIDFromWorld(Vector2 world_position)
-{
- Vector2 grid_pos = Vector2Divide(Vector2Multiply(world_position, grid_dims), (Vector2){screenWidth, screenHeight});
- int tile = floor_grid_map[(int)grid_pos.y][(int)grid_pos.x];
- return tile;
-}
-
-bool MoveCharacter(struct Character *to_move, Vector2 position)
-{
- Vector2 new_pos = Vector2Add(to_move->position, position);
- int tile_at_new_pos = GetTileIDFromWorld(new_pos);
- int tile_at_curr_pos = GetTileIDFromWorld(to_move->position);
- bool char_at_home = to_move->home_tile_id == tile_at_curr_pos ? true: false;
- // move only if next position in home tile
- if (tile_at_new_pos == to_move->home_tile_id || to_move->state == C_FOLLOW || char_at_home == false)
- {
- to_move->position = Vector2Add(to_move->position, position);
- return true;
- }
- else
- {
- to_move->target_position = to_move->position;
- return false;
- }
-}
-
-AttackedEntity GetEntityToAttack(struct Character attacker)
-{
- AttackedEntity attackee = {};
- // check if player can be attacked
- bool attacker_at_home_tile = GetTileIDFromWorld(attacker.position) == attacker.home_tile_id ? true: false;
- Vector2 char_position = mega_state.player.position;
- int char_tile_id = GetTileIDFromWorld(char_position);
- Rectangle char_rect = mega_state.player.render_rect;
- float min_dist = screenWidth;
-
- if ((attacker.attackers[0].type == PLAYER || char_tile_id == attacker.home_tile_id || attacker_at_home_tile == false)
- && attacker.friends[0].type != PLAYER)
- {
- float char_dist = Vector2Distance(char_position, attacker.position);
- if (char_dist < 200)
- {
- attackee.type = PLAYER;
- if (attacker.attackers[0].type == PLAYER) return attackee;
- }
- }
-
- // check if bandit can instead be attacked
- for (int i=0; i<mega_state.bandit_arr_sz;i++)
- {
- Bandit bandit = mega_state.bandits[i];
- char_tile_id = GetTileIDFromWorld(char_position);
- char_position = bandit.position;
- char_rect = bandit.render_rect;
- if (bandit.state == C_DEAD) continue;
- if ((char_tile_id == attacker.home_tile_id || attacker_at_home_tile == false) &&
- ((attacker.attackers[0].type == BANDIT && attacker.attackers[0].id == i) ||
- attacker.entity_type != BANDIT))
- {
- float char_dist = Vector2Distance(char_position, attacker.position);
- if (char_dist < 200 && (char_dist < min_dist || attacker.attackers[0].type == BANDIT))
- {
- min_dist = char_dist;
- attackee.type = BANDIT;
- attackee.id = bandit.entity_id;
- if (attacker.attackers[0].type == BANDIT) return attackee;
- }
- }
- }
-
- // check if troll can instead be attacked
- for (int i=0; i<mega_state.troll_arr_sz;i++) {
- char_position = mega_state.trolls[i].position;
- char_tile_id = GetTileIDFromWorld(char_position);
- char_rect = mega_state.trolls[i].render_rect;
- if (mega_state.trolls[i].state == C_DEAD) continue;
- if ((char_tile_id == attacker.home_tile_id || attacker_at_home_tile == false) &&
- ((attacker.attackers[0].type == TROLL && attacker.attackers[0].id == i) ||
- attacker.entity_type != TROLL))
- {
- float char_dist = Vector2Distance(char_position, attacker.position);
- if (char_dist < 200 && (char_dist < min_dist || attacker.attackers[0].type == TROLL))
- {
- min_dist = char_dist;
- attackee.type = TROLL;
- attackee.id = mega_state.trolls[i].entity_id;
- if (attacker.attackers[0].type == TROLL) return attackee;
- }
- }
- }
-
- return attackee;
-}
-
-bool TrollAttackTarget(Troll *troll, AttackedEntity to_attack)
-{
- float dist_to_target = 0;
-
- troll->state = C_IDLE;
- troll->ai_state = AI_NONE;
- switch (to_attack.type)
- {
- case (PLAYER):
- {
- troll->last_enemy_position = mega_state.player.position;
- troll->target_position = mega_state.player.position;
- troll->target_rect = mega_state.player.render_rect;
-
- dist_to_target = Vector2Distance(troll->target_position, troll->position);
- troll->ai_state = AI_DETECT;
- troll->state = C_FOLLOW;
- } break;
- case (BANDIT):
- {
- troll->last_enemy_position = mega_state.bandits[to_attack.id].position;
- troll->target_position = mega_state.bandits[to_attack.id].position;
- troll->target_rect = mega_state.bandits[to_attack.id].render_rect;
-
- dist_to_target = Vector2Distance(troll->target_position, troll->position);
- troll->ai_state = AI_DETECT;
- troll->state = C_FOLLOW;
- } break;
- default:
- break;
- }
- if (troll->ai_state == AI_DETECT && dist_to_target < 80)
- {
- troll->ai_state = AI_ATTACK;
- }
- if (troll->ai_state >= AI_DETECT && troll->anim_attack_state != AA_ATTACK)
- {
- troll->move_dir = Vector2Normalize(Vector2Subtract(troll->target_position, troll->position));
- if (dist_to_target > 10.0f)
- {
- // @note: this actually might not even be needed
- // move only if both are more than 10pixels apart.
- // it becomes jarring other wise
- MoveCharacter(troll, Vector2Scale(troll->move_dir, troll->speed_multiplier*troll->move_speed));
- }
- }
- CenterRectAroundTL(&troll->render_rect, troll->position);
- if (troll->anim_attack_state == AA_IDLE && troll->ai_state == AI_ATTACK)
- {
- // start attack animation
- troll->t_anim_charge_start = GetTime();
- troll->anim_attack_state = AA_CHARGE;
- }
- float charge_time = 0.0f;
- float charge_color_delta = 0.0f;
- if (troll->anim_attack_state == AA_CHARGE)
- {
- // get color based on time
- float charge_progress = (GetTime() - troll->t_anim_charge_start) / troll->t_anim_charge_duration;
- troll->tint_color.r = Clamp(troll->tint_color_active.r - (charge_progress*troll->tint_color_active.r), 0, 255);
- if (charge_progress >= 1.0f)
- {
- troll->anim_attack_state = AA_ATTACK;
- troll->t_anim_attack_start = GetTime();
- }
- }
- else if (troll->anim_attack_state == AA_ATTACK)
- {
- // maximum distance to attack jump in
- float anim_length = GetTime() - troll->t_anim_attack_start;
- float ft = GetFrameTime();
- float pixel_per_second_per_ft = ft*troll->anim_attack_speed/troll->t_anim_attack_duration;
- troll->position = Vector2Add(troll->position, Vector2Scale(troll->move_dir, pixel_per_second_per_ft));
- troll->tint_color = (Color){255, 128, 255, 255};
- // get troll center position and check for collision with player
- // now check if colliding with player
- bool is_colliding = CheckCollisionRecs(troll->target_rect, troll->render_rect);
- if (anim_length >= troll->t_anim_attack_duration || is_colliding)
- {
- troll->state = C_IDLE;
- troll->ai_state = AI_NONE;
- troll->anim_attack_state = AA_IDLE;
- troll->tint_color = troll->tint_color_active;
- if (is_colliding == true)
- {
- return true; // is colliding with target
- }
- }
- }
- // once troll is done moving, clear state.
- troll->state = C_IDLE;
- troll->ai_state = AI_NONE;
- return false;
-}
-
-bool BanditAttackTarget(Bandit *bandit, AttackedEntity to_attack)
-{
- float dist_to_target = 0;
-
- bandit->state = C_IDLE;
- bandit->ai_state = AI_NONE;
- switch (to_attack.type)
- {
- case (PLAYER):
- {
- bandit->last_enemy_position = mega_state.player.position;
- bandit->target_position = mega_state.player.position;
- bandit->target_rect = mega_state.player.render_rect;
-
- dist_to_target = Vector2Distance(bandit->target_position, bandit->position);
- bandit->ai_state = AI_DETECT;
- bandit->state = C_FOLLOW;
- } break;
- case (TROLL):
- {
- bandit->last_enemy_position = mega_state.trolls[to_attack.id].position;
- bandit->target_position = mega_state.trolls[to_attack.id].position;
- bandit->target_rect = mega_state.trolls[to_attack.id].render_rect;
-
- dist_to_target = Vector2Distance(bandit->target_position, bandit->position);
- bandit->ai_state = AI_DETECT;
- bandit->state = C_FOLLOW;
- } break;
- default:
- break;
- }
- if (bandit->ai_state == AI_DETECT && dist_to_target < 80)
- {
- bandit->ai_state = AI_ATTACK;
- }
- if (bandit->ai_state >= AI_DETECT && bandit->anim_attack_state != AA_ATTACK)
- {
- bandit->move_dir = Vector2Normalize(Vector2Subtract(bandit->target_position, bandit->position));
- if (dist_to_target > 10.0f)
- {
- // @note: this actually might not even be needed
- // move only if both are more than 10pixels apart.
- // it becomes jarring other wise
- bool can_move = MoveCharacter(bandit, Vector2Scale(bandit->move_dir, bandit->speed_multiplier*bandit->move_speed));
- }
- }
- CenterRectAroundTL(&bandit->render_rect, bandit->position);
- if (bandit->anim_attack_state == AA_IDLE && bandit->ai_state == AI_ATTACK)
- {
- // start attack animation
- bandit->t_anim_charge_start = GetTime();
- bandit->anim_attack_state = AA_CHARGE;
- }
- float charge_time = 0.0f;
- float charge_color_delta = 0.0f;
- if (bandit->anim_attack_state == AA_CHARGE)
- {
- // get color based on time
- float charge_progress = (GetTime() - bandit->t_anim_charge_start) / bandit->t_anim_charge_duration;
- bandit->tint_color.r = Clamp(bandit->tint_color_active.r - (charge_progress*bandit->tint_color_active.r), 0, 255);
- if (charge_progress >= 1.0f)
- {
- bandit->anim_attack_state = AA_ATTACK;
- bandit->t_anim_attack_start = GetTime();
- }
- }
- else if (bandit->anim_attack_state == AA_ATTACK)
- {
- // maximum distance to attack jump in
- float anim_length = GetTime() - bandit->t_anim_attack_start;
- float ft = GetFrameTime();
- float pixel_per_second_per_ft = ft*bandit->anim_attack_speed/bandit->t_anim_attack_duration;
- bandit->position = Vector2Add(bandit->position, Vector2Scale(bandit->move_dir, pixel_per_second_per_ft));
- bandit->tint_color = (Color){255, 128, 255, 255};
- // get bandit center position and check for collision with player
- // now check if colliding with player
- bool is_colliding = CheckCollisionRecs(bandit->target_rect, bandit->render_rect);
- if (anim_length >= bandit->t_anim_attack_duration || is_colliding)
- {
- bandit->state = C_IDLE;
- bandit->ai_state = AI_NONE;
- bandit->anim_attack_state = AA_IDLE;
- bandit->tint_color = bandit->tint_color_active;
- if (is_colliding == true)
- {
- return true; // is colliding with target
- }
- }
- }
- bandit->state = C_IDLE;
- bandit->ai_state = AI_NONE;
- return false;
-}
-void UpdateDrawFrame(void)
-{
- // INPUT
- if (IsKeyPressed(KEY_ESCAPE))
- {
- mega_state.gameplay_state = mega_state.gameplay_state == GS_UI ? GS_GAME : GS_UI;
- }
- if (mega_state.gameplay_state == GS_GAME)
- {
- mega_state.mouse_position = GetMousePosition();
- if (IsKeyPressed(KEY_ONE))
- {
- mega_state.player.active_potion = &mega_state.player.fire_potion;
- mega_state.player.active_potion->t_potion_throw_start = 0;
- mega_state.player.active_potion->t_potion_spread_start = 0;
- mega_state.player.active_potion->state = PS_HELD;
- }
- else if (IsKeyPressed(KEY_TWO))
- {
- mega_state.player.active_potion = &mega_state.player.friend_potion;
- mega_state.player.active_potion->t_potion_throw_start = 0;
- mega_state.player.active_potion->t_potion_spread_start = 0;
- mega_state.player.active_potion->state = PS_HELD;
- }
- if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && mega_state.player.state <= P_MOVE)
- {
- mega_state.player.state = P_MOVE;
- mega_state.player.target_position = mega_state.mouse_position;
- mega_state.player.move_dir = Vector2Normalize(Vector2Subtract(mega_state.player.target_position, mega_state.player.position));
- }
- if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
- {
- // @todo: abilities
- mega_state.player.active_potion->throw_dir = Vector2Normalize(Vector2Subtract(mega_state.mouse_position, mega_state.player.position));
- mega_state.player.active_potion->position_start = mega_state.player.position;
- mega_state.player.active_potion->position_curr = mega_state.player.position;
- mega_state.player.active_potion->position_target = mega_state.mouse_position;
- mega_state.player.active_potion->state = PS_THROWN;
- mega_state.player.active_potion->t_potion_throw_start = GetTime();
- }
-
- // PROCESSING
- // initialize values
- for (int i = 0; i < mega_state.troll_arr_sz; i++)
- {
- if (mega_state.trolls[i].health <= 0)
- {
- mega_state.trolls[i].state = C_DEAD;
- mega_state.trolls[i].tint_color = (Color){128, 128, 128, 128};
- }
- mega_state.trolls[i].speed_multiplier = 1.0f;
- }
- for (int i = 0; i < mega_state.bandit_arr_sz; i++)
- {
- if (mega_state.bandits[i].health <= 0)
- {
- mega_state.bandits[i].state = C_DEAD;
- mega_state.bandits[i].tint_color = (Color){128, 128, 128, 128};
- }
- mega_state.bandits[i].speed_multiplier = 1.0f;
- }
- if (mega_state.player.health <= 0)
- {
- mega_state.gameplay_state = GS_OVER;
- }
-
- switch (mega_state.player.state)
- {
- case (P_MOVE):
- {
- // MOVE PLAYER
- Vector2 next_position = Vector2Add(mega_state.player.position,
- Vector2Scale(mega_state.player.move_dir, mega_state.player.move_speed));
- // checke player collisions
- bool is_colliding_gate = CheckCollisionRecs(mega_state.player.render_rect, mega_state.gate_render_rect);
- if (is_colliding_gate)
- {
- if (mega_state.key_picked_count == 2)
- {
- mega_state.is_gate_open = true;
- mega_state.active_gate_sprite = mega_state.gate_open_sprite;
- mega_state.gameplay_state = GS_SUCCESS;
- }
- }
- mega_state.player.position = next_position;
-
- if (Vector2Distance(mega_state.player.position, mega_state.player.target_position) <= 5.0f)
- {
- mega_state.player.state = P_IDLE;
- }
- // calculate center positions
- CenterRectAroundTL(&mega_state.player.render_rect, mega_state.player.position);
- mega_state.player.tile_id = GetTileIDFromWorld(mega_state.player.position);
- // check if a key can be picked up
- for (int i=0;i<2;i++)
- {
- bool is_colliding = CheckCollisionRecs(mega_state.player.render_rect, mega_state.key_render_rects[i]);
- if (is_colliding && mega_state.key_should_render[i] == 1)
- {
- mega_state.key_picked_count += 1;
- mega_state.key_should_render[i] = 0;
- }
- }
- } break;
- case (P_HIT):
- {
- float anim_length = GetTime() - mega_state.player.t_anim_hit_start;
- float ft = GetFrameTime();
- float pixel_per_second_per_ft = ft*mega_state.player.anim_hit_speed/mega_state.player.t_anim_hit_duration;
- mega_state.player.position = Vector2Add(mega_state.player.position, Vector2Scale(mega_state.player.move_dir, pixel_per_second_per_ft));
- mega_state.player.tint_color = (Color){255, 128, 128, 255};
- if (anim_length >= mega_state.player.t_anim_hit_duration)
- {
- mega_state.player.state = P_IDLE;
- mega_state.player.anim_hit_state = HA_IDLE;
- mega_state.player.tint_color = (Color){255, 255, 255, 255};
- }
- // calculate center positions
- CenterRectAroundTL(&mega_state.player.render_rect, mega_state.player.position);
- mega_state.player.tile_id = GetTileIDFromWorld(mega_state.player.position);
- } break;
- default:
- {}break;
- }
- switch (mega_state.player.active_potion->state)
- {
- case (PS_THROWN):
- {
- // play potion throw animation
- float throw_speed = GetFrameTime() * mega_state.player.potion_throw_speed;
- float dist_thrown = Vector2Distance(mega_state.player.active_potion->position_curr, mega_state.player.active_potion->position_start);
- mega_state.player.active_potion->position_curr = Vector2Add(mega_state.player.active_potion->position_curr,
- Vector2Scale(mega_state.player.active_potion->throw_dir, throw_speed));
- float dist_to_target = Vector2Distance(mega_state.player.active_potion->position_curr, mega_state.player.active_potion->position_target);
- if (dist_thrown > mega_state.player.potion_throw_dist || dist_to_target <= 5.0f)
- {
- // change potion state to potion explode
- mega_state.player.active_potion->state = PS_SPREAD;
- mega_state.player.active_potion->t_potion_spread_start = GetTime();
- }
- } break;
- case (PS_SPREAD):
- {
- float spread_duration = GetTime() - mega_state.player.active_potion->t_potion_spread_start;
- if (spread_duration >= mega_state.player.active_potion->t_potion_spread_duration)
- {
- mega_state.player.active_potion->state = PS_HELD;
- }
- // loop through enemies to check if any are being burned
- // check troll
- for (int i=0;i<mega_state.troll_arr_sz;i++)
- {
- Troll *troll = &mega_state.trolls[i];
- if (troll->state == C_DEAD) continue;
- float dist_to_enemy = Vector2Distance(troll->position, mega_state.player.active_potion->position_curr);
- if (dist_to_enemy <= mega_state.player.active_potion->radius)
- {
- if (mega_state.player.active_potion->type == PT_ATTACK)
- {
- // mark troll state as being burned
- if (troll->isburning == false)
- {
- troll->isburning = true;
- troll->t_anim_burn_start = GetTime();
- troll->attackers[0].type = PLAYER;
- troll->attackers[0].id = 0;
- }
- }
- else if (mega_state.player.active_potion->type == PT_ALLY)
- {
- troll->friends[0] = (FriendEntity){.type=PLAYER, .id=0};
- }
- troll->tint_color_active = mega_state.player.active_potion->tint_color_effect;
- troll->tint_color = troll->tint_color_active;
- troll->speed_multiplier = mega_state.player.active_potion->speed_multiplier;
- }
- else
- {
- troll->speed_multiplier = 1.0f;
- }
- if (mega_state.player.active_potion->state != PS_SPREAD)
- {
- troll->tint_color_active = troll->tint_color_base;
- troll->tint_color = troll->tint_color_active;
- troll->isburning = false;
- // remove player/entity as friend
- troll->friends[0].type = 0;
- troll->friends[0].id = 0;
- }
- }
- // check bandit
- for (int i=0;i<mega_state.bandit_arr_sz;i++)
- {
- Bandit *bandit = &mega_state.bandits[i];
- if (bandit->state == C_DEAD) continue;
- float dist_to_enemy = Vector2Distance(bandit->position, mega_state.player.active_potion->position_curr);
- if (dist_to_enemy <= mega_state.player.active_potion->radius)
- {
- if (mega_state.player.active_potion->type == PT_ATTACK)
- {
- // mark bandit state as being burned
- if (bandit->isburning == false)
- {
- bandit->isburning = true;
- bandit->t_anim_burn_start = GetTime();
- bandit->attackers[0].type = PLAYER;
- bandit->attackers[0].id = 0;
- }
- }
- else if (mega_state.player.active_potion->type == PT_ALLY)
- {
- bandit->friends[0] = (FriendEntity){.type=PLAYER, .id=0};
- }
- bandit->tint_color_active = mega_state.player.active_potion->tint_color_effect;
- bandit->tint_color = bandit->tint_color_active;
- bandit->speed_multiplier = mega_state.player.active_potion->speed_multiplier;
- }
- else
- {
- bandit->speed_multiplier = 1.0f;
- }
- if (mega_state.player.active_potion->state != PS_SPREAD)
- {
- bandit->tint_color_active = bandit->tint_color_base;
- bandit->tint_color = bandit->tint_color_active;
- bandit->isburning = false;
- // remove player/entity as friend
- bandit->friends[0].type = 0;
- bandit->friends[0].id = 0;
- }
- }
- } break;
- default:
- break;
- }
-
- // ================= TROLL DETECTION LOOP AND STUFF =======================
- for (int i=0;i<mega_state.troll_arr_sz;i++)
- {
- Troll *troll = &mega_state.trolls[i];
- if (troll->state == C_HIT)
- {
- float anim_length = GetTime() - troll->t_anim_hit_start;
- float ft = GetFrameTime();
- float pixel_per_second_per_ft = ft*troll->anim_hit_speed/troll->t_anim_hit_duration;
- troll->position = Vector2Add(troll->position, Vector2Scale(troll->move_dir, pixel_per_second_per_ft));
- troll->tint_color = (Color){255, 128, 128, 255};
- if (anim_length >= troll->t_anim_hit_duration)
- {
- troll->state = C_IDLE;
- troll->anim_hit_state = HA_IDLE;
- troll->tint_color = (Color){255, 255, 255, 255};
- }
- // calculate center positions
- CenterRectAroundTL(&troll->render_rect, troll->position);
- troll->tile_id = GetTileIDFromWorld(troll->position);
- }
- else if (troll->state != C_DEAD)
- {
- if (troll->isburning == true)
- {
- int anim_length_ms = 1000*(int)(GetTime() - troll->t_anim_burn_start);
- if (anim_length_ms%500 == 0 && anim_length_ms > 0)
- {
- // decrement health every 500ms
- troll->health -= 8;
- troll->t_anim_burn_start = GetTime();
- }
- }
- troll->speed_multiplier *= troll->anim_attack_state == AA_CHARGE ? 0.2f : 1.0f;
- AttackedEntity tentity = GetEntityToAttack(*troll);
- if (tentity.type > NONE || troll->anim_attack_state >= AA_CHARGE)
- {
- bool entity_hit = TrollAttackTarget(troll, tentity);
- if (entity_hit)
- {
- switch (tentity.type)
- {
- case (PLAYER):
- {
- mega_state.player.anim_hit_state = HA_PLAY;
- mega_state.player.t_anim_hit_start = GetTime();
- mega_state.player.move_dir = troll->move_dir;
- mega_state.player.state = P_HIT; // disable walk check, stuff been thrown off
- mega_state.player.health -= 8;
- } break;
- case (TROLL):
- {
- // trigger troll get hit animation
- } break;
- case (BANDIT):
- {
- // trigger bandit get hit animation
- AggroEntity attacker = {.type=TROLL, .id=0};
- mega_state.bandits[tentity.id].attackers[0] = attacker;
- mega_state.bandits[tentity.id].anim_hit_state = HA_PLAY;
- mega_state.bandits[tentity.id].t_anim_hit_start = GetTime();
- mega_state.bandits[tentity.id].move_dir = troll->move_dir;
- mega_state.bandits[tentity.id].state = C_HIT;
- mega_state.bandits[tentity.id].health -= 10;
- } break;
- default:
- // do nothing
- }
- }
- }
- else
- {
- // get entity to follow
- FriendEntity follow = {};
- if (troll->friends[0].type == PLAYER)
- {
- float char_dist = Vector2Distance(mega_state.player.position, troll->position);
- if (char_dist < 200)
- {
- follow.type = PLAYER;
- }
- }
- if (troll->state == C_IDLE && troll->ai_state == AI_NONE)
- {
- troll->t_idle_start = GetTime();
- troll->move_dir = Vector2Zero();
- troll->ai_state = AI_IDLE;
- troll->to_core_pos = troll->to_core_pos == true ? false: true;
- }
- double idle_time = GetTime() - troll->t_idle_start;
- if (idle_time >= troll->t_idle_duration && troll->ai_state == AI_IDLE)
- {
- if (troll->to_core_pos == false)
- {
- // calculate target position from patrol direction
- float max_dist = 200.0f;
- Vector2 move_dir;
- switch(troll->patrol_dir)
- {
- case (PATROL_TOP):
- {
- move_dir = (Vector2){.x=0.0f, .y=-1.0f};
- } break;
- case (PATROL_LEFT):
- {
- move_dir = (Vector2){.x=-1.0f, .y=0.0f};
- } break;
- case (PATROL_DOWN):
- {
- move_dir = (Vector2){.x=0.0f, .y=1.0f};
- } break;
- case (PATROL_RIGHT):
- {
- move_dir = (Vector2){.x=1.0f, .y=0.0f};
- } break;
- };
- troll->move_dir = move_dir;
- troll->target_position = Vector2Add(troll->position, Vector2Scale(troll->move_dir, max_dist));
- }
- else
- {
- troll->target_position = troll->core_position;
- troll->move_dir = Vector2Normalize(Vector2Subtract(troll->target_position, troll->position));
- }
- troll->state = C_PATROL;
- troll->ai_state = AI_PATROL;
- }
- // follow player / friend
- if (follow.type == PLAYER)
- {
- troll->state = C_FOLLOW;
- troll->ai_state = AI_NONE;
- troll->target_position = mega_state.player.position;
- troll->move_dir = Vector2Normalize(Vector2Subtract(troll->target_position, troll->position));
- }
- float dist_to_target = Vector2Distance(troll->target_position, troll->position);
- if (dist_to_target > 50.0f)
- {
- MoveCharacter(troll, Vector2Scale(troll->move_dir, troll->move_speed));
- }
- else if (troll->state == C_PATROL && troll->ai_state == AI_PATROL)
- {
- // we have reached target position
- // in case we were patrolling, increment the direction to move to
- // @note: maybe do this when first changing state from idle after character has been idle for hours
- if (troll->to_core_pos == false)
- {
- troll->patrol_dir = (troll->patrol_dir + 1)%PATROL_END;
- }
- troll->state = C_IDLE;
- troll->ai_state = AI_NONE;
- }
- CenterRectAroundTL(&troll->render_rect, troll->position);
- }
- }
- }
- // ========== BANDIT DETECTION AND STUFF
- for (int i=0;i<mega_state.bandit_arr_sz;i++)
- {
- Bandit *bandit = &mega_state.bandits[i];
- if (bandit->state == C_HIT)
- {
- float anim_length = GetTime() - bandit->t_anim_hit_start;
- float ft = GetFrameTime();
- float pixel_per_second_per_ft = ft*bandit->anim_hit_speed/bandit->t_anim_hit_duration;
- bandit->position = Vector2Add(bandit->position, Vector2Scale(bandit->move_dir, pixel_per_second_per_ft));
- bandit->tint_color = (Color){255, 128, 128, 255};
- if (anim_length >= bandit->t_anim_hit_duration)
- {
- bandit->state = P_IDLE;
- bandit->anim_hit_state = HA_IDLE;
- bandit->tint_color = (Color){255, 255, 255, 255};
- }
- // calculate center positions
- CenterRectAroundTL(&bandit->render_rect, bandit->position);
- bandit->tile_id = GetTileIDFromWorld(bandit->position);
- }
- else if (bandit->state != C_DEAD)
- {
- if (bandit->isburning == true)
- {
- int anim_length_ms = 1000*(int)(GetTime() - bandit->t_anim_burn_start);
- if (anim_length_ms%500 == 0 && anim_length_ms > 0)
- {
- // decrement health every 500ms
- bandit->health -= 8;
- bandit->t_anim_burn_start = GetTime();
- }
- }
- bandit->speed_multiplier *= bandit->anim_attack_state == AA_CHARGE ? 0.2f : 1.0f;
- AttackedEntity tentity = GetEntityToAttack(*bandit);
- if (tentity.type > NONE || bandit->anim_attack_state >= AA_CHARGE)
- {
- bool entity_hit = BanditAttackTarget(bandit, tentity);
- if (tentity.type > NONE)
- {
- if (entity_hit)
- {
- switch (tentity.type)
- {
- case (PLAYER):
- {
- mega_state.player.anim_hit_state = HA_PLAY;
- mega_state.player.t_anim_hit_start = GetTime();
- mega_state.player.move_dir = bandit->move_dir;
- mega_state.player.state = P_HIT; // disable walk check, stuff been thrown off
- mega_state.player.health -= 5;
- } break;
- case (TROLL):
- {
- // trigger troll get hit animation
- AggroEntity attacker = {.type=BANDIT, .id=0};
- mega_state.trolls[tentity.id].attackers[0] = attacker;
- mega_state.trolls[tentity.id].anim_hit_state = HA_PLAY;
- mega_state.trolls[tentity.id].t_anim_hit_start = GetTime();
- mega_state.trolls[tentity.id].move_dir = bandit->move_dir;
- mega_state.trolls[tentity.id].state = C_HIT;
- mega_state.trolls[tentity.id].health -= 5;
- } break;
- case (BANDIT):
- {
- // trigger bandit get hit animation
- } break;
- default:
- // do nothing
- }
- }
- }
- }
- else
- {
- if (bandit->state == C_IDLE && bandit->ai_state == AI_NONE)
- {
- bandit->t_idle_start = GetTime();
- bandit->move_dir = Vector2Zero();
- bandit->ai_state = AI_IDLE;
- bandit->to_core_pos = bandit->to_core_pos == true ? false: true;
- }
- double idle_time = GetTime() - bandit->t_idle_start;
- if (idle_time >= bandit->t_idle_duration && bandit->ai_state == AI_IDLE)
- {
- if (bandit->to_core_pos == false)
- {
- // calculate target position from patrol direction
- float max_dist = 200.0f;
- Vector2 move_dir;
- switch(bandit->patrol_dir)
- {
- case (PATROL_TOP):
- {
- move_dir = (Vector2){.x=0.0f, .y=-1.0f};
- } break;
- case (PATROL_LEFT):
- {
- move_dir = (Vector2){.x=-1.0f, .y=0.0f};
- } break;
- case (PATROL_DOWN):
- {
- move_dir = (Vector2){.x=0.0f, .y=1.0f};
- } break;
- case (PATROL_RIGHT):
- {
- move_dir = (Vector2){.x=1.0f, .y=0.0f};
- } break;
- };
- bandit->move_dir = move_dir;
- bandit->target_position = Vector2Add(bandit->position, Vector2Scale(bandit->move_dir, max_dist));
- }
- else
- {
- bandit->target_position = bandit->core_position;
- bandit->move_dir = Vector2Normalize(Vector2Subtract(bandit->target_position, bandit->position));
- }
- bandit->state = C_PATROL;
- bandit->ai_state = AI_PATROL;
- }
- // get entity to follow
- FriendEntity follow = {};
- if (bandit->friends[0].type == PLAYER)
- {
- float char_dist = Vector2Distance(mega_state.player.position, bandit->position);
- if (char_dist < 200)
- {
- follow.type = PLAYER;
- }
- }
- // follow player / friend
- if (follow.type == PLAYER)
- {
- bandit->target_position = mega_state.player.position;
- bandit->state = C_FOLLOW;
- bandit->ai_state = AI_NONE;
- bandit->move_dir = Vector2Normalize(Vector2Subtract(bandit->target_position, bandit->position));
- }
- float dist_to_target = Vector2Distance(bandit->target_position, bandit->position);
- if (dist_to_target > 50.0f)
- {
- MoveCharacter(bandit, Vector2Scale(bandit->move_dir, bandit->move_speed));
- }
- else if (bandit->state == C_PATROL && bandit->ai_state == AI_PATROL)
- {
- if (bandit->to_core_pos == false)
- {
- bandit->patrol_dir = (bandit->patrol_dir + 1)%PATROL_END;
- }
- bandit->state = C_IDLE;
- bandit->ai_state = AI_NONE;
- }
- CenterRectAroundTL(&bandit->render_rect, bandit->position);
-
- }
- }
- }
-
- // RENDERING
- BeginDrawing();
- ClearBackground(RAYWHITE);
- DrawMapFloorTiles();
- DrawFloorCoverTiles();
- DrawCharacters();
-
- // do text rendering at the end
- // draw mouse position for debugging
- if (mega_state.player.state == P_HIT)
- {
- DrawText("player hit", 500, 20, 20, GREEN);
- }
- DrawText(TextFormat("Keys: %d/2", mega_state.key_picked_count), 1100, 20, 20, GREEN);
- EndDrawing();
- }
- else if (mega_state.gameplay_state == GS_UI)
- {
- BeginDrawing();
- ClearBackground(BLACK);
- DrawText("Blaidville", screenWidth/2 - 100, 40, 28, WHITE);
- DrawText("Instructions", screenWidth/2 - 140, 100, 22, WHITE);
- DrawText("Find keys to unlock the gate", screenWidth/2 - 140, 140, 18, WHITE);
- DrawText("Unlock the gate to escape", screenWidth/2 - 140, 160, 18, WHITE);
- DrawText("Controls", screenWidth/2 - 140, 220, 22, WHITE);
- DrawText("1 -> Potion 1", screenWidth/2 - 140, 260, 18, WHITE);
- DrawText("2 -> Potion 2", screenWidth/2 - 140, 280, 18, WHITE);
- DrawText("right mouse click -> throw potion", screenWidth/2 - 140, 300, 18, WHITE);
- DrawText("left mouse click -> move", screenWidth/2 - 140, 320, 18, WHITE);
- DrawText("Escape to play or pause the game", screenWidth/2 - 140, 340, 18, WHITE);
- DrawText("Restart the game to reset state", screenWidth/2 - 140, 360, 18, WHITE);
- EndDrawing();
- }
- else if (mega_state.gameplay_state == GS_SUCCESS)
- {
- BeginDrawing();
- ClearBackground(BLACK);
- DrawText("Objective Complete", screenWidth/2 - 100, 40, 28, GREEN);
- EndDrawing();
- }
- else if (mega_state.gameplay_state == GS_OVER)
- {
- BeginDrawing();
- ClearBackground(BLACK);
- DrawText("You Died", screenWidth/2 - 100, 40, 28, RED);
- EndDrawing();
- }
-}
-