diff options
-rw-r--r-- | README.md | 22 | ||||
-rw-r--r-- | include/pacman/game.hpp | 1 | ||||
-rw-r--r-- | src/ghost.cpp | 55 |
3 files changed, 44 insertions, 34 deletions
@@ -95,11 +95,15 @@ If false, a more accurate implementation, the pacman bugfix, is used: - Sync speed by dropping tick, every n-frames - Ghost *AI* - Scared RNG target - - Scatter and chase targets - - Next move algo + - Scatter, chase and phantom targets + - Next `direction_t` algo - Grouped wave switch of scatter, chase and frightened - Exit home using local and global pellet timer - PRNG with an identical seed value every new level and life for predictable results + - Adjust tunnel speed + - No turning up in *Red-Zones* if chasing or scattering +- Pacman + - show eaten ghosts score onscreen (FREEZE) - Level specification (per level) - Timings - scatter and chase duration per phase @@ -110,25 +114,29 @@ If false, a more accurate implementation, the pacman bugfix, is used: - ghost speed normal, frightening or in tunnel - Score - Score - - show eaten ghosts score onscreen + - ghost 1-4 per power pellet - Sound - Using wav chunks, mixed from seperated channels ### To Do - Ghost *AI* - *Elroy 1+2* mode - - Tunnel speed - - *Red-zones* w/o turning up - Score - Fruits / Bonus -- Pacman lives +- Pacman + - Lives + - Freeze pacman only for 3 frames after eating power pellet - Sound - Use lossy formats - Complete samples - Extension - - Second play moves a ghost + - Second player moves a ghost - Maze - Render maze itself from maze-spec file +- Persistent game state + - Save/load game state + - Screenshot + - Record video ## Media Data diff --git a/include/pacman/game.hpp b/include/pacman/game.hpp index 325e02d..6958faa 100644 --- a/include/pacman/game.hpp +++ b/include/pacman/game.hpp @@ -225,6 +225,7 @@ class ghost_t { animtex_t atex_phantom; animtex_t * atex; + acoord_t home_pos; acoord_t pos_; acoord_t target_; diff --git a/src/ghost.cpp b/src/ghost.cpp index 7ab68d8..491509e 100644 --- a/src/ghost.cpp +++ b/src/ghost.cpp @@ -98,9 +98,23 @@ ghost_t::ghost_t(const personality_t id_, SDL_Renderer* rend, const float fields atex_scared_flash( "S+", rend, ms_per_fright_flash/2, global_tex->all_images(), 0, 0, 14, 14, { { 10*14, 0 }, { 11*14, 0 } }), atex_phantom( "P", rend, ms_per_atex, global_tex->all_images(), 0, 41 + 4*14, 14, 14, { { 0*14, 0 }, { 1*14, 0 }, { 2*14, 0 }, { 3*14, 0 } }), atex( &get_tex() ), - pos_( global_maze->ghost_home_int_box().center_x(), global_maze->ghost_home_int_box().center_y() ), - target_( global_maze->ghost_home_int_box().center_x(), global_maze->ghost_home_int_box().center_y() ) + home_pos( -1, -1 ), + pos_( -1, -1 ), + target_( -1, -1 ) { + if( ghost_t::personality_t::BLINKY == id ) { + // positioned outside of the box at start + home_pos = acoord_t( global_maze->ghost_start_box().center_x()-0.0f, global_maze->ghost_start_box().y()-0.0f ); + // home_pos = acoord_t( global_maze->ghost_home_int_box().center_x(), global_maze->ghost_home_int_box().center_y() ); + } else if( ghost_t::personality_t::PINKY == id ) { + home_pos = acoord_t( global_maze->ghost_home_int_box().center_x()-0.0f, global_maze->ghost_home_int_box().center_y()-0.0f ); + } else if( ghost_t::personality_t::INKY == id ) { + home_pos = acoord_t( global_maze->ghost_home_int_box().center_x()-2.0f, global_maze->ghost_home_int_box().center_y()-0.0f ); + } else { + home_pos = acoord_t( global_maze->ghost_home_int_box().center_x()+2.0f, global_maze->ghost_home_int_box().center_y()-0.0f ); + } + pos_ = home_pos; + target_ = home_pos; } @@ -127,16 +141,7 @@ void ghost_t::set_speed(const float pct) noexcept { void ghost_t::set_next_target() noexcept { switch( mode_ ) { case mode_t::HOME: - if( ghost_t::personality_t::BLINKY == id ) { - target_ = acoord_t( global_maze->ghost_start_box().x(), global_maze->ghost_start_box().y() ); - break; - } else if( ghost_t::personality_t::PINKY == id ) { - target_ = acoord_t( global_maze->ghost_home_int_box().center_x(), global_maze->ghost_home_int_box().center_y() ); - } else if( ghost_t::personality_t::INKY == id ) { - target_ = acoord_t( global_maze->ghost_home_int_box().center_x(), global_maze->ghost_home_int_box().center_y() ); - } else { - target_ = acoord_t( global_maze->ghost_home_int_box().center_x(), global_maze->ghost_home_int_box().center_y() ); - } + target_ = home_pos; target_.set_centered(keyframei_); break; @@ -220,7 +225,11 @@ void ghost_t::set_next_target() noexcept { break; case mode_t::PHANTOM: - target_ = acoord_t( global_maze->ghost_home_int_box().center_x(), global_maze->ghost_home_int_box().center_y() ); + if( ghost_t::personality_t::BLINKY == id ) { + target_ = acoord_t( global_maze->ghost_home_int_box().center_x(), global_maze->ghost_home_int_box().center_y() ); + } else { + target_ = home_pos; + } target_.set_centered(keyframei_); break; @@ -312,7 +321,8 @@ void ghost_t::set_next_dir(const bool collision, const bool is_center) noexcept const float d_half = ( global_maze->width() * global_maze->height() ) / 2; // not_up on red_zones acts as collision, also assume it as a wall when deciding whether we have a decision point or not! - const bool not_up = !in_house() && ( pos_.intersects_i( global_maze->red_zone1_box() ) || pos_.intersects_i( global_maze->red_zone2_box() ) ); + const bool not_up = is_scattering_or_chasing() && + ( pos_.intersects_i( global_maze->red_zone1_box() ) || pos_.intersects_i( global_maze->red_zone2_box() ) ); const direction_t left_dir = rot_left(cur_dir); const direction_t right_dir = rot_right(cur_dir); @@ -535,7 +545,7 @@ void ghost_t::set_mode_speed() noexcept { set_speed(game_level_spec().ghost_fright_speed); break; case mode_t::PHANTOM: - set_speed(1.00f); + set_speed(2.00f); break; default: break; @@ -565,16 +575,7 @@ void ghost_t::set_mode(const mode_t m, const int mode_ms) noexcept { pellet_counter_active_ = false; } } - if( ghost_t::personality_t::BLINKY == id ) { - // positioned outside of the box at start - pos_ = acoord_t( global_maze->ghost_start_box().center_x()-0.0f, global_maze->ghost_start_box().y()-0.0f ); - } else if( ghost_t::personality_t::PINKY == id ) { - pos_ = acoord_t( global_maze->ghost_home_int_box().center_x()-0.0f, global_maze->ghost_home_int_box().center_y()-0.0f ); - } else if( ghost_t::personality_t::INKY == id ) { - pos_ = acoord_t( global_maze->ghost_home_int_box().center_x()-2.0f, global_maze->ghost_home_int_box().center_y()-0.0f ); - } else { - pos_ = acoord_t( global_maze->ghost_home_int_box().center_x()+2.0f, global_maze->ghost_home_int_box().center_y()-0.0f ); - } + pos_ = home_pos; dir_ = direction_t::LEFT; pos_.set_aligned_dir(keyframei_); break; @@ -668,7 +669,7 @@ void ghost_t::tick() noexcept { return; // wait } } else if( mode_t::LEAVE_HOME == mode_ ) { - if( pos_.intersects(target_) ) { + if( pos_.intersects_f( target_ ) ) { if( mode_t::PHANTOM == mode_last && mode_t::SCARED == global_mode ) { // avoid re-materialized ghost to restart SCARED again set_mode( global_mode_last ); @@ -689,7 +690,7 @@ void ghost_t::tick() noexcept { set_next_target(); // update dummy } } else if( mode_t::PHANTOM == mode_ ) { - if( pos_.intersects_i( global_maze->ghost_home_int_box() ) ) { + if( pos_.intersects_f( target_) ) { // too fuzzy: global_maze->ghost_home_int_box() set_mode( mode_t::LEAVE_HOME ); } } |