Skip to content

Commit

Permalink
collision system
Browse files Browse the repository at this point in the history
  • Loading branch information
Cadecraft committed Mar 23, 2024
1 parent a80deee commit 47b764a
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 81 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ add_executable(PlatScifi
src/renderer.h
src/worldstate.cpp
src/worldstate.h
src/gamestate.cpp
src/gamestate.h
src/worldobjects/redcube.h
src/worldobjects/bluecube.h
src/worldobjects/stationaryimage.h
src/worldobjects/player.h
src/worldobjects/staticcollider.h
)
target_link_libraries(PlatScifi PRIVATE sfml-graphics)
target_compile_features(PlatScifi PRIVATE cxx_std_17)
Expand Down
31 changes: 31 additions & 0 deletions src/gamestate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "gamestate.h"

void GameState::spawnObject(WorldObject* object) {
objects.push_back(object);
}

void GameState::update() {
for (WorldObject* object : objects) {
object->update(worldState, objects);
}
}

std::vector<WorldObject*>::iterator GameState::objectsBegin() {
return objects.begin();
}

std::vector<WorldObject*>::iterator GameState::objectsEnd() {
return objects.end();
}

void GameState::clear() {
while (!objects.empty()) {
// TODO: good memory freeing?
delete objects.back();
objects.pop_back();
}
}

GameState::~GameState() {
clear();
}
25 changes: 25 additions & 0 deletions src/gamestate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <vector>
#include "worldobject.h"
#include "worldstate.h"

// Store the full state of the world and all objects
class GameState {
private:
WorldState worldState;
std::vector<WorldObject*> objects;

public:
// Spawn an object
void spawnObject(WorldObject* object);
// Update
void update();
// Get all objects
std::vector<WorldObject*>::iterator objectsBegin();
std::vector<WorldObject*>::iterator objectsEnd();
// Clear all items
void clear();
// Destructor to free memory
~GameState();
};
51 changes: 31 additions & 20 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
#include "assethandler.h"
#include "renderer.h"
#include "renderdata.h"
#include "worldstate.h"
#include "gamestate.h"
#include "worldobject.h"
#include "worldobjects/redcube.h" // Debugging
#include "worldobjects/bluecube.h"
#include "worldobjects/stationaryimage.h"
#include "worldobjects/player.h"
#include "worldobjects/staticcollider.h"

// SFML Demo
int main() {
Expand All @@ -21,17 +22,24 @@ int main() {
// Main data and objects
AssetHandler assetHandler;
Renderer renderer(window, assetHandler);
WorldState worldState;
GameState gameState;
std::set<sf::Keyboard::Key> keysPressed;

// Main world objects
Player* player = new Player(4, 10);
worldState.spawnObject(player);
Player* player = new Player(5, 10);
gameState.spawnObject(player);

// Debug: create a red cube, blue cube, and image
worldState.spawnObject(new RedCube(0, 0));
worldState.spawnObject(new BlueCube(0, 0));
worldState.spawnObject(new StationaryImage(6, 6, 2, 2, "assets/tiv_logo.png"));
// Debug: create a red cube, blue cube, image, etc.
gameState.spawnObject(new RedCube(0, 0));
gameState.spawnObject(new BlueCube(0, 0));
gameState.spawnObject(new StationaryImage(6, 6, 2, 2, "assets/tiv_logo.png"));
// Bottom colliders
gameState.spawnObject(new StaticCollider(3, 25, 6, 2));
gameState.spawnObject(new StaticCollider(9, 27, 10, 2));
gameState.spawnObject(new StaticCollider(19, 25, 6, 2));
// Vertical colliders
gameState.spawnObject(new StaticCollider(0, 0, 2, 25));
gameState.spawnObject(new StaticCollider(25, 0, 2, 19));

// Main game loop
while (window.isOpen()) {
Expand All @@ -49,28 +57,31 @@ int main() {

// Use input
if (keysPressed.find(sf::Keyboard::A) != keysPressed.end()) {
player->move(-0.2, 0);
player->accelerate(-0.05, 0);
}
if (keysPressed.find(sf::Keyboard::D) != keysPressed.end()) {
player->move(0.2, 0);
player->accelerate(0.05, 0);
}
if (keysPressed.find(sf::Keyboard::W) != keysPressed.end()) {
player->move(0, -0.2);
if (
keysPressed.find(sf::Keyboard::W) != keysPressed.end()
|| keysPressed.find(sf::Keyboard::Space) != keysPressed.end()
) {
player->jump();
}
if (keysPressed.find(sf::Keyboard::S) != keysPressed.end()) {
player->move(0, 0.2);
player->accelerate(0, 0.05);
}
if (keysPressed.find(sf::Keyboard::Space) != keysPressed.end()) {
worldState.spawnObject(new BlueCube(player->getLocx(), player->getLocy()));
/*if () {
gameState.spawnObject(new BlueCube(player->getLocx(), player->getLocy()));
keysPressed.erase(sf::Keyboard::Space);
}
}*/

// Update the world
worldState.update();
// Update the game and world
gameState.update();

// Render the world
// Render the game and world
window.clear();
renderer.renderWorld(worldState);
renderer.renderWorldObjects(gameState);
window.display();
}
}
4 changes: 2 additions & 2 deletions src/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ void Renderer::renderFromData(RenderData& data) {
}
}

void Renderer::renderWorld(WorldState& worldState) {
void Renderer::renderWorldObjects(GameState& gameState) {
// todo: fix on mac/linux
for (std::vector<WorldObject*>::iterator it = worldState.objectsBegin(); it != worldState.objectsEnd(); it++) {
for (std::vector<WorldObject*>::iterator it = gameState.objectsBegin(); it != gameState.objectsEnd(); it++) {
renderFromData((*it)->getRenderData());
}
}
4 changes: 2 additions & 2 deletions src/renderer.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include <SFML/Graphics.hpp>
#include "worldstate.h"
#include "gamestate.h"
#include "renderdata.h"
#include "assethandler.h"

Expand All @@ -19,5 +19,5 @@ class Renderer {
void renderFromData(RenderData& data);

// Render the entire world
void renderWorld(WorldState& worldState);
void renderWorldObjects(GameState& worldState);
};
22 changes: 21 additions & 1 deletion src/worldobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,31 @@ WorldObject::WorldObject() {
height = 1.0;
}

UpdateResult WorldObject::update() {
UpdateResult WorldObject::update(WorldState& worldState, std::vector<WorldObject*>& objects) {
// Update
return UpdateResult::None;
}

double WorldObject::isPointInside(float x, float y) {
return (x >= locx && x < locx + width && y > locy && y < locy + height);
}

double WorldObject::getLocx() {
return locx;
}

double WorldObject::getLocy() {
return locy;
}

double WorldObject::getWidth() {
return width;
}

double WorldObject::getHeight() {
return height;
}

RenderData WorldObject::getRenderData() {
return {
RenderType::Rectangle,
Expand Down
17 changes: 11 additions & 6 deletions src/worldobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <vector>
#include "renderdata.h"
//#include "worldstate.h"
#include "worldstate.h"

// The result of an update function
enum class UpdateResult {
Expand All @@ -24,12 +24,17 @@ class WorldObject {
WorldObject();

// Update each frame
virtual UpdateResult update(/*WorldState& worldState*/);
virtual UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects);

// TODO: delete this function
/*void tester(std::vector<WorldObject*>& v) {
// Do stuff with v
}*/
// Get whether a point is inside of this object
double isPointInside(float x, float y);

double getLocx();
double getLocy();
double getWidth();
double getHeight();

// TODO: get whether a rectangle is inside of this object

// Return the results to render
virtual RenderData getRenderData();
Expand Down
2 changes: 1 addition & 1 deletion src/worldobjects/bluecube.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class BlueCube : public WorldObject {
}

// Override the update function
UpdateResult update() {
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
locx += velx;
if (locx > 64 || locx < 0) velx *= -1;
locy += vely;
Expand Down
52 changes: 46 additions & 6 deletions src/worldobjects/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@

// The data for the player
class Player : public WorldObject {
private:
float velx = 0;
float vely = 0;

public:
// Constructor
Player(double spawnx, double spawny) : WorldObject() {
locx = spawnx;
locy = spawny;
}

// Input: movement
// Input: acceleration
// TODO: accelerate instead of move
void move(double deltax, double deltay) {
locx += deltax;
locy += deltay;
void accelerate(double deltax, double deltay) {
velx += deltax;
vely += deltay;
}

// Input: jump
void jump() {
vely = -0.4;
}

double getLocx() {
Expand All @@ -26,8 +35,39 @@ class Player : public WorldObject {
return locy;
}

// Override update: do nothing (yet)
UpdateResult update() {
// Override update: gravity and acceleration
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
vely += worldState.getGravityStrength();
velx *= 0.96;
vely *= 0.96;
locx += velx;
locy += vely;
//if (velx < 0.01 && velx >= -0.01) velx = 0;
// Check collision
// todo: refactor
// todo: only check with types enabling collision
// todo: when hitting multiple?
for (WorldObject* object : objects) {
if (object == this) continue;
// X movement pushout
// todo: better way of doing the 0.1 thing
if (locy + height - 0.1 >= object->getLocy() && locy + 0.1 < object->getLocy() + object->getHeight()) {
// Within the y
if (locx + width > object->getLocx() && locx < object->getLocx() + object->getWidth()) {
// Side wall
locx -= velx;
velx = 0;
}
}
if (locx + width >= object->getLocx() && locx < object->getLocx() + object->getWidth()) {
// Within the x
if (locy + height > object->getLocy() && locy < object->getLocy() + object->getHeight()) {
// Floor/ceiling
locy -= vely;
vely = 0;
}
}
}
return UpdateResult::None;
}

Expand Down
2 changes: 1 addition & 1 deletion src/worldobjects/redcube.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class RedCube : public WorldObject {
}

// Override update: move right over time
UpdateResult update() {
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
locx += 0.1;
if (locx > 30) {
locy += 1;
Expand Down
35 changes: 35 additions & 0 deletions src/worldobjects/staticcollider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include "../worldobject.h"

// An object that does not move, but that other objects can collide with
class StaticCollider : public WorldObject {
public:
// Constructor
StaticCollider(double spawnx, double spawny, double width, double height) : WorldObject() {
locx = spawnx;
locy = spawny;
this->width = width;
this->height = height;
}

// Override update: gravity
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
return UpdateResult::None;
}

// Override rendering
RenderData getRenderData() {
// TODO: image/animations
return {
RenderType::Rectangle,
coordType,
locx,
locy,
width,
height,
{ 14, 92, 81 },
""
};
}
};
2 changes: 1 addition & 1 deletion src/worldobjects/stationaryimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class StationaryImage : public WorldObject {
}

// Override update: do nothing
UpdateResult update() {
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
return UpdateResult::None;
}

Expand Down
Loading

0 comments on commit 47b764a

Please sign in to comment.