diff options
-rw-r--r-- | src/demo.c | 4 | ||||
-rw-r--r-- | src/engine/bullet.c | 40 | ||||
-rw-r--r-- | src/engine/enemy.c | 10 | ||||
-rw-r--r-- | src/engine/enemy.h | 5 | ||||
-rw-r--r-- | src/engine/enemy_ai.c | 99 | ||||
-rw-r--r-- | src/engine/enemy_ai.h | 10 | ||||
-rw-r--r-- | src/engine/entity.c | 31 | ||||
-rw-r--r-- | src/engine/entity.h | 5 | ||||
-rw-r--r-- | src/engine/level_const.c | 2 | ||||
-rw-r--r-- | src/engine/player_controller.c | 2 | ||||
-rw-r--r-- | src/engine/types.h | 4 | ||||
-rw-r--r-- | src/game_loop/gameplay.c | 45 | ||||
-rw-r--r-- | src/game_loop/gameplay.h | 3 | ||||
-rw-r--r-- | src/game_loop/starting_screen.c | 1 | ||||
-rw-r--r-- | src/makefile | 1 |
15 files changed, 230 insertions, 32 deletions
@@ -65,14 +65,16 @@ void hh_demo_loop(unsigned long frame) { hh_gameplay(&hh_game, &hh_game_states); break; case hh_e_state_game_over: - // todo: + // TODO: // function: show game over screen // function: after time goto high score + hh_game_states = hh_e_state_high_score; break; case hh_e_state_high_score: // todo: // fucntion: show all previously scored points // function: button pressed goto starting screen + hh_game_states = hh_e_state_starting_screen; break; default: hh_game_states = hh_e_state_starting_screen; diff --git a/src/engine/bullet.c b/src/engine/bullet.c index 55b20cc..eb9a8bb 100644 --- a/src/engine/bullet.c +++ b/src/engine/bullet.c @@ -42,12 +42,47 @@ bool rising_edge(bool signal, bool* prev) { return edge; } bool prev_signal = false; +void hh_handle_bullet_direction(hh_entity* bullet){ + bullet->vel = (vec2){0,0}; + if (g_hh_controller_p1.dpad_left) { + if (g_hh_controller_p1.dpad_up) { + bullet->vel.x = -1; + bullet->vel.y = -1; + } else if (g_hh_controller_p1.dpad_down) { + bullet->vel.x = -1; + bullet->vel.y = 1; + } else { + bullet->vel.x = -1; + } + }else if (g_hh_controller_p1.dpad_right) { + if (g_hh_controller_p1.dpad_up) { + bullet->vel.x = 1; + bullet->vel.y = -1; + } else if (g_hh_controller_p1.dpad_down) { + bullet->vel.x = 1; + bullet->vel.y = 1; + } else { + bullet->vel.x = 1; + } + } else if (g_hh_controller_p1.dpad_up){ + bullet->vel.y = -1; + } else if (g_hh_controller_p1.dpad_down){ + bullet->vel.y = 1; + } + else{ + bullet->vel.x = 1; + } + bullet->render.fam.horizontal_flip = (bullet->vel.x < 0); + bullet->render.fam.vertical_flip = (bullet->vel.y != 0); + +} void hh_shoot_bullet(vec2 player, hh_entity* bullet){ vec2 temp; if(rising_edge(g_hh_controller_p1.button_secondary,&prev_signal) && bullet->is_grounded){ bullet->is_grounded=false; bullet->pos = player; current_bullet = (current_bullet + 1) % bullets_size; + hh_handle_bullet_direction(bullet); } } @@ -55,11 +90,10 @@ void hh_shoot_bullet(vec2 player, hh_entity* bullet){ void hh_update_bullet(hh_entity* bullet){ if(hh_background_collision_bulllet(*bullet)){ hh_bullet_death(bullet); - - // printf("x %d y %d\n",(bullet->pos.x-cam_pos.x),(bullet->pos.y-cam_pos.y)); } else{ - bullet->pos.x += bullet->speed; + bullet->pos.x = bullet->pos.x + bullet->vel.x * bullet->speed; + bullet->pos.y = bullet->pos.y + bullet->vel.y * bullet->speed; } } diff --git a/src/engine/enemy.c b/src/engine/enemy.c index 186cfa0..4ed48a2 100644 --- a/src/engine/enemy.c +++ b/src/engine/enemy.c @@ -1,14 +1,9 @@ #include "engine/enemy.h" -void hh_update_enemy(hh_entity* enemy, vec_cor cam_pos){ - //Bjorn functions - -} - -void hh_multiple_enemies( vec_cor cam_pos, hh_entity* enemies, int total_enemies){ +void hh_multiple_enemies(hh_entity* enemies, hh_entity player, vec_cor cam_pos, int total_enemies){ for(int i=0; i < total_enemies;i++){ - hh_update_enemy(&enemies[i] , cam_pos); + hh_update_enemy(&enemies[i] , player, cam_pos); } } @@ -22,6 +17,7 @@ void hh_enemy_death_check(hh_entity* enemy){ enemy->hp--; } } + void hh_solve_hitted_enemies(hh_entity* enemies, int total_enemies){ for(int i = 0; i < total_enemies; i++){ if(enemies[i].is_hit){ diff --git a/src/engine/enemy.h b/src/engine/enemy.h index 80498f5..c8a3f20 100644 --- a/src/engine/enemy.h +++ b/src/engine/enemy.h @@ -1,14 +1,13 @@ #pragma once #include "player_controller.h" #include "engine/sprite_controller.h" +#include "engine/enemy_ai.h" #include "types.h" #include "input.h" -/** @brief updates a single enemy locations TODO: Bjorn sets functions in here*/ -void hh_update_enemy(hh_entity* , vec_cor ); /** @brief calculates all the given enemies positions*/ -void hh_multiple_enemies( vec_cor cam_pos, hh_entity* enemies, int total_enemies); +void hh_multiple_enemies(hh_entity* enemies, hh_entity player, vec_cor cam_pos, int total_enemies); /** @brief checks if the enemy has zero hp else it takes hp from the enemy */ void hh_enemy_death_check(hh_entity* enemy); diff --git a/src/engine/enemy_ai.c b/src/engine/enemy_ai.c new file mode 100644 index 0000000..81d04d9 --- /dev/null +++ b/src/engine/enemy_ai.c @@ -0,0 +1,99 @@ +#include "engine/enemy_ai.h" + +int8_t hh_get_direction(int32_t player_x, int32_t enemy_x){ + int movement_direction = player_x - enemy_x; // = player.pos.x - player.prev_pos.x; + if (movement_direction > 0) { + return 1; // move in positive direction + } else if (movement_direction < 0) { + return -1; // move in negative direction + } else { + return 0; // don't move + } +} +void hh_update_enemy_movement(hh_entity* enemy){ + hh_entity enemy_new = {0}; + enemy_new = *enemy; + enemy_new.vel = (vec2){ + .x = enemy->vel.x, + .y = enemy->vel.y, + }; + + enemy_new.pos = (vec2){ + .x = enemy->pos.x + enemy_new.vel.x, + .y = enemy->pos.y + enemy_new.vel.y, + }; + + + *enemy = hh_background_collision ( *enemy, enemy_new); +} +void hh_slime_ai(hh_entity* enemy, hh_entity player){ + int8_t direction = hh_get_direction(player.pos.x, enemy->pos.x); + if((player.pos.x - enemy->pos.x) >= -hunt_player && (player.pos.x - enemy->pos.x) <= hunt_player){ + hh_movement_entity(enemy, direction); + } + hh_gravity_entity(enemy); + hh_update_enemy_movement(enemy); + +} + +void hh_jump_slime_ai(hh_entity* enemy, hh_entity player){ + int8_t direction = hh_get_direction(player.pos.x, enemy->pos.x); + hh_gravity_entity(enemy); + if((player.pos.x - enemy->pos.x) >= -hunt_player && (player.pos.x - enemy->pos.x) <= hunt_player){ + hh_movement_entity(enemy, direction); + // TODO: fix this if statement and make it cleaner. this makes the enemy jump when the player mets the condition + if((player.pos.y - enemy->pos.y) < -16 && (player.pos.y - enemy->pos.y) >= -100 && (player.pos.x - enemy->pos.x) >= -10 && (player.pos.x - enemy->pos.x) <= 10){ + hh_jump_entity(enemy); + } + } + + hh_update_enemy_movement(enemy); + +} +#define terror_owl_attack_timer 100 +#define terror_owl_follow_player_delay 5 +#define terror_owl_attack_player_delay 12 +#define terror_owl_dive_speed 3 +#define delay_frames 2 +#define terror_owl_minimal_distance_from_player 100 +void hh_terror_owl_ai(hh_entity* enemy, hh_entity player){ + static int count=0; + static int last_y_location=0; + + if (count < terror_owl_attack_timer) { + // Move towards player position smoothly + int delta_x = (-50 + player.pos.x - enemy->pos.x) / terror_owl_follow_player_delay; + enemy->pos.x += delta_x; + enemy->pos.y = player.pos.y - terror_owl_minimal_distance_from_player; + + count++; + last_y_location=player.pos.y; + } else { + if(enemy->pos.y <= last_y_location){ + int delta_x = (player.pos.x - enemy->pos.x) / terror_owl_attack_player_delay; + enemy->pos.x += delta_x; + enemy->pos.y += terror_owl_dive_speed; + } + else{ + count = 0; + } + } + +} +void hh_update_enemy(hh_entity* enemy , hh_entity player, vec_cor cam_pos){ + // static hh_e_entity_type type; + switch (enemy->object_type) + { + case slime: + hh_slime_ai(enemy,player); + break; + case jumping_slime: + hh_jump_slime_ai(enemy,player); + break; + case terror_owl: + hh_terror_owl_ai(enemy,player); + break; + default: + break; + } +} diff --git a/src/engine/enemy_ai.h b/src/engine/enemy_ai.h new file mode 100644 index 0000000..d68f50f --- /dev/null +++ b/src/engine/enemy_ai.h @@ -0,0 +1,10 @@ +#pragma once +#include "player_controller.h" +#include "engine/sprite_controller.h" +#include "types.h" +#include "input.h" +#include <math.h> + + +#define hunt_player 100 +void hh_update_enemy(hh_entity* enemy , hh_entity player, vec_cor cam_pos); diff --git a/src/engine/entity.c b/src/engine/entity.c index 1cb88be..eba6481 100644 --- a/src/engine/entity.c +++ b/src/engine/entity.c @@ -43,6 +43,7 @@ void hh_solve_collision(vec2 pos_environment, hh_entity* entity){ // entity->vel.x = 0; // } } + hh_entity hh_background_collision (hh_entity temp_old_entity,hh_entity temp_new_entity){ temp_new_entity.is_grounded = false; @@ -119,6 +120,7 @@ bool hh_background_collision_bulllet (hh_entity temp_old_entity){ // temp_old_entity.vel = temp_new_entity.vel; return false; } + hh_entity hh_enemy_collision(hh_entity temp_player, hh_entity temp_enemy){ bool collide = hh_distance_circles( temp_player.pos, temp_enemy.pos, temp_player.radius, temp_enemy.radius); @@ -138,7 +140,7 @@ hh_entity hh_enemy_collision(hh_entity temp_player, hh_entity temp_enemy){ temp_player.vel.x = 8; } // ghost mode / invulnerable or other things on hit - // temp_player.hp--; + temp_player.hp--; } else { temp_player.is_hit = false; @@ -170,14 +172,35 @@ void hh_jump_entity(hh_entity* object_1){ } } void hh_gravity_entity(hh_entity* object_1){ - if (object_1->is_grounded == false && object_1->vel.y < 6) { + if (object_1->is_grounded == false) { object_1->vel.y += 1; //gravity } } -void hh_hit_entity(hh_entity* object_1, int8_t* hit_timer, int8_t* direction){ + +void hh_movement_entity(hh_entity* object_1, int8_t* direction){ + if(direction != 0){ + if(object_1->vel.x > -1 * object_1->speed && object_1->vel.x < object_1->speed) { + object_1->vel.x = object_1->vel.x + direction; + } else { + if (object_1->vel.x > 0) { + object_1->vel.x--; + } else if(object_1->vel.x < 0) { + object_1->vel.x++; + } + } + } else { + if (object_1->vel.x > 0) { + object_1->vel.x--; + } else if(object_1->vel.x < 0) { + object_1->vel.x++; + } + } + +} +void hh_player_move_hit(hh_entity* object_1, int8_t* hit_timer, int8_t* direction){ if(object_1->is_hit == true){ hit_timer = 9; - object_1->is_hit = false; + //object_1->is_hit = false; } if(hit_timer > -10){ hit_timer--; diff --git a/src/engine/entity.h b/src/engine/entity.h index fde9341..fb1c905 100644 --- a/src/engine/entity.h +++ b/src/engine/entity.h @@ -51,9 +51,12 @@ void hh_jump_entity(hh_entity* ); /** @brief looks if the player is grounded and if not it sets the position down */ void hh_gravity_entity(hh_entity* ); /** @brief if object is hit bounches in specific direction and moves the object */ -void hh_hit_entity(hh_entity* object_1, int8_t* hit_timer, int8_t* direction); +void hh_player_move_hit(hh_entity* object_1, int8_t* hit_timer, int8_t* direction); + +void hh_movement_entity(hh_entity* object_1, int8_t* direction); /** @brief specific bullet background collisions detection */ bool hh_background_collision_bulllet (hh_entity temp_old_entity); /** @brief checks any entity has a hit on each othe*/ void hh_check_all_collisions(hh_entity* player, hh_entity* enemies, int total_enemies, hh_entity* bullets, int total_bullets, vec_cor cam_pos); + diff --git a/src/engine/level_const.c b/src/engine/level_const.c index 642a474..5d5f5e0 100644 --- a/src/engine/level_const.c +++ b/src/engine/level_const.c @@ -4,7 +4,7 @@ hh_g_all_levels hh_init_game_levels(){ hh_g_all_levels levels; - levels.current_level=0; + levels.current_level=1; levels.level[0].size.x=40; levels.level[0].size.y=15; diff --git a/src/engine/player_controller.c b/src/engine/player_controller.c index 6400b02..0148792 100644 --- a/src/engine/player_controller.c +++ b/src/engine/player_controller.c @@ -18,7 +18,7 @@ void hh_player_actions(hh_entity* player){ int8_t direction_x = (-1 * g_hh_controller_p1.dpad_left) + (1 * g_hh_controller_p1.dpad_right); int8_t direction_y = (-1 * g_hh_controller_p1.dpad_up) + (1 * g_hh_controller_p1.dpad_down); - hh_hit_entity(player,hit_timer,direction_x); + hh_player_move_hit(player,hit_timer,direction_x); hh_gravity_entity(player); if(g_hh_controller_p1.button_primary){ hh_jump_entity(player); diff --git a/src/engine/types.h b/src/engine/types.h index 00b381b..8040e46 100644 --- a/src/engine/types.h +++ b/src/engine/types.h @@ -4,6 +4,9 @@ typedef uint8_t hh_ppu_fg_idx; // typedef uint16_t hh_bg_idx; +typedef enum { + slime, jumping_slime, terror_owl, +}hh_e_all_objects_game_type; typedef enum { fire, ice, poison @@ -31,6 +34,7 @@ typedef struct { vec2 pos, vel, size; bool is_grounded; bool is_hit; + hh_e_all_objects_game_type object_type; uint8_t radius; int8_t hp; int8_t speed; diff --git a/src/game_loop/gameplay.c b/src/game_loop/gameplay.c index 2950870..a7ce5b6 100644 --- a/src/game_loop/gameplay.c +++ b/src/game_loop/gameplay.c @@ -12,7 +12,7 @@ void hh_gameplay(hh_g_all_levels* game, hh_e_game_state* hh_game_state){ .speed = 6, .is_grounded = false, .is_hit = false, - .radius = 8, + .radius = 16, .pos = (vec2){32,32}, .size = (vec2){32,32}, .vel = (vec2){0,0}, @@ -29,12 +29,13 @@ void hh_gameplay(hh_g_all_levels* game, hh_e_game_state* hh_game_state){ }; // enemy gets replaced here is just for reference static hh_entity enemy={ + .object_type = jumping_slime, .hp = 4, - .speed = 6, + .speed = 2, .is_grounded = false, .is_hit = false, .radius = 8, - .pos = (vec2){128,24}, + .pos = (vec2){200,200}, .size = (vec2){16,16}, .vel = (vec2){0,0}, // .vec = (vec2){0,0}, @@ -53,19 +54,17 @@ void hh_gameplay(hh_g_all_levels* game, hh_e_game_state* hh_game_state){ switch (gameplay) { case hh_e_setup_screen: - printf("%d\n",game->current_level); bullets = hh_init_bullets(total_bullets); hh_setup_screen(game->level[game->current_level]); gameplay = hh_e_play_level; - enemy.hp=4; break; case hh_e_play_level: - // TODO: here come all the different functions for the gameplay - vec_cor cam_pos;//value in tiles + + vec_cor cam_pos; cam_pos = hh_draw_screen(player1.pos); hh_player_actions(&player1); hh_multiple_bullets(player1.pos,bullets); - hh_multiple_enemies(cam_pos, &enemy,1); + hh_multiple_enemies(&enemy, player1, cam_pos, 1); hh_check_all_collisions(&player1,&enemy,1,bullets,total_bullets,cam_pos); hh_solve_hitted_enemies(&enemy,1); hh_render_all_entities(&player1,bullets,&enemy,total_bullets,1, cam_pos); @@ -75,19 +74,24 @@ void hh_gameplay(hh_g_all_levels* game, hh_e_game_state* hh_game_state){ if(game->level[game->current_level].hh_level_completed){ gameplay = hh_e_level_complete; } + else if(player1.hp == 0){ + gameplay = hh_e_game_over; + } break; case hh_e_level_complete: + // TODO: from complete to shop or game_over if(game->current_level < 3){ game->current_level+=1; gameplay = hh_e_setup_screen; } else { + gameplay = hh_e_game_over; } break; case hh_e_game_over: // todo make reset levels - hh_reset_levels(); + hh_reset_levels(&player1); gameplay = hh_e_setup_screen; *hh_game_state = hh_e_state_game_over; break; @@ -96,7 +100,28 @@ void hh_gameplay(hh_g_all_levels* game, hh_e_game_state* hh_game_state){ } } -void hh_reset_levels(){} +void hh_reset_levels(hh_entity* player){ + *player = (hh_entity){ + .hp = 4, + .speed = 6, + .is_grounded = false, + .is_hit = false, + .radius = 16, + .pos = (vec2){32,32}, + .size = (vec2){32,32}, + .vel = (vec2){0,0}, + .render = { + .frame0 = 3, + .palette = 3, + .fam = (hh_s_ppu_loc_fam_entry){ + .horizontal_flip = false, + .vertical_flip = false, + .palette_index = 3, + .tilemap_index = 80, + } + } + }; +} void hh_render_all_entities(hh_entity* player, hh_entity* bullets, hh_entity* enemies, int bullet_size, int enemy_size, vec_cor cam_pos){ diff --git a/src/game_loop/gameplay.h b/src/game_loop/gameplay.h index 9d66c37..8adddb4 100644 --- a/src/game_loop/gameplay.h +++ b/src/game_loop/gameplay.h @@ -15,8 +15,9 @@ typedef enum { hh_e_level_complete, hh_e_game_over, }hh_e_gameplay; + /** @brief resets all the levels the first condition */ -void hh_reset_levels(); +void hh_reset_levels(hh_entity* player); /** @brief game loop function to handle the gameplay*/ void hh_gameplay(hh_g_all_levels* game, hh_e_game_state* hh_game_state); /** @brief renders all the entities*/ diff --git a/src/game_loop/starting_screen.c b/src/game_loop/starting_screen.c index c11e4fc..d9f8ea6 100644 --- a/src/game_loop/starting_screen.c +++ b/src/game_loop/starting_screen.c @@ -11,6 +11,7 @@ bool hh_show_starting_screen(){ { case hh_e_state_show: hh_clear_screen(); + hh_clear_sprite(); hh_init_title_screen(); hh_e_starting_screen = hh_e_state_input; return false; diff --git a/src/makefile b/src/makefile index a7af89e..ada73b1 100644 --- a/src/makefile +++ b/src/makefile @@ -42,6 +42,7 @@ LOCAL_SRCS += main.c \ engine/title_screen.c \ engine/level_const.c \ engine/enemy.c \ + engine/enemy_ai.c \ engine/animator.c \ game_loop/shop.c \ game_loop/gameplay.c \ |