NEWS: Welcome to my new homepage! <3

enemy.c - freezo - A retro platform game

freezo

A retro platform game
git clone git://192.168.2.2/freezo
Log | Files | Refs | README

enemy.c (6865B)


      1 #include <stdlib.h>
      2 #include <math.h>
      3 
      4 #include "enemy.h"
      5 #include "const.h"
      6 #include "entity.h"
      7 #include "effect.h"
      8 
      9 enemy_t *enemy_create(pos_t pos, enemy_e type) {
     10   enemy_t *enemy = malloc(sizeof(enemy_t));
     11   enemy->pos = pos;
     12   enemy->type = type;
     13   enemy->on_ground = false;
     14   enemy->velocity = 0.0;
     15   enemy->gravity = 0.0;
     16   enemy->dir = 1;
     17   enemy->stunned = false;
     18   enemy->frozen = false;
     19   enemy->frozen_timer = 0;
     20   enemy->fall_height = 0.0;
     21   enemy->timer_walking = timer_create(9, 8);
     22   enemy->timer_sneaking = timer_create(9, 16);
     23   return enemy;
     24 }
     25 
     26 void enemy_update(enemy_t *enemy, game_t *game) {
     27   enemy->stunned = false;
     28   bool on_ground = false;
     29   // not beeing held
     30   if (game->player->held_enemy != enemy) {
     31     // detect on ground
     32     if (!(enemy->velocity > 0.0)) {
     33       for (int i = 0; i < game->tiles_len; i++) {
     34         tile_t *tile = game->tiles[i];
     35         if (tile_ground(tile)) {
     36           if (
     37             enemy->pos.x + PLAYER_WIDTH > tile->pos.x &&
     38             enemy->pos.x < tile->pos.x + TILE_WIDTH
     39           ) {
     40             float tolerance = 4.0;
     41             if (enemy->gravity > tolerance) {
     42               tolerance = enemy->gravity;
     43             }
     44             if (fabs(enemy->pos.y + PLAYER_HEIGHT - tile->pos.y) < tolerance) {
     45               enemy->pos.y = tile->pos.y - PLAYER_HEIGHT;
     46               on_ground = true;
     47               if (enemy->fall_height >= 2 * TILE_HEIGHT) {
     48                 effect_play(enemy->pos, EFFECT_BREAK, game);
     49                 effect_play(enemy->pos, EFFECT_PARTICLE, game);
     50                 enemy_kill(enemy, game);
     51               }
     52             }
     53           }
     54         }
     55       }
     56     }
     57     enemy->on_ground = on_ground;
     58     if (enemy->on_ground) {
     59       enemy->gravity = 0.0;
     60       enemy->fall_height = 0.0;
     61     }
     62     else {
     63       enemy->pos.y += enemy->gravity;
     64       enemy->fall_height += enemy->gravity;
     65       if (enemy->gravity < PLAYER_GRAVITY) {
     66         enemy->gravity += 0.2;
     67       }
     68       else {
     69         enemy->gravity = PLAYER_GRAVITY;
     70       }
     71     }
     72     // handle shooting
     73     if (
     74       game->player->shooting &&
     75       game->player->target_entity != NULL &&
     76       game->player->target_entity->type == ENTITY_ENEMY &&
     77       game->player->target_entity->enemy == enemy
     78     ) {
     79       if (enemy->frozen) {
     80         if (game->player->dir > 0) {
     81           enemy->pos.x += 2.0;
     82         }
     83         else {
     84           enemy->pos.x -= 2.0;
     85         }
     86       }
     87       else {
     88         enemy->stunned = true;
     89       }
     90     }
     91   }
     92   // handle freezing
     93   if (!enemy->frozen) {
     94     if (enemy->stunned) {
     95       if (enemy->frozen_timer >= 100) {
     96         enemy->frozen = true;
     97         enemy->frozen_timer = 0;
     98       }
     99       enemy->frozen_timer++;
    100     }
    101     else if (enemy->frozen_timer > 0) {
    102       enemy->frozen_timer--;
    103     }
    104   }
    105   else {
    106     if (enemy->frozen_timer >= 1500) {
    107       enemy->frozen = false;
    108       enemy->frozen_timer = 0;
    109       if (game->player->held_enemy == enemy) {
    110         game->player->held_enemy = NULL;
    111       }
    112     }
    113     enemy->frozen_timer++;
    114   }
    115   // handle movement
    116   tile_t *next_ground_tile = tile_get(game, enemy->pos.x + ENEMY_WIDTH / 2.0 + enemy->dir * ENEMY_WIDTH / 2.0, enemy->pos.y + ENEMY_HEIGHT + 1);
    117   if (!enemy->frozen) {
    118     if (enemy->on_ground && (next_ground_tile == NULL || next_ground_tile->type == TILE_AIR)) {
    119       enemy->dir = -enemy->dir;
    120     }
    121     if (enemy->stunned) {
    122       enemy->pos.x += enemy->dir * 0.1;
    123     }
    124     else {
    125       enemy->pos.x += enemy->dir * 0.5;
    126     }
    127   }
    128   // detect wall
    129   for (int i = 0; i < game->tiles_len; i++) {
    130     tile_t *tile = game->tiles[i];
    131     if (tile_wall(tile)) {
    132       if (
    133         enemy->pos.y + ENEMY_HEIGHT > tile->pos.y &&
    134         enemy->pos.y < tile->pos.y + TILE_HEIGHT
    135       ) {
    136         float tolerance = 4.0;
    137         if (enemy->dir > 0) {
    138           if (fabs((enemy->pos.x + ENEMY_WIDTH - 0.4 * TILE_WIDTH) - tile->pos.x) < tolerance) {
    139             enemy->dir = -enemy->dir;
    140           }
    141         }
    142         else {
    143           if (fabs((enemy->pos.x + 0.4 * TILE_WIDTH) - (tile->pos.x + TILE_WIDTH)) < tolerance) {
    144             enemy->dir = -enemy->dir;
    145           }
    146         }
    147       }
    148     }
    149   }
    150   // fall out of map
    151   if (enemy->pos.y > TILE_HEIGHT * game->level->height) {
    152     pos_t pos = { enemy->pos.x, enemy->pos.y - ENEMY_HEIGHT + ENEMY_HEIGHT / 3.0 };
    153     effect_play(pos, EFFECT_PARTICLE, game);
    154     enemy_kill(enemy, game);
    155   }
    156   // update timer
    157   if (enemy->on_ground && !enemy->frozen) {
    158     timer_update(enemy->timer_walking);
    159     timer_update(enemy->timer_sneaking);
    160   }
    161   else {
    162     timer_reset(enemy->timer_walking);
    163     timer_reset(enemy->timer_sneaking);
    164   }
    165 }
    166 
    167 void enemy_draw(enemy_t *enemy, game_t *game) {
    168   pos_t pos = pos_snap(enemy->pos);
    169   int frame_walking = timer_get(enemy->timer_walking);
    170   int frame_sneaking = timer_get(enemy->timer_sneaking);
    171   if (enemy->dir > 0) {
    172     DrawTextureRec(game->assets.entities, texture_rect(enemy->stunned ? frame_sneaking : frame_walking, 8, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    173   }
    174   else {
    175     DrawTextureRec(game->assets.entities, texture_rect(enemy->stunned ? frame_sneaking : frame_walking, 9, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    176   }
    177   if (enemy->frozen) {
    178     if (enemy->frozen_timer <= 1200) {
    179       DrawTextureRec(game->assets.entities, texture_rect(3, 2, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    180     }
    181     else if (enemy->frozen_timer <= 1350) {
    182       DrawTextureRec(game->assets.entities, texture_rect(4, 2, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    183     }
    184     else if (enemy->frozen_timer <= 1450) {
    185       DrawTextureRec(game->assets.entities, texture_rect(5, 2, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    186     }
    187     else {
    188       DrawTextureRec(game->assets.entities, texture_rect(6, 2, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    189     }
    190   }
    191   else if (enemy->stunned) {
    192     if (enemy->frozen_timer <= 33) {
    193       DrawTextureRec(game->assets.entities, texture_rect(0, 2, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    194     }
    195     else if (enemy->frozen_timer <= 66) {
    196       DrawTextureRec(game->assets.entities, texture_rect(1, 2, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    197     }
    198     else {
    199       DrawTextureRec(game->assets.entities, texture_rect(2, 2, PLAYER_WIDTH, PLAYER_HEIGHT), pos, WHITE);
    200     }
    201   }
    202 }
    203 
    204 void enemy_kill(enemy_t *enemy, game_t *game) {
    205   for (int i = 0; i < game->entities_len; i++) {
    206     if (game->entities[i].type == ENTITY_ENEMY && game->entities[i].enemy == enemy) {
    207       if (i + 1 < game->entities_len) {
    208         for (int j = i; j < game->entities_len - 1; j++) {
    209           game->entities[j] = game->entities[j + 1];
    210         }
    211       }
    212       game->entities_len--;
    213       game->entities = realloc(game->entities, sizeof(entity_t) * game->entities_len);
    214       game->xp += 10;
    215       break;
    216     }
    217   }
    218 }
    219 
    220 void enemy_free(enemy_t *enemy) {
    221   timer_free(enemy->timer_walking);
    222   timer_free(enemy->timer_sneaking);
    223   free(enemy);
    224 }