proper collision
This commit is contained in:
parent
83e312894b
commit
553ab7c1df
|
@ -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
32
include/collision.hpp
Normal 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);
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
54
src/collision.cpp
Normal 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;
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue