Преглед на файлове

:sparkles: added non-deadly walls

after hitting a target, there's now a 5% chance the wall will be wrap-around until the next target is hit.
in that case the wall turns yellow and passing through will let you reenter on the opposite side of the field
Felix Bytow преди 1 година
родител
ревизия
e037eb2680
променени са 2 файла, в които са добавени 29 реда и са изтрити 7 реда
  1. 27 7
      game/PlayingState.cxx
  2. 2 0
      game/PlayingState.hxx

+ 27 - 7
game/PlayingState.cxx

@@ -88,19 +88,33 @@ void PlayingState::update(GameStateManager& gsm, std::chrono::milliseconds const
 
   auto const direction = new_direction_.value_or(direction_);
 
+  auto const MAX_X = static_cast<float>(CELLS_X-1);
+  auto const MAX_Y = static_cast<float>(CELLS_Y-1);
   SDL_FPoint new_head = head_;
   switch (direction) {
   case Direction::Up:
     new_head.y -= distance;
+    if (new_head.y<0.0f && !deadly_wall_) {
+      new_head.y += MAX_Y;
+    }
     break;
   case Direction::Down:
     new_head.y += distance;
+    if (new_head.y>=MAX_Y && !deadly_wall_) {
+      new_head.y -= MAX_Y;
+    }
     break;
   case Direction::Left:
     new_head.x -= distance;
+    if (new_head.x<0.0f && !deadly_wall_) {
+      new_head.x += MAX_X;
+    }
     break;
   case Direction::Right:
     new_head.x += distance;
+    if (new_head.x>=MAX_X && !deadly_wall_) {
+      new_head.x -= MAX_X;
+    }
     break;
   }
 
@@ -112,6 +126,11 @@ void PlayingState::update(GameStateManager& gsm, std::chrono::milliseconds const
       new_direction_.reset();
     }
 
+    if (detect_death(new_pos)) {
+      HighScoreManager::instance().set_new_score(length_);
+      gsm.replace_state(GameStates::GameOver);
+    }
+
     if (new_pos==target_) {
       ++length_;
       speed_ = std::min(MAX_SPEED, speed_*ACCELERATION);
@@ -122,11 +141,6 @@ void PlayingState::update(GameStateManager& gsm, std::chrono::milliseconds const
       }
     }
 
-    if (detect_death(new_pos)) {
-      HighScoreManager::instance().set_new_score(length_);
-      gsm.replace_state(GameStates::GameOver);
-    }
-
     tail_.push_front(old_pos);
     if (tail_.size()+1>length_)
       tail_.pop_back();
@@ -151,7 +165,8 @@ void PlayingState::handle_direction_change()
     else if (keyboard[SDL_SCANCODE_DOWN] || keyboard[SDL_SCANCODE_S]) {
       new_direction_ = Direction::Down;
     }
-  } else {
+  }
+  else {
     if (keyboard[SDL_SCANCODE_LEFT] || keyboard[SDL_SCANCODE_A]) {
       new_direction_ = Direction::Left;
     }
@@ -190,7 +205,10 @@ void PlayingState::render_ui(SDLRenderer& renderer, SDL_Rect const& playing_fiel
   SDL_RenderCopy(renderer, text, nullptr, &render_quad);
   SDL_DestroyTexture(text);
 
-  SDL_SetRenderDrawColor(renderer, 249, 95, 0, SDL_ALPHA_OPAQUE);
+  if (deadly_wall_)
+    SDL_SetRenderDrawColor(renderer, 249, 95, 0, SDL_ALPHA_OPAQUE);
+  else
+    SDL_SetRenderDrawColor(renderer, 255, 204, 0, SDL_ALPHA_OPAQUE);
   SDL_RenderDrawRect(renderer, &playing_field);
 }
 
@@ -204,6 +222,7 @@ bool PlayingState::place_target()
     }
   }
 
+  field.erase(::head_position(head_));
   for (auto const& particle: tail_) {
     field.erase(particle);
   }
@@ -216,6 +235,7 @@ bool PlayingState::place_target()
   std::ranges::sample(field, std::back_inserter(result), 1, generator_);
 
   target_ = result[0];
+  deadly_wall_ = distribution_deadly_wall(generator_)!=0;
 
   return true;
 }

+ 2 - 0
game/PlayingState.hxx

@@ -57,6 +57,7 @@ private:
   std::mt19937 generator_;
   std::uniform_int_distribution<int> distribution_position_x_{0, CELLS_X-1};
   std::uniform_int_distribution<int> distribution_position_y_{0, CELLS_Y-1};
+  std::discrete_distribution<int> distribution_deadly_wall{{5, 95}};
 
   SDL_Point target_{};
   unsigned length_{0u};
@@ -66,6 +67,7 @@ private:
   std::deque<SDL_Point> tail_;
   float speed_{0.001f};
   int fps_{0};
+  bool deadly_wall_{true};
 
   Asset<TTF_Font*> font_;
 };