Files
2025-12-31 13:22:56 +08:00

156 lines
4.3 KiB
C++

#include "Snake.h"
#include "SDL3/SDL_oldnames.h"
#include "SDL3/SDL_render.h"
static std::mt19937 gen(static_cast<unsigned int>(std::time(nullptr)));
Snake::Snake(int screenWidth, int screenHeight, int segmentSize = 25) {
this->segmentSize = segmentSize;
int maxGridX = (screenWidth / segmentSize) - 1;
int maxGridY = (screenHeight / segmentSize) - 1;
std::uniform_int_distribution<int> distX(5, maxGridX - 5);
std::uniform_int_distribution<int> distY(5, maxGridY - 5);
SDL_Point startPoint = { distX(gen), distY(gen) };
body.clear();
body.push_front(startPoint);
RandomizeDirection();
growing = false;
}
void Snake::Reset(int screenWidth, int screenHeight) {
int maxGridX = (screenWidth / segmentSize) - 1;
int maxGridY = (screenHeight / segmentSize) - 1;
std::uniform_int_distribution<int> distX(5, maxGridX - 5);
std::uniform_int_distribution<int> distY(5, maxGridY - 5);
SDL_Point startPoint = { distX(gen), distY(gen) };
body.clear();
body.push_front(startPoint);
}
void Snake::HandleInput(SDL_Keycode key) {
switch(key) {
case SDLK_UP:
if (direction.y != 1) {
direction.x = 0;
direction.y = -1;
}
break;
case SDLK_DOWN:
if (direction.y != -1) {
direction.x = 0;
direction.y = 1;
}
break;
case SDLK_LEFT:
if (direction.x != 1) {
direction.x = -1;
direction.y = 0;
}
break;
case SDLK_RIGHT:
if (direction.x != -1) {
direction.x = 1;
direction.y = 0;
}
break;
}
}
void Snake::Update(){
SDL_Point newPoint = {body.front().x + direction.x, body.front().y + direction.y};
body.push_front(newPoint);
if(!growing){
body.pop_back();
} else {
growing = false;
}
}
void Snake::Render(SDL_Renderer* renderer) {
for (size_t i = 0; i < body.size(); ++i) {
SDL_FRect rect = {
(float)(body[i].x * segmentSize),
(float)(body[i].y * segmentSize),
(float)segmentSize - 1.0f,
(float)segmentSize - 1.0f
};
if (i == 0) {
SDL_SetRenderDrawColor(renderer, 0, 200, 0, 255);
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_FRect leftEye = { rect.x + 4, rect.y + 4, 6, 6 };
SDL_FRect rightEye = { rect.x + rect.w - 10, rect.y + 4, 6, 6 };
SDL_RenderFillRect(renderer, &leftEye);
SDL_RenderFillRect(renderer, &rightEye);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderPoint(renderer, leftEye.x + 3, leftEye.y + 3);
SDL_RenderPoint(renderer, rightEye.x + 3, rightEye.y + 3);
} else {
SDL_SetRenderDrawColor(renderer, 50, 255, 50, 255);
SDL_RenderFillRect(renderer, &rect);
}
}
}
void Snake::Grow(){
growing = true;
}
// Snake.cpp
void Snake::RandomizeDirection() {
// Define 4 possible directions: Up, Down, Left, Right
// Remember: SDL3 Y-axis increases downwards
static const SDL_Point directions[] = {
{0, -1}, // Up
{0, 1}, // Down
{-1, 0}, // Left
{1, 0} // Right
};
std::uniform_int_distribution<int> dist(0, 3);
int randomIndex = dist(gen);
this->direction = directions[randomIndex];
}
bool Snake::CheckCollision(int screenWidth, int screenHeight){
if(body.empty()) return false;
SDL_Point head = body.front();
// Boundary Collision (Wall)
int gridWidth = screenWidth / segmentSize;
int gridHeight = screenHeight / segmentSize;
if (head.x < 0 || head.x >= gridWidth || head.y < 0 || head.y >= gridHeight) {
return true;
}
// Self Collision
// Start loop from index 1 to skip the head itself
for (size_t i = 1; i < body.size(); ++i) {
if (head.x == body[i].x && head.y == body[i].y) {
return true; // Bit its own tail
}
}
return false;
}
SDL_Point Snake::GetHeadPos() const{
return body.front();
}
std::deque<SDL_Point> Snake::GetBody() const {
return body;
}