Skip to content

Commit

Permalink
refactor: cyclical dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
Cadecraft committed Apr 8, 2024
1 parent b80ca06 commit 075a011
Show file tree
Hide file tree
Showing 18 changed files with 226 additions and 200 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ add_executable(PlatScifi
src/renderer.h
src/worldstate.cpp
src/worldstate.h
src/gamestate.cpp
src/gamestate.h
src/worldspawner.cpp
src/worldspawner.h
src/worldobjectincludes.h
Expand All @@ -39,6 +37,9 @@ add_executable(PlatScifi
src/worldobjects/leveltp.h
src/worldobjects/spike.h
src/worldobjects/animal.cpp
src/worldobjects/player.cpp
src/gamestate.cpp
src/gamestate.h
)
target_link_libraries(PlatScifi PRIVATE sfml-graphics)
target_compile_features(PlatScifi PRIVATE cxx_std_17)
Expand Down
6 changes: 5 additions & 1 deletion src/gamestate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ UpdateResult GameState::update() {
// Update world objects
std::vector<WorldObject*> newToSpawn;
for (std::vector<WorldObject*>::iterator it = objects.begin(); it != objects.end();) {
UpdateResult updateResult = (*it)->update(worldState, objects);
UpdateResult updateResult = (*it)->update(*this);
if (updateResult == UpdateResult::NextLevel) {
// TODO: improve this
return UpdateResult::NextLevel;
Expand Down Expand Up @@ -58,6 +58,10 @@ std::string GameState::getNextLevelName() {
return nextLevelName;
}

WorldState& GameState::getWorldState() {
return worldState;
}

void GameState::updateLevelNames(std::string newLevelName, std::string newNextLevelName) {
levelName = newLevelName;
nextLevelName = newNextLevelName;
Expand Down
2 changes: 2 additions & 0 deletions src/gamestate.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class GameState {
std::string getLevelName();
// Get the next level name
std::string getNextLevelName();
// Get the current world state
WorldState& getWorldState();
// Update the current level name
void updateLevelNames(std::string newLevelName, std::string newNextLevelName);
// Add a UI message
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "assethandler.h"
#include "renderer.h"
#include "renderdata.h"
//class GameState;
#include "gamestate.h"
#include "worldspawner.h"
#include "worldobject.h"
Expand Down
8 changes: 7 additions & 1 deletion src/worldobject.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "worldobject.h"
#include "gamestate.h"

WorldObject::WorldObject() {
coordType = CoordType::World;
Expand All @@ -10,7 +11,7 @@ WorldObject::WorldObject() {
vely = 0.0;
}

UpdateResult WorldObject::update(WorldState& worldState, std::vector<WorldObject*>& objects) {
UpdateResult WorldObject::update(GameState& gameState) {
// Update
return UpdateResult::None;
}
Expand Down Expand Up @@ -43,6 +44,11 @@ double WorldObject::getVely() {
return vely;
}

// TODO: remove this debug
void WorldObject::debugCyclical(GameState& gameState) {
gameState.getLevelName();
}

bool WorldObject::hasAttribute(ObjectAttribute attribute) {
return objectAttributes.find(attribute) != objectAttributes.end();
}
Expand Down
7 changes: 6 additions & 1 deletion src/worldobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "renderdata.h"
#include "worldstate.h"

// To fix the cyclical dependency error
class GameState;

// The result of an update function
enum class UpdateResult {
None,
Expand Down Expand Up @@ -40,7 +43,7 @@ class WorldObject {
WorldObject();

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

// Get whether a point is inside of this object
double isPointInside(double x, double y);
Expand All @@ -52,6 +55,8 @@ class WorldObject {
double getVelx();
double getVely();

void debugCyclical(GameState& gameState);

bool hasAttribute(ObjectAttribute attribute);

// TODO: get whether a rectangle is inside of this object
Expand Down
91 changes: 91 additions & 0 deletions src/worldobjects/animal.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "animal.h"
#include "../gamestate.h"

// Define the default data for all named animals (<name, data>)
const std::map<std::string, AnimalData> Animal::animalDefaults = {
Expand Down Expand Up @@ -62,3 +63,93 @@ const std::map<std::string, AnimalData> Animal::animalDefaults = {
}
}
};

UpdateResult Animal::update(GameState& gameState) {
// AI Logic
UpdateResult updateResultToReturn = UpdateResult::None;
accelerate(moveRight ? 0.01 : -0.01, 0);
jump();
// Special named animal abilities
// TODO: change from stringly typed?
if (name == "replicator") {
// Replicate after 300 frames
if (frameCount >= 300) {
// Replicate
updateResultToReturn = UpdateResult::ReplicateAndDestroy;
} else if (frameCount >= 293) {
animFrameNum = 2;
} else if (frameCount >= 285) {
animFrameNum = 1;
}
}

// Physics
if (!LEVEL_DESIGN_MODE) {
vely += gameState.getWorldState().getGravityStrength();
}
velx *= 0.88;
vely *= 0.96;
locx += velx;
locy += vely;
// Check collision and update
onGround = false;
// TODO: refactor
// TODO: update all collisions from player
for (WorldObject* object : gameState.objects) {
if (object == this) continue;
bool collided = false;
bool overlapped = false;
if (object->hasAttribute(ObjectAttribute::Collision)) {
// X movement pushout
// todo: improve time complexity (O(n^2) :skull:)
// todo: better way of doing the 0.1 thing (subtract velocity instead?)
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;
collided = true;
overlapped = true;
// For AI
moveRight = !moveRight;
}
}
if (locx + width >= object->getLocx() && locx < object->getLocx() + object->getWidth()) {
// Within the x
if (locy + height > object->getLocy() && locy < object->getLocy() + object->getHeight()) {
if (locy > object->getLocy() + object->getHeight() / 2.0) {
// Ceiling
if (vely >= 0) {
// Already traveling down: do nothing
} else {
// Traveling up: stop
locy -= vely;
vely = 0;
}
collided = true;
overlapped = true;
} else {
// Floor
locy -= vely;
vely = 0;
collided = true;
overlapped = true;
// todo: should not be on ground on a bottom corner
onGround = true;
}
}
}
} else if (object->hasAttribute(ObjectAttribute::OverlapDetect)) {
// Check overlap only
if (locy + height >= object->getLocy() && locy < object->getLocy() + object->getHeight()) {
if (locx + width > object->getLocx() && locx < object->getLocx() + object->getWidth()) {
// Hit
overlapped = true;
}
}
}
}
// TODO: out of bounds respawn/death
return updateResultToReturn;
}
90 changes: 1 addition & 89 deletions src/worldobjects/animal.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,95 +98,7 @@ class Animal : public WorldObject {
}

// Override update: gravity and acceleration, and AI logic
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
// AI Logic
UpdateResult updateResultToReturn = UpdateResult::None;
accelerate(moveRight ? 0.01 : -0.01, 0);
jump();
// Special named animal abilities
// TODO: change from stringly typed?
if (name == "replicator") {
// Replicate after 300 frames
if (frameCount >= 300) {
// Replicate
updateResultToReturn = UpdateResult::ReplicateAndDestroy;
} else if (frameCount >= 293) {
animFrameNum = 2;
} else if (frameCount >= 285) {
animFrameNum = 1;
}
}

// Physics
if (!LEVEL_DESIGN_MODE) {
vely += worldState.getGravityStrength();
}
velx *= 0.88;
vely *= 0.96;
locx += velx;
locy += vely;
// Check collision and update
onGround = false;
// TODO: refactor
// TODO: update all collisions from player
for (WorldObject* object : objects) {
if (object == this) continue;
bool collided = false;
bool overlapped = false;
if (object->hasAttribute(ObjectAttribute::Collision)) {
// X movement pushout
// todo: improve time complexity (O(n^2) :skull:)
// todo: better way of doing the 0.1 thing (subtract velocity instead?)
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;
collided = true;
overlapped = true;
// For AI
moveRight = !moveRight;
}
}
if (locx + width >= object->getLocx() && locx < object->getLocx() + object->getWidth()) {
// Within the x
if (locy + height > object->getLocy() && locy < object->getLocy() + object->getHeight()) {
if (locy > object->getLocy() + object->getHeight() / 2.0) {
// Ceiling
if (vely >= 0) {
// Already traveling down: do nothing
} else {
// Traveling up: stop
locy -= vely;
vely = 0;
}
collided = true;
overlapped = true;
} else {
// Floor
locy -= vely;
vely = 0;
collided = true;
overlapped = true;
// todo: should not be on ground on a bottom corner
onGround = true;
}
}
}
} else if (object->hasAttribute(ObjectAttribute::OverlapDetect)) {
// Check overlap only
if (locy + height >= object->getLocy() && locy < object->getLocy() + object->getHeight()) {
if (locx + width > object->getLocx() && locx < object->getLocx() + object->getWidth()) {
// Hit
overlapped = true;
}
}
}
}
// TODO: out of bounds respawn/death
return updateResultToReturn;
}
UpdateResult update(GameState& gameState);

// Override rendering
RenderData getRenderData() {
Expand Down
4 changes: 2 additions & 2 deletions src/worldobjects/bluecube.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class BlueCube : public WorldObject {
objectAttributes.insert(ObjectAttribute::Collision);
}

// Override the update function
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
// Override update: bounce around the screen
UpdateResult update(GameState& gameState) {
locx += velx;
if (locx > 64 || locx < 0) velx *= -1;
locy += vely;
Expand Down
6 changes: 3 additions & 3 deletions src/worldobjects/leveltp.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ class LevelTp : public WorldObject {
this->objectAttributes.insert(ObjectAttribute::LevelTeleport);
}

// Override update: check with player
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
// TODO: stuff
// Override update: check with player ?
UpdateResult update(GameState& gameState) {
// TODO: stuff
return UpdateResult::None;
}

Expand Down
4 changes: 2 additions & 2 deletions src/worldobjects/movingcollider.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class MovingCollider : public WorldObject {
objectAttributes.insert(ObjectAttribute::Collision);
}

// Override update: gravity
UpdateResult update(WorldState& worldState, std::vector<WorldObject*>& objects) {
// Override update: interpolation
UpdateResult update(GameState& gameState) {
double alpha = sin(2 * 3.14159 * frameCount / periodFrames) * 0.5 + 0.5;
// Interpolate between positions
double locxnew = spawnx * (1.0 - alpha) + targetx * (alpha);
Expand Down
Loading

0 comments on commit 075a011

Please sign in to comment.