Kaynağa Gözat

: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 yıl önce
ebeveyn
işleme
e037eb2680
2 değiştirilmiş dosya ile 29 ekleme ve 7 silme
  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_;
 };