aboutsummaryrefslogtreecommitdiff
path: root/src/games/snake/Snake.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/games/snake/Snake.cpp')
-rw-r--r--src/games/snake/Snake.cpp269
1 files changed, 141 insertions, 128 deletions
diff --git a/src/games/snake/Snake.cpp b/src/games/snake/Snake.cpp
index 4c6ca18..7969616 100644
--- a/src/games/snake/Snake.cpp
+++ b/src/games/snake/Snake.cpp
@@ -1,196 +1,218 @@
-#include "renderer/Renderer.hpp"
+#include "common/defs.hpp"
+#include <chrono>
#include <games/snake/Snake.hpp>
+#include <renderer/Renderer.hpp>
#include <imgui.h>
+std::mt19937 Snake::s_rng{std::random_device{}()};
+
+
Snake::Snake()
{
- m_IsPaused = false;
- m_IsRunning = true;
-
- m_DtInSecondsRemaining = 0.0f;
- m_LastMillisecondsSinceT0 = SDL_GetTicks();
+ static_assert(max_map_width <= sizeof(m_body_bitmap[0])*8);
+ static_assert(max_map_height <= sizeof(m_body_bitmap[0])*8);
+}
- m_TilesPerSecond = 4.0f;
- m_Direction = right;
- m_LastAdvancedDirection = right;
+void
+Snake::Start(int32_t map_width, int32_t map_height)
+{
+ m_dt_remaining_seconds = 0.0f;
+ m_tlast_milliseconds = SDL_GetTicks();
- m_MapWidth = 16;
- m_MapHeight = 16;
- assert(MAX_MAP_WIDTH <= 64); // m_BodyBitmap is uint64_t[]. We can't exceed that!
- assert(MAX_MAP_HEIGHT <= 64);
- assert(m_MapWidth <= MAX_MAP_WIDTH);
- assert(m_MapHeight <= MAX_MAP_WIDTH);
+ m_direction = right;
+ m_last_advanced_direction = right;
- m_Tail = 0;
- m_Head = 1;
- memset(m_BodyBitmap, 0, sizeof(m_BodyBitmap));
+ assert(map_width <= max_map_width);
+ assert(map_height <= max_map_height);
+ m_map_width = map_width;
+ m_map_height = map_height;
- int32_t head_x = m_MapWidth / 2;
- int32_t head_y = m_MapHeight / 2;
- m_BodyPositions[0] = {head_x -1, head_y};
- m_BodyPositions[1] = {head_x, head_y};
+ m_tail = 0;
+ m_head = 1;
- m_Rng = std::mt19937((std::random_device()()));
- m_Dist = std::uniform_int_distribution<int32_t>(0, m_MapWidth * m_MapHeight - 3);
+ int32_t head_x = m_map_width / 2;
+ int32_t head_y = m_map_height / 2;
+ m_body_positions[0] = {head_x -1, head_y};
+ m_body_positions[1] = {head_x, head_y};
+ memset(m_body_bitmap, 0, sizeof(m_body_bitmap));
+ m_dist = std::uniform_int_distribution<int32_t>(0, m_map_width*m_map_height - 3);
SpawnFood();
-}
-
-bool Snake::Update(std::vector<SDL_Event> &events) {
- uint64_t milliseconds_since_t0 = SDL_GetTicks();
- uint64_t milliseconds_since_t0_last = m_LastMillisecondsSinceT0;
- uint64_t dt_in_milliseconds = milliseconds_since_t0 - milliseconds_since_t0_last;
- float dt_in_seconds = (float)dt_in_milliseconds / 1000.0f;
- m_LastMillisecondsSinceT0 = milliseconds_since_t0;
+ m_game_status = game_resuming;
+}
+bool
+Snake::Update(std::vector<SDL_Event> &events)
+{
Color clear_color = {0.3f, 0.3f, 0.3f, 1.0f};
g_renderer.SetCameraSize(4.0f, 3.0f);
g_renderer.Clear(clear_color);
+ if (m_game_status == game_starting) {
+ int32_t map_width = 16;
+ int32_t map_height = 16;
+ Start(map_width, map_height);
+ }
+
+
for (SDL_Event &event : events) {
- if (!m_IsRunning) {
- printf("event loop is running just false\n");
- return false;
+ if (m_game_status == game_resuming) {
+ ProcessEventDuringResume(event);
}
- if (m_IsPaused) {
+ else if (m_game_status == game_paused) {
ProcessEventDuringPause(event);
}
- else {
- ProcessEventDuringResume(event);
- }
}
- if (!m_IsPaused) {
- MaybeMoveSnake(dt_in_seconds);
+
+ float dt = ProcessDt();
+
+ switch (m_game_status) {
+ case game_starting: {
+ } break;
+ case game_resuming: {
+ MaybeMoveSnake(dt);
+ } break;
+ case game_over: {
+ DrawGameOverMenu();
+ } break;
+ case game_paused: {
+ DrawGamePausedMenu();
+ } break;
+ case game_exit: {
+ return false;
+ } break;
}
Draw();
- DoImgui();
-
- return m_IsRunning;
+ return true;
}
-void Snake::MaybeMoveSnake(float dt_in_seconds) {
- float dt_in_seconds_to_use = m_DtInSecondsRemaining + dt_in_seconds;
- float tiles_per_second = m_TilesPerSecond;
+void
+Snake::MaybeMoveSnake(float dt)
+{
float seconds_per_tile = 1.0f / tiles_per_second;
- while (dt_in_seconds_to_use > seconds_per_tile) {
- V2I32 head_pos = m_BodyPositions[m_Head];
- V2I32 tail_pos = m_BodyPositions[m_Tail];
+ while (dt > seconds_per_tile) {
+ V2I32 head_pos = m_body_positions[m_head];
+ V2I32 tail_pos = m_body_positions[m_tail];
// find head_pos
- if (m_Direction == up) {
+ if (m_direction == up) {
head_pos.y += 1;
}
- else if (m_Direction == down) {
+ else if (m_direction == down) {
head_pos.y -= 1;
}
- else if (m_Direction == right) {
+ else if (m_direction == right) {
head_pos.x += 1;
}
- else if (m_Direction == left) {
+ else if (m_direction == left) {
head_pos.x -= 1;
}
- if ((head_pos.x < 0 || head_pos.x >= m_MapWidth) ||
- (head_pos.y < 0 || head_pos.y >= m_MapHeight))
+ if ((head_pos.x < 0 || head_pos.x >= m_map_width) ||
+ (head_pos.y < 0 || head_pos.y >= m_map_height))
{
- m_IsRunning = false;
+ m_game_status = game_over;
return;
}
uint64_t head_bit = 1 << head_pos.x;
- uint64_t body_bits = m_BodyBitmap[head_pos.y];
+ uint64_t body_bits = m_body_bitmap[head_pos.y];
if (head_pos.y == tail_pos.y) {
body_bits &= ~(1 << tail_pos.x);
}
if (head_bit & body_bits) {
- m_IsRunning = false;
+ m_game_status = game_over;
return;
}
// advance head
- int32_t max_positions = sizeof(m_BodyPositions) / sizeof(m_BodyPositions[0]);
- m_Head += 1;
- if (m_Head >= max_positions) {
- m_Head = 0;
+ int32_t max_positions = ARRAY_COUNT(m_body_positions);
+ m_head += 1;
+ if (m_head >= max_positions) {
+ m_head = 0;
}
- m_BodyPositions[m_Head] = head_pos;
- m_BodyBitmap[head_pos.y] |= (1 << head_pos.x);
+ m_body_positions[m_head] = head_pos;
+ m_body_bitmap[head_pos.y] |= (1 << head_pos.x);
- if (m_BodyPositions[m_Head] == m_FoodPosition) {
+ if (m_body_positions[m_head] == m_food_position) {
SpawnFood();
}
else {
// advance tail
- V2I32 next_tail_pos = m_BodyPositions[m_Tail];
- m_BodyBitmap[next_tail_pos.y] &= ~(1 << next_tail_pos.x);
+ V2I32 next_tail_pos = m_body_positions[m_tail];
+ m_body_bitmap[next_tail_pos.y] &= ~(1 << next_tail_pos.x);
- m_Tail += 1;
- if (m_Tail >= max_positions) {
- m_Tail = 0;
+ m_tail += 1;
+ if (m_tail >= max_positions) {
+ m_tail = 0;
}
}
- m_LastAdvancedDirection = m_Direction;
- dt_in_seconds_to_use -= seconds_per_tile;
+ m_last_advanced_direction = m_direction;
+ dt -= seconds_per_tile;
}
- m_DtInSecondsRemaining = dt_in_seconds_to_use;
+ m_dt_remaining_seconds = dt;
}
-void Snake::ProcessEventDuringPause(SDL_Event &event) {
+void
+Snake::ProcessEventDuringPause(SDL_Event &event)
+{
switch (event.type) {
case SDL_EVENT_KEY_DOWN: {
if (event.key.key == SDLK_ESCAPE) {
- m_IsPaused = false;
+ m_game_status = game_resuming;
}
}
default:;
}
}
-void Snake::ProcessEventDuringResume(SDL_Event &event) {
+void
+Snake::ProcessEventDuringResume(SDL_Event &event)
+{
switch (event.type) {
case SDL_EVENT_KEY_DOWN: {
if (event.key.key == SDLK_UP) {
- if (m_LastAdvancedDirection == right ||
- m_LastAdvancedDirection == left)
+ if (m_last_advanced_direction == right ||
+ m_last_advanced_direction == left)
{
- m_Direction = up;
+ m_direction = up;
}
}
else if (event.key.key == SDLK_DOWN) {
- if (m_LastAdvancedDirection == right ||
- m_LastAdvancedDirection == left)
+ if (m_last_advanced_direction == right ||
+ m_last_advanced_direction == left)
{
- m_Direction = down;
+ m_direction = down;
}
}
else if (event.key.key == SDLK_RIGHT) {
- if (m_LastAdvancedDirection == up ||
- m_LastAdvancedDirection == down)
+ if (m_last_advanced_direction == up ||
+ m_last_advanced_direction == down)
{
- m_Direction = right;
+ m_direction = right;
}
}
else if (event.key.key == SDLK_LEFT) {
- if (m_LastAdvancedDirection == up ||
- m_LastAdvancedDirection == down)
+ if (m_last_advanced_direction == up ||
+ m_last_advanced_direction == down)
{
- m_Direction = left;
+ m_direction = left;
}
}
else if (event.key.key == SDLK_ESCAPE) {
- m_IsPaused = true;
+ m_game_status = game_paused;
}
}
@@ -198,21 +220,23 @@ void Snake::ProcessEventDuringResume(SDL_Event &event) {
}
}
-void Snake::SpawnFood() {
- int32_t bit0_counts[MAX_MAP_HEIGHT];
+void
+Snake::SpawnFood()
+{
+ int32_t bit0_counts[max_map_height];
int32_t bit0_count_total = 0;
// count bits
- for (int32_t y = 0; y < m_MapHeight; y++) {
+ for (int32_t y = 0; y < m_map_height; y++) {
int32_t bit1_count = 0;
- uint64_t bitmap_row = m_BodyBitmap[y];
+ uint64_t bitmap_row = m_body_bitmap[y];
while (bitmap_row != 0) {
bitmap_row = bitmap_row & (bitmap_row - 1);
bit1_count += 1;
}
- int32_t bit0_count = m_MapWidth - bit1_count;
+ int32_t bit0_count = m_map_width - bit1_count;
bit0_counts[y] = bit0_count;
bit0_count_total += bit0_count;
}
@@ -221,13 +245,13 @@ void Snake::SpawnFood() {
return;
}
- m_Dist.param(std::uniform_int_distribution<int32_t>::param_type(0, bit0_count_total - 1));
- int32_t bit0_index = m_Dist(m_Rng);
+ m_dist.param(std::uniform_int_distribution<int32_t>::param_type(0, bit0_count_total - 1));
+ int32_t bit0_index = m_dist(s_rng);
int32_t bit0_x = 0;
int32_t bit0_y = 0;
// find y
- for (int32_t y = 0; y < m_MapHeight; y++) {
+ for (int32_t y = 0; y < m_map_height; y++) {
if (bit0_index < bit0_counts[y]) {
bit0_y = y;
break;
@@ -236,8 +260,8 @@ void Snake::SpawnFood() {
}
// find x
- uint64_t bitmap_row_not = ~m_BodyBitmap[bit0_y];
- for (int32_t x = 0; x < m_MapWidth; x++) {
+ uint64_t bitmap_row_not = ~m_body_bitmap[bit0_y];
+ for (int32_t x = 0; x < m_map_width; x++) {
if (bitmap_row_not & 1) {
if (bit0_index == 0) {
bit0_x = x;
@@ -248,23 +272,25 @@ void Snake::SpawnFood() {
bitmap_row_not >>= 1;
}
- m_FoodPosition = {bit0_x, bit0_y};
+ m_food_position = {bit0_x, bit0_y};
}
-void Snake::Draw() {
+void
+Snake::Draw()
+{
float world_width = 4.0f;
float world_height = 3.0f;
- float tile_size = (world_width / 2) / MAX_MAP_WIDTH;
+ float tile_size = (world_width / 2) / max_map_width;
float bodypart_size = 0.8f * tile_size;
float bodypart_offset = (tile_size - bodypart_size) / 2;
- float map_view_width = tile_size * (float)m_MapWidth;
- float map_view_height = tile_size * (float)m_MapHeight;
+ float map_view_width = tile_size * (float)m_map_width;
+ float map_view_height = tile_size * (float)m_map_height;
float map_x = (world_width - map_view_width) / 2;
float map_y = (world_height - map_view_height) / 2;
- int32_t max_positions = sizeof(m_BodyPositions) / sizeof(m_BodyPositions[0]);
+ int32_t max_positions = ARRAY_COUNT(m_body_positions);
/* draw map background */
@@ -282,12 +308,12 @@ void Snake::Draw() {
/* draw snake */
// 1) if tail > head: advance to end first
- int32_t tail = m_Tail;
- if (tail > m_Head) {
+ int32_t tail = m_tail;
+ if (tail > m_head) {
while (tail < max_positions) {
V3F32 local_pos = {
- (float)m_BodyPositions[tail].x * tile_size + bodypart_offset,
- (float)m_BodyPositions[tail].y * tile_size + bodypart_offset,
+ (float)m_body_positions[tail].x * tile_size + bodypart_offset,
+ (float)m_body_positions[tail].y * tile_size + bodypart_offset,
1.0f
};
V2F32 local_dim = {bodypart_size, bodypart_size};
@@ -312,10 +338,10 @@ void Snake::Draw() {
tail = 0;
}
// 2) advance to head
- while (tail <= m_Head) {
+ while (tail <= m_head) {
V3F32 local_pos = {
- (float)m_BodyPositions[tail].x * tile_size + bodypart_offset,
- (float)m_BodyPositions[tail].y * tile_size + bodypart_offset,
+ (float)m_body_positions[tail].x * tile_size + bodypart_offset,
+ (float)m_body_positions[tail].y * tile_size + bodypart_offset,
1.0f
};
V2F32 local_dim = {bodypart_size, bodypart_size};
@@ -341,8 +367,8 @@ void Snake::Draw() {
/* draw food */
V3F32 pos = {
- map_world_pos.x + (float)m_FoodPosition.x * tile_size + bodypart_offset,
- map_world_pos.y + (float)m_FoodPosition.y * tile_size + bodypart_offset,
+ map_world_pos.x + (float)m_food_position.x * tile_size + bodypart_offset,
+ map_world_pos.y + (float)m_food_position.y * tile_size + bodypart_offset,
1.0f
};
V2F32 dim = {bodypart_size, bodypart_size};
@@ -356,16 +382,3 @@ void Snake::Draw() {
g_renderer.PushRectangle(rect, pos.z, color);
}
-void Snake::DoImgui() {
- if (m_IsPaused) {
- ImGui::Begin("SnakePause");
- if (ImGui::Button("Resume")) {
- m_IsPaused = false;
- }
- if (ImGui::Button("Exit")) {
- m_IsRunning = false;
- }
- ImGui::End();
- }
-}
-