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

View file

@ -4,12 +4,12 @@ Size=400,400
Collapsed=0 Collapsed=0
[Window][Phoenix Map Editor] [Window][Phoenix Map Editor]
Pos=1261,211 Pos=851,698
Size=556,101 Size=556,101
Collapsed=0 Collapsed=0
[Window][Map Editor Tools] [Window][Map Editor Tools]
Pos=3009,535 Pos=1002,137
Size=338,211 Size=357,247
Collapsed=0 Collapsed=0

32
include/collision.hpp Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#include "map.hpp"
#include <SDL.h>
#include <map>
struct PCollisionRect {
SDL_Rect rect;
};
struct PCollisionInfo {
bool isSolid = false;
};
struct PCollisionDatabase {
std::map<std::string, PCollisionInfo> tileInfo;
};
/*
* Called once, generates a list of tiles which are solid, and which ones are
* not solid
*/
void PPopulateCollisionDb();
/*
* Check if we can move to the given position in the map
*/
bool PCanMoveTo(int x, int y);
/*
* Build a list of PCollisionRects from the given map
*/
void PBuildCollisionFromMap(Map *map);

View file

@ -15,6 +15,8 @@ struct Map {
int mapHeight; int mapHeight;
int mapScaleX; // Rendering scale int mapScaleX; // Rendering scale
int mapScaleY; // Rendering scale int mapScaleY; // Rendering scale
int mapPlayerSpawnX;
int mapPlayerSpawnY;
MapData data; MapData data;
}; };

View file

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <SDL.h>
#include <string> #include <string>
enum PPlayerFacingDirection { Up, Down, Left, Right }; enum PPlayerFacingDirection { Up, Down, Left, Right };
@ -13,3 +14,4 @@ struct PPlayer {
}; };
void PRenderPlayer(PPlayer *player); void PRenderPlayer(PPlayer *player);
SDL_Rect PGetPlayerRect(PPlayer *player);

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "assets.hpp" #include "assets.hpp"
#include "collision.hpp"
#include "config.hpp" #include "config.hpp"
#include "player.hpp" #include "player.hpp"
#include <SDL.h> #include <SDL.h>
@ -8,7 +9,10 @@ struct GlobalState {
SDL_Window *window; SDL_Window *window;
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_Rect camera; SDL_Rect camera;
PPlayer player; PPlayer player;
PCollisionDatabase collisionDb;
std::vector<PCollisionRect> collisions;
PhoenixAssets assets; PhoenixAssets assets;
int scale = 20; int scale = 20;
}; };

View file

@ -2,7 +2,8 @@ MAPNAME DMSCALE
MAPVERS 1 MAPVERS 1
MAPAUTH Interfiber MAPAUTH Interfiber
MAPSIZE 10x10 MAPSIZE 10x10
MAPSCAL 2x2 MAPSCAL 3x3
MAPSPWN 32,32
MAP MAP
TILE WALL TILE WALL
TILE FLOOR TILE FLOOR
@ -214,4 +215,14 @@ TILE WALL
TILE WALL TILE WALL
TILE WALL TILE WALL
TILE WALL TILE WALL
TILE WALL
TILE WALL
TILE WALL
TILE WALL
TILE WALL
TILE WALL
TILE WALL
TILE WALL
TILE WALL
TILE WALL
ENDMAP ENDMAP

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"); std::vector<std::string> mapScale = split(mapCommand[1], "x");
map.mapScaleX = std::stoi(mapScale[0]); map.mapScaleX = std::stoi(mapScale[0]);
map.mapScaleY = std::stoi(mapScale[1]); 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 name: %s", map.mapName.c_str());
SDL_Log("Map author: %s", map.mapAuthor.c_str()); SDL_Log("Map author: %s", map.mapAuthor.c_str());
SDL_Log("Map version: %s", map.mapVersion.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); 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" + mapContent += "MAPSCAL " + std::to_string(map->mapScaleX) + "x" +
std::to_string(map->mapScaleY) + "\n"; std::to_string(map->mapScaleY) + "\n";
mapContent += "MAPSPWN " + std::to_string(map->mapPlayerSpawnX) + "," +
std::to_string(map->mapPlayerSpawnY) + "\n";
mapContent += "MAP\n"; mapContent += "MAP\n";
// Map data // Map data
for (auto tile : map->data.mapTiles) { for (auto tile : map->data.mapTiles) {

View file

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

View file

@ -27,3 +27,13 @@ void PRenderPlayer(PPlayer *player) {
"Invalid player->facing direction, expected Up, Down, Left, or Right"); "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;
}