Files
snakePlus/source/game_logic.cpp
T

175 lines
5.1 KiB
C++

#include "game_logic.h"
#include <algorithm>
#include <cstdlib>
#include <nds.h>
#include <consts.h>
void update_snake(GameState &state) {
std::array<int, 3> headpos = state.snake.front();
std::array<int, 3> newHead = headpos;
if (state.snakeDirection == 0) {
newHead = {headpos[0], headpos[1] - 1, state.snakeDirection};
} else if (state.snakeDirection == 1) {
newHead = {headpos[0] + 1, headpos[1], state.snakeDirection};
} else if (state.snakeDirection == 2) {
newHead = {headpos[0], headpos[1] + 1, state.snakeDirection};
} else if (state.snakeDirection == 3) {
newHead = {headpos[0] - 1, headpos[1], state.snakeDirection};
}
if (newHead[0] > X_MAX) {
newHead[0] = 0;
}
if (newHead[1] > Y_MAX) {
newHead[1] = 0;
}
if (newHead[0] < 0) {
newHead[0] = X_MAX;
}
if (newHead[1] < 0) {
newHead[1] = Y_MAX;
}
state.snake.push_front(newHead);
state.snake.resize(state.snakelength);
}
bool check_collision_self(GameState &state) {
if (state.snake.size() < 2 || state.gameOver) {
return false;
}
const std::array<int, 3> headpos = state.snake.front();
for (auto it = state.snake.begin() + 1; it != state.snake.end(); ++it) {
if ((*it)[0] == headpos[0] && (*it)[1] == headpos[1]) {
state.gameOver = true;
return true;
}
}
return false;
}
bool check_collision_apples(GameState &state) {
const std::array<int, 3> headpos = state.snake.front();
auto it =
std::find_if(state.apples.begin(), state.apples.end(),
[&](const std::array<int, 2> &apple) {
return apple[0] == headpos[0] && apple[1] == headpos[1];
});
if (it == state.apples.end()) {
return false;
}
state.score += APPLE_SCORE;
state.snakelength++;
state.applesEaten++;
state.apples.erase(it);
return true;
}
bool check_collision_apples_rotten(GameState &state) {
const std::array<int, 3> headpos = state.snake.front();
auto it =
std::find_if(state.bad_apples.begin(), state.bad_apples.end(),
[&](const std::array<int, 2> &apple) {
return apple[0] == headpos[0] && apple[1] == headpos[1];
});
if (it == state.bad_apples.end()) {
return false;
}
state.snakelength--;
state.bad_apples.erase(it);
if (state.snakelength < 2) {
state.gameOver = true;
}
return true;
}
bool check_collision_apples_cursed(GameState &state) {
const std::array<int, 3> headpos = state.snake.front();
auto it =
std::find_if(state.cursed_apples.begin(), state.cursed_apples.end(),
[&](const std::array<int, 2> &apple) {
return apple[0] == headpos[0] && apple[1] == headpos[1];
});
if (it == state.cursed_apples.end()) {
return false;
}
state.cursed_apples.erase(it);
state.curseTicksRemaining = CURSE_DURATION_TICKS;
return true;
}
void spawn_apples(GameState &state) {
if (state.apples.size() < 1) {
std::array<int, 2> apple = {rand() % (X_MAX + 1), rand() % (Y_MAX + 1)};
state.apples.push_back(apple);
}
}
void spawn_apples_rotten(GameState &state) {
if ((state.ticks % 10 == 0) && state.hardMode && ((rand() % 10) < 10) &&
(state.bad_apples.size() < 20)) {
std::array<int, 2> badApple = {rand() % (X_MAX + 1), rand() % (Y_MAX + 1)};
state.bad_apples.push_back(badApple);
}
}
void spawn_apples_cursed(GameState &state) {
if (state.cursed_apples.empty() && (state.ticks % 20 == 0) &&
((rand() % 5) == 0)) {
std::array<int, 2> cursedApple = {rand() % (X_MAX + 1),
rand() % (Y_MAX + 1)};
state.cursed_apples.push_back(cursedApple);
}
}
void tick_status_effects(GameState &state) {
if (state.curseTicksRemaining > 0) {
state.curseTicksRemaining--;
}
}
uint8_t calculate_intensity_31(const GameState &state) {
const uint16_t current_apples = state.applesEaten;
const uint16_t apples =
std::min<uint16_t>(current_apples, static_cast<uint16_t>(SPEED_APPLES_CAP));
return static_cast<uint8_t>((static_cast<uint32_t>(apples) * 31U) /
static_cast<uint32_t>(SPEED_APPLES_CAP));
}
uint16_t calculate_timer_freq_mhz(const GameState &state) {
const uint16_t base_mhz =
state.hardMode ? SPEED_BASE_HARD_MHZ : SPEED_BASE_NORMAL_MHZ;
const uint16_t max_mhz =
state.hardMode ? SPEED_MAX_HARD_MHZ : SPEED_MAX_NORMAL_MHZ;
const uint16_t current_apples = state.applesEaten;
const uint16_t apples =
std::min<uint16_t>(current_apples, static_cast<uint16_t>(SPEED_APPLES_CAP));
const uint32_t diff = static_cast<uint32_t>(max_mhz - base_mhz);
return static_cast<uint16_t>(
base_mhz + ((static_cast<uint32_t>(apples) * diff) /
static_cast<uint32_t>(SPEED_APPLES_CAP)));
}
uint16_t calculate_timer_reload(const GameState &state) {
const uint32_t freq_mhz = calculate_timer_freq_mhz(state);
// Timer clock with ClockDivider_1024 is BUS_CLOCK >> 10 (32728 Hz)
const uint32_t timer_clock_mhz = (BUS_CLOCK >> 10U) * 1000U;
const uint32_t period_ticks = timer_clock_mhz / freq_mhz;
return static_cast<uint16_t>(-static_cast<int32_t>(period_ticks));
}