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
[Window][Phoenix Map Editor]
Pos=1261,211
Pos=851,698
Size=556,101
Collapsed=0
[Window][Map Editor Tools]
Pos=3009,535
Size=338,211
Pos=1002,137
Size=357,247
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 mapScaleX; // Rendering scale
int mapScaleY; // Rendering scale
int mapPlayerSpawnX;
int mapPlayerSpawnY;
MapData data;
};

View file

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

View file

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

View file

@ -2,7 +2,8 @@ MAPNAME DMSCALE
MAPVERS 1
MAPAUTH Interfiber
MAPSIZE 10x10
MAPSCAL 2x2
MAPSCAL 3x3
MAPSPWN 32,32
MAP
TILE WALL
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
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");
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;
}