diff options
Diffstat (limited to 'src/game.c')
-rw-r--r-- | src/game.c | 1566 |
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(); - } -} - |