proper collision

This commit is contained in:
Hunter 2023-05-27 17:40:27 -04:00
parent 83e312894b
commit 553ab7c1df
10 changed files with 143 additions and 8 deletions

54
src/collision.cpp Normal file
View file

@ -0,0 +1,54 @@
#include "collision.hpp"
#include "config.hpp"
#include "player.hpp"
#include "state.hpp"
void PBuildCollisionFromMap(Map *map) {
SDL_Log("Building collision data from map");
state.collisions.clear();
// Tiles have no collision data attached to them, so we have to basically
// "guess" if they are solid or not
// Except this guess works 99% of the time
// Look tiles up by name in the collision database
int x = 0;
int y = 0;
for (std::string tileName : map->data.mapTiles) {
if (x + 1 > map->mapWidth) {
x = 0;
y++;
}
if (state.collisionDb.tileInfo.at(tileName).isSolid) {
PCollisionRect collisionRect{};
collisionRect.rect.x = x * TEXTURE_WIDTH;
collisionRect.rect.y = y * TEXTURE_HEIGHT;
collisionRect.rect.w = TEXTURE_WIDTH - 5;
collisionRect.rect.h = TEXTURE_HEIGHT - 5;
state.collisions.push_back(collisionRect);
}
x++;
}
}
void PPopulateCollisionDb() {
SDL_Log("Populating collision database for the first time");
state.collisionDb.tileInfo.insert({"WALL", {true}});
state.collisionDb.tileInfo.insert({"FLOOR", {false}});
}
bool PCanMoveTo(int x, int y) {
SDL_Rect playerRect = PGetPlayerRect(&state.player);
playerRect.x = x;
playerRect.y = y;
for (PCollisionRect rect : state.collisions) {
if (SDL_HasIntersection(&playerRect, &rect.rect)) {
return false;
}
}
return true;
}

View file

@ -55,6 +55,10 @@ Map PLoadMapFromFile(std::string filepath) {
std::vector<std::string> mapScale = split(mapCommand[1], "x");
map.mapScaleX = std::stoi(mapScale[0]);
map.mapScaleY = std::stoi(mapScale[1]);
} else if (mapCommand[0] == "MAPSPWN") {
std::vector<std::string> mapSpawn = split(mapCommand[1], ",");
map.mapPlayerSpawnX = std::stoi(mapSpawn[0]);
map.mapPlayerSpawnY = std::stoi(mapSpawn[1]);
}
}
@ -63,6 +67,8 @@ Map PLoadMapFromFile(std::string filepath) {
SDL_Log("Map name: %s", map.mapName.c_str());
SDL_Log("Map author: %s", map.mapAuthor.c_str());
SDL_Log("Map version: %s", map.mapVersion.c_str());
SDL_Log("Player spawn: (%s, %s)", std::to_string(map.mapPlayerSpawnX).c_str(),
std::to_string(map.mapPlayerSpawnY).c_str());
SDL_Log("Map size: %ix%i", map.mapWidth, map.mapHeight);
@ -112,6 +118,9 @@ void PSaveMapToFile(Map *map, std::string filepath) {
mapContent += "MAPSCAL " + std::to_string(map->mapScaleX) + "x" +
std::to_string(map->mapScaleY) + "\n";
mapContent += "MAPSPWN " + std::to_string(map->mapPlayerSpawnX) + "," +
std::to_string(map->mapPlayerSpawnY) + "\n";
mapContent += "MAP\n";
// Map data
for (auto tile : map->data.mapTiles) {

View file

@ -1,4 +1,5 @@
#include "assets.hpp"
#include "collision.hpp"
#include "texture.hpp"
#include <SDL_image.h>
#include <SDL_pixels.h>
@ -17,6 +18,8 @@ void PRunBoostrap() {
PLoadTextureAsset("assets/player/player_walk_up.png");
PLoadTextureAsset("assets/player/player_walk_left.png");
PLoadTextureAsset("assets/player/player_walk_right.png");
PPopulateCollisionDb();
}
PhoenixGame::PhoenixGame() {
@ -34,11 +37,15 @@ PhoenixGame::PhoenixGame() {
PRunBoostrap();
m_currentMap = PLoadMapFromFile("maps/dm_scale.map");
PBuildCollisionFromMap(&m_currentMap);
state.camera.x = 0;
state.camera.y = 0;
state.camera.w = SCREEN_WIDTH;
state.camera.h = SCREEN_HEIGHT;
state.player.x = m_currentMap.mapPlayerSpawnX;
state.player.y = m_currentMap.mapPlayerSpawnY;
}
void PhoenixGame::present() { SDL_RenderPresent(state.renderer); }
@ -71,22 +78,26 @@ void PhoenixGame::run() {
unsigned char const *keys = SDL_GetKeyboardState(nullptr);
if (keys[SDL_SCANCODE_W]) {
if (keys[SDL_SCANCODE_W] &&
PCanMoveTo(state.player.x, state.player.y - 5)) {
state.player.facing = Up;
state.player.y -= 5;
}
if (keys[SDL_SCANCODE_S]) {
if (keys[SDL_SCANCODE_S] &&
PCanMoveTo(state.player.x, state.player.y + 5)) {
state.player.facing = Down;
state.player.y += 5;
}
if (keys[SDL_SCANCODE_A]) {
if (keys[SDL_SCANCODE_A] &&
PCanMoveTo(state.player.x - 5, state.player.y)) {
state.player.facing = Left;
state.player.x -= 5;
}
if (keys[SDL_SCANCODE_D]) {
if (keys[SDL_SCANCODE_D] &&
PCanMoveTo(state.player.x + 5, state.player.y)) {
state.player.facing = Right;
state.player.x += 5;
}

View file

@ -27,3 +27,13 @@ void PRenderPlayer(PPlayer *player) {
"Invalid player->facing direction, expected Up, Down, Left, or Right");
}
}
SDL_Rect PGetPlayerRect(PPlayer *player) {
SDL_Rect rect{};
rect.x = player->x;
rect.y = player->y;
rect.w = TEXTURE_WIDTH;
rect.h = TEXTURE_HEIGHT;
return rect;
}