From 879c2c04d9c3879f871cfe79f9b25fd23c5184b4 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 11 Jun 2015 11:38:49 -0400 Subject: Wrote EntityManager --- CMakeLists.txt | 14 -- src/component.h | 7 + src/components/ai.cpp | 142 ------------------- src/components/ai.h | 73 ---------- src/components/map_collision.cpp | 241 -------------------------------- src/components/map_collision.h | 47 ------- src/components/map_render.cpp | 40 ------ src/components/map_render.h | 19 --- src/components/physics_body.cpp | 66 --------- src/components/physics_body.h | 20 --- src/components/player_physics.cpp | 118 ---------------- src/components/player_physics.h | 25 ---- src/components/player_sprite.cpp | 60 -------- src/components/player_sprite.h | 23 --- src/components/simple_collider.cpp | 14 -- src/components/simple_collider.h | 18 --- src/components/static_image.cpp | 11 -- src/components/static_image.h | 18 --- src/components/user_movement.cpp | 100 ------------- src/components/user_movement.h | 19 --- src/entity.cpp | 46 ------ src/entity.h | 64 --------- src/entity_manager.h | 279 +++++++++++++++++++++++++++++++++++++ src/entityfactory.cpp | 182 ------------------------ src/entityfactory.h | 15 -- src/game.cpp | 178 ----------------------- src/game.h | 45 ------ src/main.cpp | 12 +- src/map.cpp | 151 -------------------- src/map.h | 70 ---------- src/world.cpp | 150 -------------------- src/world.h | 21 --- 32 files changed, 294 insertions(+), 1994 deletions(-) create mode 100644 src/component.h delete mode 100644 src/components/ai.cpp delete mode 100644 src/components/ai.h delete mode 100644 src/components/map_collision.cpp delete mode 100644 src/components/map_collision.h delete mode 100644 src/components/map_render.cpp delete mode 100644 src/components/map_render.h delete mode 100644 src/components/physics_body.cpp delete mode 100644 src/components/physics_body.h delete mode 100644 src/components/player_physics.cpp delete mode 100644 src/components/player_physics.h delete mode 100644 src/components/player_sprite.cpp delete mode 100644 src/components/player_sprite.h delete mode 100644 src/components/simple_collider.cpp delete mode 100644 src/components/simple_collider.h delete mode 100644 src/components/static_image.cpp delete mode 100644 src/components/static_image.h delete mode 100644 src/components/user_movement.cpp delete mode 100644 src/components/user_movement.h delete mode 100644 src/entity.cpp delete mode 100644 src/entity.h create mode 100644 src/entity_manager.h delete mode 100644 src/entityfactory.cpp delete mode 100644 src/entityfactory.h delete mode 100644 src/game.cpp delete mode 100644 src/game.h delete mode 100644 src/map.cpp delete mode 100644 src/map.h delete mode 100644 src/world.cpp delete mode 100644 src/world.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0af1fa2..5dfce6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,22 +47,8 @@ include_directories( set(CMAKE_BUILD_TYPE Debug) add_executable(Aromatherapy src/main.cpp - src/map.cpp src/renderer.cpp - src/entity.cpp - src/game.cpp src/muxer.cpp - src/entityfactory.cpp - src/world.cpp - src/components/ai.cpp - src/components/map_collision.cpp - src/components/map_render.cpp - src/components/physics_body.cpp - src/components/player_physics.cpp - src/components/player_sprite.cpp - src/components/simple_collider.cpp - src/components/static_image.cpp - src/components/user_movement.cpp ) target_link_libraries(Aromatherapy ${ALL_LIBS}) install(TARGETS Aromatherapy RUNTIME DESTINATION ${BIN_DIR}) diff --git a/src/component.h b/src/component.h new file mode 100644 index 0000000..2cbdc9d --- /dev/null +++ b/src/component.h @@ -0,0 +1,7 @@ +#ifndef COMPONENT_H_F0CE4573 +#define COMPONENT_H_F0CE4573 + +class Component { +}; + +#endif /* end of include guard: COMPONENT_H_F0CE4573 */ diff --git a/src/components/ai.cpp b/src/components/ai.cpp deleted file mode 100644 index 9f8c764..0000000 --- a/src/components/ai.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "ai.h" -#include -#include "entity.h" - -void AIActionContainer::addAction(std::shared_ptr action) -{ - actions.push_back(action); -} - -void AIActionContainer::start(Game& game, Entity& entity) -{ - currentAction = begin(actions); - - if (currentAction != end(actions)) - { - (*currentAction)->start(game, entity); - } -} - -void AIActionContainer::perform(Game& game, Entity& entity, double dt) -{ - if (!isDone()) - { - (*currentAction)->perform(game, entity, dt); - - if ((*currentAction)->isDone()) - { - currentAction++; - - if (!isDone()) - { - (*currentAction)->start(game, entity); - } - } - } -} - -bool AIActionContainer::isDone() const -{ - return currentAction == end(actions); -} - -AI::AI(int chance) -{ - this->chance = chance; -} - -int AI::getChance() const -{ - return chance; -} - -AI& AIComponent::emplaceAI(int chance) -{ - maxChance += chance; - ais.emplace_back(chance); - - return ais.back(); -} - -void AIComponent::tick(Game& game, Entity& entity, double dt) -{ - if (currentAI == nullptr) - { - int toChoose = rand() % maxChance; - for (auto& ai : ais) - { - if (toChoose < ai.getChance()) - { - currentAI = &ai; - break; - } else { - toChoose -= ai.getChance(); - } - } - - if (currentAI != nullptr) - { - currentAI->start(game, entity); - } - } - - if (currentAI != nullptr) - { - currentAI->perform(game, entity, dt); - - if (currentAI->isDone()) - { - currentAI = nullptr; - } - } -} - -MoveAIAction::MoveAIAction(Direction dir, int len, int speed) -{ - this->dir = dir; - this->len = len; - this->speed = speed; -} - -void MoveAIAction::start(Game& game, Entity& entity) -{ - remaining = len; -} - -void MoveAIAction::perform(Game&, Entity& entity, double dt) -{ - double dist = dt * speed; - remaining -= dist; - - switch (dir) - { - case Direction::Left: - { - entity.position.first -= dist; - break; - } - - case Direction::Right: - { - entity.position.first += dist; - break; - } - - case Direction::Up: - { - entity.position.second -= dist; - break; - } - - case Direction::Down: - { - entity.position.second += dist; - break; - } - } -} - -bool MoveAIAction::isDone() const -{ - return remaining <= 0.0; -} diff --git a/src/components/ai.h b/src/components/ai.h deleted file mode 100644 index 840283b..0000000 --- a/src/components/ai.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef AI_H -#define AI_H - -#include -#include -#include -#include - -#include "entity.h" - -class AIAction { - public: - virtual void start(Game& game, Entity& entity) = 0; - virtual void perform(Game& game, Entity& entity, double dt) = 0; - virtual bool isDone() const = 0; -}; - -class AIActionContainer { - public: - void addAction(std::shared_ptr action); - virtual void start(Game& game, Entity& entity); - virtual void perform(Game& game, Entity& entity, double dt); - virtual bool isDone() const; - - private: - std::list> actions; - std::list>::iterator currentAction {end(actions)}; -}; - -class AI : public AIActionContainer { - public: - AI(int chance); - - int getChance() const; - - private: - int chance; -}; - -class AIComponent : public Component { - public: - AI& emplaceAI(int chance); - void tick(Game& game, Entity& entity, double dt); - - private: - int maxChance = 0; - std::list ais; - AI* currentAI = nullptr; -}; - -class MoveAIAction : public AIAction { - public: - enum class Direction { - Left, - Right, - Up, - Down - }; - - MoveAIAction(Direction dir, int len, int speed); - - void start(Game& game, Entity& entity); - void perform(Game& game, Entity& entity, double dt); - bool isDone() const; - - private: - Direction dir; - int len; - int speed; - double remaining; -}; - -#endif /* end of include guard: AI_H */ diff --git a/src/components/map_collision.cpp b/src/components/map_collision.cpp deleted file mode 100644 index 3ad574b..0000000 --- a/src/components/map_collision.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "map_collision.h" -#include "map.h" -#include "game.h" -#include "consts.h" - -MapCollisionComponent::MapCollisionComponent(const Map& map) : map(map) -{ - addCollision(-6, 0, MAP_HEIGHT*TILE_HEIGHT, Direction::left, collisionFromMoveType(map.getAdjacent(Map::MoveDir::Left).type)); - addCollision(GAME_WIDTH+6, 0, MAP_HEIGHT*TILE_HEIGHT, Direction::right, collisionFromMoveType(map.getAdjacent(Map::MoveDir::Right).type)); - addCollision(-6, 0, GAME_WIDTH, Direction::up, collisionFromMoveType(map.getAdjacent(Map::MoveDir::Up).type)); - addCollision(MAP_HEIGHT*TILE_HEIGHT+6, 0, GAME_WIDTH, Direction::down, collisionFromMoveType(map.getAdjacent(Map::MoveDir::Down).type)); - - for (int i=0; i 0) && (tile < 28) && (!((tile >= 5) && (tile <= 7)))) - { - addCollision(x*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, Direction::right, Collision::Type::wall); - addCollision((x+1)*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, Direction::left, Collision::Type::wall); - addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::wall); - addCollision((y+1)*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::up, Collision::Type::wall); - } else if ((tile >= 5) && (tile <= 7)) - { - addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::platform); - } else if (tile == 42) - { - addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::danger); - } - } -} - -void MapCollisionComponent::addCollision(double axis, double lower, double - upper, Direction dir, Collision::Type type) -{ - std::list::iterator it; - - switch (dir) - { - case Direction::up: - it = up_collisions.begin(); - for (; it!=up_collisions.end(); it++) - { - if (it->axis < axis) break; - } - - up_collisions.insert(it, {axis, lower, upper, type}); - - break; - case Direction::down: - it = down_collisions.begin(); - for (; it!=down_collisions.end(); it++) - { - if (it->axis > axis) break; - } - - down_collisions.insert(it, {axis, lower, upper, type}); - - break; - case Direction::left: - it = left_collisions.begin(); - for (; it!=left_collisions.end(); it++) - { - if (it->axis < axis) break; - } - - left_collisions.insert(it, {axis, lower, upper, type}); - - break; - case Direction::right: - it = right_collisions.begin(); - for (; it!=right_collisions.end(); it++) - { - if (it->axis > axis) break; - } - - right_collisions.insert(it, {axis, lower, upper, type}); - - break; - } -} - -void MapCollisionComponent::detectCollision(Game& game, Entity&, Entity& collider, std::pair old_position) -{ - if (collider.position.first < old_position.first) - { - for (auto collision : left_collisions) - { - if (collision.axis > old_position.first) continue; - if (collision.axis < collider.position.first) break; - - if ((old_position.second+collider.size.second > collision.lower) && (old_position.second < collision.upper)) - { - // We have a collision! - processCollision(game, collider, collision, Direction::left, old_position); - - break; - } - } - } else if (collider.position.first > old_position.first) - { - for (auto collision : right_collisions) - { - if (collision.axis < old_position.first+collider.size.first) continue; - if (collision.axis > collider.position.first+collider.size.first) break; - - if ((old_position.second+collider.size.second > collision.lower) && (old_position.second < collision.upper)) - { - // We have a collision! - processCollision(game, collider, collision, Direction::right, old_position); - - break; - } - } - } - - if (collider.position.second < old_position.second) - { - for (auto collision : up_collisions) - { - if (collision.axis > old_position.second) continue; - if (collision.axis < collider.position.second) break; - - if ((collider.position.first+collider.size.first > collision.lower) && (collider.position.first < collision.upper)) - { - // We have a collision! - processCollision(game, collider, collision, Direction::up, old_position); - - break; - } - } - } else if (collider.position.second > old_position.second) - { - for (auto collision : down_collisions) - { - if (collision.axis < old_position.second+collider.size.second) continue; - if (collision.axis > collider.position.second+collider.size.second) break; - - if ((collider.position.first+collider.size.first > collision.lower) && (collider.position.first < collision.upper)) - { - // We have a collision! - processCollision(game, collider, collision, Direction::down, old_position); - - break; - } - } - } -} - -void MapCollisionComponent::processCollision(Game& game, Entity& collider, Collision collision, Direction dir, std::pair old_position) -{ - if (collision.type == Collision::Type::wall) - { - if (dir == Direction::left) - { - collider.position.first = collision.axis; - - Message msg(Message::Type::setHorizontalVelocity); - msg.velocity = 0.0; - collider.send(game, msg); - } else if (dir == Direction::right) - { - collider.position.first = collision.axis - collider.size.first; - - Message msg(Message::Type::setHorizontalVelocity); - msg.velocity = 0.0; - collider.send(game, msg); - } else if (dir == Direction::up) - { - collider.position.second = collision.axis; - - Message msg(Message::Type::setVerticalVelocity); - msg.velocity = 0.0; - collider.send(game, msg); - } else if (dir == Direction::down) - { - collider.position.second = collision.axis - collider.size.second; - collider.send(game, Message::Type::hitTheGround); - } - } else if (collision.type == Collision::Type::wrap) - { - if (dir == Direction::left) - { - collider.position.first = GAME_WIDTH-collider.size.first/2; - } else if (dir == Direction::right) - { - collider.position.first = -collider.size.first/2; - } else if (dir == Direction::up) - { - collider.position.second = GAME_HEIGHT-collider.size.second/2-1; - } else if (dir == Direction::down) - { - collider.position.second = -collider.size.second/2; - } - } else if (collision.type == Collision::Type::teleport) - { - if (dir == Direction::left) - { - game.loadMap(game.getWorld().getMap(map.getAdjacent(Map::MoveDir::Left).map), std::make_pair(GAME_WIDTH-collider.size.first/2, old_position.second)); - } else if (dir == Direction::right) - { - game.loadMap(game.getWorld().getMap(map.getAdjacent(Map::MoveDir::Right).map), std::make_pair(-collider.size.first/2, old_position.second)); - } else if (dir == Direction::up) - { - game.loadMap(game.getWorld().getMap(map.getAdjacent(Map::MoveDir::Up).map), std::make_pair(old_position.first, MAP_HEIGHT*TILE_HEIGHT-collider.size.second/2)); - } else if (dir == Direction::down) - { - game.loadMap(game.getWorld().getMap(map.getAdjacent(Map::MoveDir::Down).map), std::make_pair(old_position.first, -collider.size.second/2)); - } - } else if (collision.type == Collision::Type::reverse) - { - // TODO reverse - if (dir == Direction::right) - { - collider.position.first = collision.axis - collider.size.first; - collider.send(game, Message::Type::walkLeft); - } - } else if (collision.type == Collision::Type::platform) - { - Message msg(Message::Type::drop); - msg.dropAxis = collision.axis; - - collider.send(game, msg); - } else if (collision.type == Collision::Type::danger) - { - game.playerDie(); - } -} - -MapCollisionComponent::Collision::Type MapCollisionComponent::collisionFromMoveType(Map::MoveType type) -{ - switch (type) - { - case Map::MoveType::Wall: return Collision::Type::wall; - case Map::MoveType::Wrap: return Collision::Type::wrap; - case Map::MoveType::Warp: return Collision::Type::teleport; - case Map::MoveType::ReverseWarp: return Collision::Type::reverse; - } -} diff --git a/src/components/map_collision.h b/src/components/map_collision.h deleted file mode 100644 index 18b9397..0000000 --- a/src/components/map_collision.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef MAP_COLLISION_H -#define MAP_COLLISION_H - -#include "entity.h" -#include "map.h" -#include - -class Game; - -class MapCollisionComponent : public Component { - public: - MapCollisionComponent(const Map& map); - void detectCollision(Game& game, Entity& entity, Entity& collider, std::pair old_position); - - private: - enum class Direction { - up, left, down, right - }; - - struct Collision { - enum class Type { - wall, - wrap, - teleport, - reverse, - platform, - danger - }; - - double axis; - double lower; - double upper; - Type type; - }; - - void addCollision(double axis, double lower, double upper, Direction dir, Collision::Type type); - void processCollision(Game& game, Entity& collider, Collision collision, Direction dir, std::pair old_position); - Collision::Type collisionFromMoveType(Map::MoveType type); - - std::list left_collisions; - std::list right_collisions; - std::list up_collisions; - std::list down_collisions; - const Map& map; -}; - -#endif diff --git a/src/components/map_render.cpp b/src/components/map_render.cpp deleted file mode 100644 index 45766e1..0000000 --- a/src/components/map_render.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "map_render.h" -#include "map.h" -#include "game.h" -#include "consts.h" - -MapRenderComponent::MapRenderComponent(const Map& map) : screen(GAME_WIDTH, GAME_HEIGHT) -{ - screen.fill(screen.entirety(), 0, 0, 0); - - Texture tiles("res/tiles.png"); - - for (int i=0; i 0) - { - screen.blit(tiles, src, dst); - } - } - - Texture font("res/font.bmp"); - std::string map_name = map.getTitle(); - int start_x = (40/2) - (map_name.length()/2); - for (size_t i=0; i TERMINAL_VELOCITY_X) velocity.first = TERMINAL_VELOCITY_X; - if (velocity.second < -TERMINAL_VELOCITY_Y) velocity.second = -TERMINAL_VELOCITY_Y; - if (velocity.second > TERMINAL_VELOCITY_Y) velocity.second = TERMINAL_VELOCITY_Y; - - // Do the movement - entity.position.first += velocity.first * dt; - entity.position.second += velocity.second * dt; -} - -void PhysicsBodyComponent::detectCollision(Game& game, Entity& entity, Entity& collider, std::pair old_position) -{ - // If already colliding, do nothing! - if ((old_position.first + collider.size.first > entity.position.first) - && (old_position.first < entity.position.first + entity.size.first) - && (old_position.second + collider.size.second > entity.position.second) - && (old_position.second < entity.position.second + entity.size.second)) - { - return; - } - - // If newly colliding, SHOCK AND HORROR! - if ((collider.position.first + collider.size.first > entity.position.first) - && (collider.position.first < entity.position.first + entity.size.first) - && (collider.position.second + collider.size.second > entity.position.second) - && (collider.position.second < entity.position.second + entity.size.second)) - { - Message msg(Message::Type::collision); - msg.collisionEntity = &collider; - - entity.send(game, msg); - } -} diff --git a/src/components/physics_body.h b/src/components/physics_body.h deleted file mode 100644 index 079cc51..0000000 --- a/src/components/physics_body.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef PHYSICS_BODY_H -#define PHYSICS_BODY_H - -#include "entity.h" -#include - -class Game; - -class PhysicsBodyComponent : public Component { - public: - void receive(Game& game, Entity& entity, const Message& msg); - void tick(Game& game, Entity& entity, double dt); - void detectCollision(Game& game, Entity& entity, Entity& collider, std::pair old_position); - - protected: - std::pair velocity; - std::pair accel; -}; - -#endif diff --git a/src/components/player_physics.cpp b/src/components/player_physics.cpp deleted file mode 100644 index 40e9948..0000000 --- a/src/components/player_physics.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "player_physics.h" -#include "muxer.h" -#include "game.h" -#include "consts.h" - -#define JUMP_VELOCITY(h, l) (-2 * (h) / (l)) -#define JUMP_GRAVITY(h, l) (2 * ((h) / (l)) / (l)) - -PlayerPhysicsComponent::PlayerPhysicsComponent() -{ - jump_velocity = JUMP_VELOCITY(TILE_HEIGHT*4.5, 0.3); - jump_gravity = JUMP_GRAVITY(TILE_HEIGHT*4.5, 0.3); - jump_gravity_short = JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233); - - accel.second = jump_gravity_short; -} - -void PlayerPhysicsComponent::receive(Game&, Entity& entity, const Message& msg) -{ - if (msg.type == Message::Type::walkLeft) - { - velocity.first = -90; - direction = -1; - } else if (msg.type == Message::Type::walkRight) - { - velocity.first = 90; - direction = 1; - } else if (msg.type == Message::Type::stopWalking) - { - velocity.first = 0.0; - direction = 0; - } else if (msg.type == Message::Type::setHorizontalVelocity) - { - velocity.first = msg.velocity; - } else if (msg.type == Message::Type::setVerticalVelocity) - { - velocity.second = msg.velocity; - } else if (msg.type == Message::Type::hitTheGround) - { - if (isFalling) - { - playSound("res/Randomize27.wav", 0.05); - isFalling = false; - } - - velocity.second = 0.0; - } else if (msg.type == Message::Type::jump) - { - playSound("res/Randomize87.wav", 0.25); - - velocity.second = jump_velocity; - accel.second = jump_gravity; - } else if (msg.type == Message::Type::stopJump) - { - accel.second = jump_gravity_short; - } else if (msg.type == Message::Type::canDrop) - { - canDrop = true; - } else if (msg.type == Message::Type::cantDrop) - { - canDrop = false; - } else if (msg.type == Message::Type::drop) - { - if (canDrop) - { - canDrop = false; - } else { - entity.position.second = msg.dropAxis - entity.size.second; - velocity.second = 0; - } - } else if (msg.type == Message::Type::die) - { - frozen = true; - } else if (msg.type == Message::Type::stopDying) - { - frozen = false; - } -} - -void PlayerPhysicsComponent::tick(Game& game, Entity& entity, double dt) -{ - // If frozen, do nothing - if (frozen) - { - return; - } - - // Continue walking even if blocked earlier - if (velocity.first == 0) - { - if (direction < 0) - { - velocity.first = -90; - } else if (direction > 0) - { - velocity.first = 90; - } - } - - // Increase gravity at the height of jump - if ((accel.second == jump_gravity) && (velocity.second >= 0)) - { - accel.second = jump_gravity_short; - } - - // Do the movement - std::pair old_position = entity.position; - PhysicsBodyComponent::tick(game, entity, dt); - - // Check for collisions - game.detectCollision(entity, old_position); - - // Are we moving due to gravity? - if (velocity.second != 0.0) - { - isFalling = true; - } -} diff --git a/src/components/player_physics.h b/src/components/player_physics.h deleted file mode 100644 index 26f1fae..0000000 --- a/src/components/player_physics.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PLAYER_PHYSICS_H -#define PLAYER_PHYSICS_H - -#include "entity.h" -#include "physics_body.h" - -class Game; - -class PlayerPhysicsComponent : public PhysicsBodyComponent { - public: - PlayerPhysicsComponent(); - void tick(Game& game, Entity& entity, double dt); - void receive(Game& game, Entity& entity, const Message& msg); - - private: - double jump_velocity; - double jump_gravity; - double jump_gravity_short; - int direction = 0; - bool canDrop = false; - bool frozen = false; - bool isFalling = false; -}; - -#endif diff --git a/src/components/player_sprite.cpp b/src/components/player_sprite.cpp deleted file mode 100644 index 452a940..0000000 --- a/src/components/player_sprite.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "player_sprite.h" - -PlayerSpriteComponent::PlayerSpriteComponent() : sprite("res/Starla.png") -{ - -} - -void PlayerSpriteComponent::render(Game&, Entity& entity, Texture& buffer) -{ - animFrame++; - - int frame = 0; - if (isMoving) - { - frame += 2; - - if (animFrame % 20 < 10) - { - frame += 2; - } - } - - if (facingLeft) - { - frame++; - } - - double alpha = 1.0; - if (dying && (animFrame % 4 < 2)) - { - alpha = 0.0; - } - - Rectangle src_rect {frame*10, 0, 10, 12}; - Rectangle dst_rect {(int) entity.position.first, (int) entity.position.second, entity.size.first, entity.size.second}; - buffer.blit(sprite, src_rect, dst_rect, alpha); -} - -void PlayerSpriteComponent::receive(Game&, Entity&, const Message& msg) -{ - if (msg.type == Message::Type::walkLeft) - { - facingLeft = true; - isMoving = true; - } else if (msg.type == Message::Type::walkRight) - { - facingLeft = false; - isMoving = true; - } else if (msg.type == Message::Type::stopWalking) - { - isMoving = false; - } else if (msg.type == Message::Type::die) - { - dying = true; - isMoving = false; - } else if (msg.type == Message::Type::stopDying) - { - dying = false; - } -} diff --git a/src/components/player_sprite.h b/src/components/player_sprite.h deleted file mode 100644 index b1ac0af..0000000 --- a/src/components/player_sprite.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef PLAYER_SPRITE_H -#define PLAYER_SPRITE_H - -#include "entity.h" -#include "renderer.h" - -class Game; - -class PlayerSpriteComponent : public Component { - public: - PlayerSpriteComponent(); - void render(Game& game, Entity& entity, Texture& buffer); - void receive(Game& game, Entity& entity, const Message& msg); - - private: - Texture sprite; - int animFrame = 0; - bool facingLeft = false; - bool isMoving = false; - bool dying = false; -}; - -#endif diff --git a/src/components/simple_collider.cpp b/src/components/simple_collider.cpp deleted file mode 100644 index f4b414e..0000000 --- a/src/components/simple_collider.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "simple_collider.h" - -SimpleColliderComponent::SimpleColliderComponent(std::function callback) : callback(callback) -{ - -} - -void SimpleColliderComponent::receive(Game& game, Entity&, const Message& msg) -{ - if (msg.type == Message::Type::collision) - { - callback(game, *msg.collisionEntity); - } -} diff --git a/src/components/simple_collider.h b/src/components/simple_collider.h deleted file mode 100644 index 15d78cf..0000000 --- a/src/components/simple_collider.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef SIMPLE_COLLIDER_H -#define SIMPLE_COLLIDER_H - -#include "entity.h" -#include - -class Game; - -class SimpleColliderComponent : public Component { - public: - SimpleColliderComponent(std::function callback); - void receive(Game& game, Entity& entity, const Message& msg); - - private: - std::function callback; -}; - -#endif diff --git a/src/components/static_image.cpp b/src/components/static_image.cpp deleted file mode 100644 index 9fa8dca..0000000 --- a/src/components/static_image.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "static_image.h" - -StaticImageComponent::StaticImageComponent(const char* filename) : sprite(Texture(filename)) -{ - -} - -void StaticImageComponent::render(Game&, Entity& entity, Texture& buffer) -{ - buffer.blit(sprite, sprite.entirety(), {(int) entity.position.first, (int) entity.position.second, entity.size.first, entity.size.second}); -} diff --git a/src/components/static_image.h b/src/components/static_image.h deleted file mode 100644 index 2dec78b..0000000 --- a/src/components/static_image.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef STATIC_IMAGE_H -#define STATIC_IMAGE_H - -#include "entity.h" -#include "renderer.h" - -class Game; - -class StaticImageComponent : public Component { - public: - StaticImageComponent(const char* filename); - void render(Game& game, Entity& entity, Texture& buffer); - - private: - Texture sprite; -}; - -#endif diff --git a/src/components/user_movement.cpp b/src/components/user_movement.cpp deleted file mode 100644 index e499fee..0000000 --- a/src/components/user_movement.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "user_movement.h" -#include "renderer.h" - -void UserMovementComponent::input(Game& game, Entity& entity, int key, int action) -{ - if (action == GLFW_PRESS) - { - if (key == GLFW_KEY_LEFT) - { - holdingLeft = true; - - if (!frozen) - { - entity.send(game, Message::Type::walkLeft); - } - } else if (key == GLFW_KEY_RIGHT) - { - holdingRight = true; - - if (!frozen) - { - entity.send(game, Message::Type::walkRight); - } - } else if (key == GLFW_KEY_UP) - { - if (!frozen) - { - entity.send(game, Message::Type::jump); - } - } else if (key == GLFW_KEY_DOWN) - { - if (!frozen) - { - entity.send(game, Message::Type::canDrop); - } - } - } else if (action == GLFW_RELEASE) - { - if (key == GLFW_KEY_LEFT) - { - holdingLeft = false; - - if (!frozen) - { - if (holdingRight) - { - entity.send(game, Message::Type::walkRight); - } else { - entity.send(game, Message::Type::stopWalking); - } - } - } else if (key == GLFW_KEY_RIGHT) - { - holdingRight = false; - - if (!frozen) - { - if (holdingLeft) - { - entity.send(game, Message::Type::walkLeft); - } else { - entity.send(game, Message::Type::stopWalking); - } - } - } else if (key == GLFW_KEY_DOWN) - { - if (!frozen) - { - entity.send(game, Message::Type::cantDrop); - } - } else if (key == GLFW_KEY_UP) - { - if (!frozen) - { - entity.send(game, Message::Type::stopJump); - } - } - } -} - -void UserMovementComponent::receive(Game& game, Entity& entity, const Message& msg) -{ - if (msg.type == Message::Type::die) - { - frozen = true; - - entity.send(game, Message::Type::stopWalking); - } else if (msg.type == Message::Type::stopDying) - { - frozen = false; - - if (holdingLeft) - { - entity.send(game, Message::Type::walkLeft); - } else if (holdingRight) - { - entity.send(game, Message::Type::walkRight); - } - } -} diff --git a/src/components/user_movement.h b/src/components/user_movement.h deleted file mode 100644 index 1bcf05e..0000000 --- a/src/components/user_movement.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef USER_MOVEMENT_H -#define USER_MOVEMENT_H - -#include "entity.h" - -class Game; - -class UserMovementComponent : public Component { - public: - void input(Game& game, Entity& entity, int key, int action); - void receive(Game&, Entity&, const Message& msg); - - private: - bool holdingLeft = false; - bool holdingRight = false; - bool frozen = false; -}; - -#endif diff --git a/src/entity.cpp b/src/entity.cpp deleted file mode 100644 index 2b6cd7f..0000000 --- a/src/entity.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "entity.h" - -void Entity::addComponent(std::shared_ptr c) -{ - components.push_back(c); -} - -void Entity::send(Game& game, const Message& msg) -{ - for (auto component : components) - { - component->receive(game, *this, msg); - } -} - -void Entity::tick(Game& game, double dt) -{ - for (auto component : components) - { - component->tick(game, *this, dt); - } -} - -void Entity::input(Game& game, int key, int action) -{ - for (auto component : components) - { - component->input(game, *this, key, action); - } -} - -void Entity::render(Game& game, Texture& buffer) -{ - for (auto component : components) - { - component->render(game, *this, buffer); - } -} - -void Entity::detectCollision(Game& game, Entity& collider, std::pair old_position) -{ - for (auto component : components) - { - component->detectCollision(game, *this, collider, old_position); - } -} diff --git a/src/entity.h b/src/entity.h deleted file mode 100644 index 7f09f2d..0000000 --- a/src/entity.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef ENTITY_H -#define ENTITY_H - -#include -#include "renderer.h" - -class Game; -class Map; -class Entity; -class Component; - -class Message { - public: - enum class Type { - walkLeft, - walkRight, - stopWalking, - setHorizontalVelocity, - setVerticalVelocity, - collision, - jump, - stopJump, - drop, - canDrop, - cantDrop, - die, - stopDying, - hitTheGround - }; - - Message(Type type) : type(type) {} - - Type type; - Entity* collisionEntity; - int dropAxis; - double velocity; -}; - -class Entity { - public: - void addComponent(std::shared_ptr c); - void send(Game& game, const Message& msg); - void tick(Game& game, double dt); - void input(Game& game, int key, int action); - void render(Game& game, Texture& buffer); - void detectCollision(Game& game, Entity& collider, std::pair old_position); - - std::pair position; - std::pair size; - - private: - std::list> components; -}; - -class Component { - public: - virtual void receive(Game&, Entity&, const Message&) {} - virtual void render(Game&, Entity&, Texture&) {} - virtual void tick(Game&, Entity&, double) {} - virtual void input(Game&, Entity&, int, int) {} - virtual void detectCollision(Game&, Entity&, Entity&, std::pair) {} -}; - -#endif diff --git a/src/entity_manager.h b/src/entity_manager.h new file mode 100644 index 0000000..74e758c --- /dev/null +++ b/src/entity_manager.h @@ -0,0 +1,279 @@ +#ifndef ENTITY_MANAGER_H_C5832F11 +#define ENTITY_MANAGER_H_C5832F11 + +#include +#include +#include +#include +#include "component.h" + +class EntityManager { + private: + struct EntityData { + int parent = -1; + std::map> components; + }; + + std::map entities; + std::map> cachedChildren; + std::map, std::set> cachedComponents; + + int nextEntityID = 0; + + bool ensureNoParentCycles(int entity, int parent) + { + EntityData& data = entities[parent]; + if (data.parent == entity) + { + return false; + } else if (data.parent == -1) + { + return true; + } + + return ensureNoParentCycles(entity, data.parent); + } + + std::set getEntitiesWithComponents(std::set& componentTypes) + { + if (cachedComponents.count(componentTypes) == 1) + { + return cachedComponents[componentTypes]; + } + + std::set& cache = cachedComponents[componentTypes]; + for (auto& entity : entities) + { + EntityData& data = entity.second; + bool cacheEntity = true; + + for (auto& componentType : componentTypes) + { + if (data.components.count(componentType) == 0) + { + cacheEntity = false; + break; + } + } + + if (cacheEntity) + { + cache.insert(entity.first); + } + } + + return cache; + } + + template std::set getEntitiesWithComponents(std::set& componentTypes) + { + componentTypes.insert(typeid(T)); + + return getEntitiesWithComponents(componentTypes); + } + + public: + EntityManager() = default; + EntityManager(const EntityManager& copy) = delete; + + int emplaceEntity() + { + // Find a suitable entity ID + while ((entities.count(nextEntityID) == 1) && (nextEntityID >= 0)) + { + nextEntityID++; + } + + if (nextEntityID < 0) + { + nextEntityID = 0; + + while ((entities.count(nextEntityID) == 1) && (nextEntityID >= 0)) + { + nextEntityID++; + } + + assert(nextEntityID >= 0); + } + + // Initialize the data + int id = nextEntityID++; + entities[id]; + + return id; + } + + void deleteEntity(int entity) + { + assert(entities.count(entity) == 1); + + EntityData& data = entities[entity]; + + // Destroy the children + std::set children = getChildren(entity); + for (int child : children) + { + EntityData& childData = entities[child]; + childData.parent = -1; + + deleteEntity(child); + } + + // Uncache children + cachedChildren.erase(entity); + + if ((data.parent != -1) && (cachedChildren.count(data.parent) == 1)) + { + cachedChildren[data.parent].erase(entity); + } + + // Uncache components + for (auto& cache : cachedComponents) + { + cache.second.erase(entity); + } + + // Destroy the data + entities.erase(entity); + } + + std::set getChildren(int parent) + { + assert(entities.count(parent) == 1); + + if (cachedChildren.count(parent) == 1) + { + return cachedChildren[parent]; + } + + std::set& cache = cachedChildren[parent]; + for (auto& entity : entities) + { + EntityData& data = entity.second; + if (data.parent == parent) + { + cache.insert(entity.first); + } + } + + return cache; + } + + void setParent(int entity, int parent) + { + assert(entities.count(entity) == 1); + assert(entities.count(parent) == 1); + assert(ensureNoParentCycles(entity, parent)); + + EntityData& data = entities[entity]; + + // Remove from old parent + if (data.parent != -1) + { + if (cachedChildren.count(data.parent) == 1) + { + cachedChildren[data.parent].erase(entity); + } + } + + data.parent = parent; + + // Cache new parent + if (cachedChildren.count(parent) == 1) + { + cachedChildren[parent].insert(entity); + } + } + + void setNoParent(int entity) + { + assert(entities.count(entity) == 1); + + EntityData& data = entities[entity]; + + // Remove from old parent + if (data.parent != -1) + { + if (cachedChildren.count(data.parent) == 1) + { + cachedChildren[data.parent].erase(entity); + } + } + + data.parent = -1; + } + + int getParent(int entity) + { + assert(entities.count(entity) == 1); + + EntityData& data = entities[entity]; + return data.parent; + } + + template T& emplaceComponent(int entity, Args&&... args) + { + assert(entities.count(entity) == 1); + + EntityData& data = entities[entity]; + std::type_index componentType = typeid(T); + + assert(data.components.count(componentType) == 0); + + // Initialize the component + std::unique_ptr ptr = std::unique_ptr(new T(std::forward(args)...)); + T& component = *ptr; + data.components[componentType] = std::move(ptr); + + // Invalidate related caches + std::remove_if(begin(cachedComponents), end(cachedComponents), [&] (std::pair, int>& cache) { + return cache.first.count(componentType) == 1; + }); + + return component; + } + + template void removeComponent(int entity) + { + assert(entities.count(entity) == 1); + + EntityData& data = entities[entity]; + std::type_index componentType = typeid(T); + + assert(data.components.count(componentType) == 1); + + // Destroy the component + data.components.erase(componentType); + + // Uncache the component + for (auto& cache : cachedComponents) + { + if (cache.first.count(componentType) == 1) + { + cache.second.erase(entity); + } + } + } + + template T& getComponent(int entity) + { + assert(entities.count(entity) == 1); + + EntityData& data = entities[entity]; + std::type_index componentType = typeid(T); + + assert(data.components.count(componentType) == 1); + + return *(data.components[componentType]); + } + + template std::set getEntitiesWithComponents() + { + std::set componentTypes; + componentTypes.insert(typeid(T)); + + return getEntitiesWithComponents(componentTypes); + } +}; + +#endif /* end of include guard: ENTITY_MANAGER_H_C5832F11 */ diff --git a/src/entityfactory.cpp b/src/entityfactory.cpp deleted file mode 100644 index b80fe99..0000000 --- a/src/entityfactory.cpp +++ /dev/null @@ -1,182 +0,0 @@ -#include "entityfactory.h" -#include -#include "muxer.h" -#include -#include -#include -#include "components/static_image.h" -#include "components/simple_collider.h" -#include "components/physics_body.h" -#include "components/ai.h" -#include "game.h" - -void parseEntityAIData(AI& ai, xmlNodePtr node, const std::map& items) -{ - xmlChar* key; - - for (xmlNodePtr aiNode = node->xmlChildrenNode; aiNode != NULL; aiNode = aiNode->next) - { - if (!xmlStrcmp(aiNode->name, (xmlChar*) "move")) - { - MoveAIAction::Direction dir; - int len; - int speed; - - key = xmlGetProp(aiNode, (xmlChar*) "direction"); - if (key == 0) exit(2); - if (!xmlStrcmp(key, (xmlChar*) "left")) - { - dir = MoveAIAction::Direction::Left; - } else if (!xmlStrcmp(key, (xmlChar*) "right")) - { - dir = MoveAIAction::Direction::Right; - } else if (!xmlStrcmp(key, (xmlChar*) "up")) - { - dir = MoveAIAction::Direction::Up; - } else if (!xmlStrcmp(key, (xmlChar*) "down")) - { - dir = MoveAIAction::Direction::Down; - } else { - exit(2); - } - xmlFree(key); - - key = xmlGetProp(aiNode, (xmlChar*) "length"); - if (key != 0) - { - len = atoi((char*) key); - } else { - key = xmlGetProp(aiNode, (xmlChar*) "length-var"); - if (key == 0) exit(2); - std::string varName = (char*) key; - len = items.at(varName); - } - xmlFree(key); - - key = xmlGetProp(aiNode, (xmlChar*) "speed"); - if (key != 0) - { - speed = atoi((char*) key); - } else { - key = xmlGetProp(aiNode, (xmlChar*) "speed-var"); - if (key == 0) exit(2); - std::string varName = (char*) key; - speed = items.at(varName); - } - xmlFree(key); - - ai.addAction(std::make_shared(dir, len, speed)); - } else if (!xmlStrcmp(aiNode->name, (xmlChar*) "switch")) - { - key = xmlGetProp(aiNode, (xmlChar*) "item"); - if (key == 0) exit(2); - std::string switchItem = (char*) key; - xmlFree(key); - - for (xmlNodePtr switchNode = aiNode->xmlChildrenNode; switchNode != NULL; switchNode = switchNode->next) - { - if (!xmlStrcmp(switchNode->name, (xmlChar*) "case")) - { - key = xmlGetProp(switchNode, (xmlChar*) "value"); - if (key == 0) exit(2); - int caseValue = atoi((char*) key); - xmlFree(key); - - if (items.at(switchItem) == caseValue) - { - parseEntityAIData(ai, switchNode, items); - } - } - } - } - } -} - -std::shared_ptr EntityFactory::createNamedEntity(const std::string name, const std::map& items) -{ - xmlDocPtr doc = xmlParseFile("res/entities.xml"); - if (doc == nullptr) - { - fprintf(stderr, "Error reading entities\n"); - exit(-1); - } - - xmlNodePtr top = xmlDocGetRootElement(doc); - if (top == nullptr) - { - fprintf(stderr, "Empty entities file\n"); - exit(-1); - } - - if (xmlStrcmp(top->name, (const xmlChar*) "entities")) - { - fprintf(stderr, "Invalid entities definition\n"); - exit(-1); - } - - auto entity = std::make_shared(); - - xmlChar* key; - for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) - { - if (!xmlStrcmp(node->name, (xmlChar*) "entity")) - { - key = xmlGetProp(node, (xmlChar*) "id"); - if (key == 0) exit(-1); - std::string entityID = (char*) key; - xmlFree(key); - - if (entityID == name) - { - key = xmlGetProp(node, (xmlChar*) "sprite"); - if (key == 0) exit(-1); - auto spriteComponent = std::make_shared((char*) key); - entity->addComponent(spriteComponent); - xmlFree(key); - - auto physicsComponent = std::make_shared(); - entity->addComponent(physicsComponent); - - key = xmlGetProp(node, (xmlChar*) "width"); - if (key == 0) exit(-1); - entity->size.first = atoi((char*) key); - xmlFree(key); - - key = xmlGetProp(node, (xmlChar*) "height"); - if (key == 0) exit(-1); - entity->size.second = atoi((char*) key); - xmlFree(key); - - bool addAI = false; - auto aiComponent = std::make_shared(); - - for (xmlNodePtr entityNode = node->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next) - { - if (!xmlStrcmp(entityNode->name, (xmlChar*) "ai")) - { - addAI = true; - - xmlChar* chanceKey = xmlGetProp(entityNode, (xmlChar*) "chance"); - if (chanceKey == 0) exit(2); - int chance = atoi((char*) chanceKey); - xmlFree(chanceKey); - - AI& ai = aiComponent->emplaceAI(chance); - parseEntityAIData(ai, entityNode, items); - } - } - - if (addAI) - { - entity->addComponent(aiComponent); - } - - break; - } - } - } - - xmlFreeDoc(doc); - - return entity; -} diff --git a/src/entityfactory.h b/src/entityfactory.h deleted file mode 100644 index 56f7216..0000000 --- a/src/entityfactory.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef ENTITYFACTORY_H -#define ENTITYFACTORY_H - -#include -#include - -class Entity; -class Map; - -class EntityFactory { - public: - static std::shared_ptr createNamedEntity(const std::string name, const std::map& items); -}; - -#endif diff --git a/src/game.cpp b/src/game.cpp deleted file mode 100644 index 673c804..0000000 --- a/src/game.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include "game.h" -#include -#include "renderer.h" -#include "muxer.h" -#include "map.h" -#include "components/user_movement.h" -#include "components/player_physics.h" -#include "components/player_sprite.h" -#include "components/map_render.h" -#include "components/map_collision.h" -#include "consts.h" - -Game::Game(const char* mapfile) : world(mapfile) -{ - // Set up entities - player = std::make_shared(); - player->position = world.getStartingPosition(); - player->size = std::make_pair(10.0,12.0); - - auto player_input = std::make_shared(); - player->addComponent(player_input); - - auto player_physics = std::make_shared(); - player->addComponent(player_physics); - - auto player_anim = std::make_shared(); - player->addComponent(player_anim); - - const Map& startingMap = world.getStartingMap(); - save = {&startingMap, player->position}; - - loadMap(startingMap, player->position); -} - -void key_callback(GLFWwindow* window, int key, int, int action, int) -{ - Game* game = (Game*) glfwGetWindowUserPointer(window); - - if ((key == GLFW_KEY_ESCAPE) && (action == GLFW_PRESS)) - { - game->shouldQuit = true; - } - - for (auto entity : game->entities) - { - entity->input(*game, key, action); - } -} - -void Game::execute(GLFWwindow* window) -{ - glfwSwapInterval(1); - glfwSetWindowUserPointer(window, this); - glfwSetKeyCallback(window, key_callback); - - Texture buffer(GAME_WIDTH, GAME_HEIGHT); - - double lastTime = glfwGetTime(); - const double dt = 0.01; - double accumulator = 0.0; - - while (!(shouldQuit || glfwWindowShouldClose(window))) - { - double currentTime = glfwGetTime(); - double frameTime = currentTime - lastTime; - lastTime = currentTime; - - // Should we load a new world? - if (newWorld) - { - newWorld = false; - entities.clear(); - entities = std::move(nextEntities); - - player->position = nextPosition; - } - - // Handle input - glfwPollEvents(); - - // Tick! - accumulator += frameTime; - while (accumulator >= dt) - { - for (auto entity : entities) - { - entity->tick(*this, dt); - } - - accumulator -= dt; - } - - // Do any scheduled tasks - for (auto& task : scheduled) - { - task.first -= frameTime; - - if (task.first <= 0) - { - task.second(); - } - } - - scheduled.remove_if([] (std::pair> value) { return value.first <= 0; }); - - // Do rendering - buffer.fill(buffer.entirety(), 0, 0, 0); - for (auto entity : entities) - { - entity->render(*this, buffer); - } - - buffer.renderScreen(); - } -} - -void Game::loadMap(const Map& map, std::pair position) -{ - auto mapEn = std::make_shared(); - - auto map_render = std::make_shared(map); - mapEn->addComponent(map_render); - - auto map_collision = std::make_shared(map); - mapEn->addComponent(map_collision); - - // Map in the back, player on top, rest of entities in between - nextEntities.clear(); - nextEntities.push_back(mapEn); - map.createEntities(nextEntities); - nextEntities.push_back(player); - - newWorld = true; - - currentMap = ↦ - nextPosition = position; -} - -void Game::detectCollision(Entity& collider, std::pair old_position) -{ - for (auto entity : entities) - { - entity->detectCollision(*this, collider, old_position); - } -} - -void Game::saveGame() -{ - save = {currentMap, player->position}; -} - -void Game::schedule(double time, std::function callback) -{ - scheduled.emplace_front(time, std::move(callback)); -} - -void Game::playerDie() -{ - player->send(*this, Message::Type::die); - - playSound("res/Hit_Hurt5.wav", 0.25); - - schedule(0.75, [&] () { - if (*currentMap != *save.map) - { - loadMap(*save.map, save.position); - } else { - player->position = save.position; - } - - player->send(*this, Message::Type::stopDying); - }); -} - -const World& Game::getWorld() const -{ - return world; -} diff --git a/src/game.h b/src/game.h deleted file mode 100644 index dd4b2f7..0000000 --- a/src/game.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef GAME_H -#define GAME_H - -#include -#include -#include -#include -#include "map.h" -#include "world.h" - -class Entity; -struct GLFWwindow; - -struct Savefile { - const Map* map; - std::pair position; -}; - -class Game { - public: - Game(const char* maps); - void execute(GLFWwindow* window); - void loadMap(const Map& map, std::pair position); - void detectCollision(Entity& collider, std::pair old_position); - void saveGame(); - void schedule(double time, std::function callback); - void playerDie(); - const World& getWorld() const; - - private: - friend void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); - - std::list> entities; - std::list> nextEntities; - std::pair nextPosition; - bool newWorld; - std::shared_ptr player; - const Map* currentMap; - Savefile save; - std::list>> scheduled; - bool shouldQuit = false; - World world; -}; - -#endif diff --git a/src/main.cpp b/src/main.cpp index 4157350..29a364b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,9 +1,9 @@ #include #include -#include "renderer.h" #include -#include "game.h" +#include "renderer.h" #include "muxer.h" +#include "entity_manager.h" int main() { @@ -14,8 +14,12 @@ int main() // Put this in a block so game goes out of scope before we destroy the renderer { - Game game {"res/maps.xml"}; - game.execute(window); + EntityManager manager; + + int eRef = manager.emplaceEntity(); + int eRef2 = manager.emplaceEntity(); + manager.setParent(eRef, eRef2); + printf("%d\n", manager.getParent(eRef)); } destroyMuxer(); diff --git a/src/map.cpp b/src/map.cpp deleted file mode 100644 index e3725b2..0000000 --- a/src/map.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include "map.h" -#include -#include -#include -#include "entityfactory.h" -#include "entity.h" -#include "game.h" -#include "consts.h" - -Map::Map(int id) -{ - this->id = id; - mapdata = (int*) calloc(1, sizeof(int)); -} - -Map::Map(const Map& map) -{ - mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int)); - memcpy(mapdata, map.mapdata, MAP_WIDTH*MAP_HEIGHT*sizeof(int)); - - id = map.id; - title = map.title; - adjacents = map.adjacents; - entities = map.entities; -} - -Map::Map(Map&& map) : Map() -{ - swap(*this, map); -} - -Map::~Map() -{ - free(mapdata); -} - -Map& Map::operator= (Map map) -{ - swap(*this, map); - - return *this; -} - -void swap(Map& first, Map& second) -{ - std::swap(first.mapdata, second.mapdata); - std::swap(first.title, second.title); - std::swap(first.adjacents, second.adjacents); - std::swap(first.id, second.id); - std::swap(first.entities, second.entities); -} - -int Map::getID() const -{ - return id; -} - -const int* Map::getMapdata() const -{ - return mapdata; -} - -std::string Map::getTitle() const -{ - return title; -} - -void Map::createEntities(std::list>& entities) const -{ - for (auto data : this->entities) - { - auto entity = EntityFactory::createNamedEntity(data.name, data.items); - entity->position = data.position; - - entities.push_back(entity); - } -} - -bool Map::operator==(const Map& other) const -{ - return id == other.id; -} - -bool Map::operator!=(const Map& other) const -{ - return id != other.id; -} - -Map::MoveType Map::moveTypeForShort(std::string str) -{ - if (str == "wrap") return MoveType::Wrap; - if (str == "warp") return MoveType::Warp; - if (str == "reverseWarp") return MoveType::ReverseWarp; - - return MoveType::Wall; -} - -Map::MoveDir Map::moveDirForShort(std::string str) -{ - if (str == "right") return MoveDir::Right; - if (str == "up") return MoveDir::Up; - if (str == "down") return MoveDir::Down; - - return MoveDir::Left; -} - -static const Map::Adjacent defaultAdjacent {}; -const Map::Adjacent& Map::getAdjacent(MoveDir dir) const -{ - if (adjacents.count(dir) > 0) - { - return adjacents.at(dir); - } else { - return defaultAdjacent; - } -} - -bool Map::moveTypeTakesMap(MoveType type) -{ - switch (type) - { - case MoveType::Wall: return false; - case MoveType::Wrap: return false; - case MoveType::Warp: return true; - case MoveType::ReverseWarp: return true; - } -} - -void Map::setMapdata(int* mapdata) -{ - free(this->mapdata); - this->mapdata = mapdata; -} - -void Map::setTitle(std::string title) -{ - this->title = title; -} - -void Map::setAdjacent(MoveDir dir, MoveType type, int map) -{ - Adjacent& cur = adjacents[dir]; - cur.type = type; - if (map != -1) cur.map = map; -} - -void Map::addEntity(EntityData& data) -{ - entities.push_back(data); -} - diff --git a/src/map.h b/src/map.h deleted file mode 100644 index 22333aa..0000000 --- a/src/map.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef MAP_H -#define MAP_H - -#include -#include -#include - -class Entity; - -class Map { - public: - Map(int id); - Map() : Map(-1) {} - Map(const Map& map); - Map(Map&& map); - ~Map(); - Map& operator= (Map other); - friend void swap(Map& first, Map& second); - - enum class MoveType { - Wall, - Wrap, - Warp, - ReverseWarp - }; - - enum class MoveDir { - Left, - Right, - Up, - Down - }; - - struct EntityData { - std::string name; - std::pair position; - std::map items; - }; - - struct Adjacent { - MoveType type = MoveType::Wall; - int map = -1; - }; - - static MoveType moveTypeForShort(std::string str); - static MoveDir moveDirForShort(std::string str); - static bool moveTypeTakesMap(MoveType type); - - int getID() const; - const int* getMapdata() const; - std::string getTitle() const; - const Adjacent& getAdjacent(MoveDir dir) const; - - void createEntities(std::list>& entities) const; - bool operator==(const Map& other) const; - bool operator!=(const Map& other) const; - - void setMapdata(int* mapdata); - void setTitle(std::string title); - void setAdjacent(MoveDir dir, MoveType type, int map); - void addEntity(EntityData& data); - private: - int* mapdata; - std::string title; - int id; - std::list entities; - std::map adjacents; -}; - -#endif diff --git a/src/world.cpp b/src/world.cpp deleted file mode 100644 index 0c61c47..0000000 --- a/src/world.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "world.h" -#include -#include "consts.h" - -World::World(const char* filename) -{ - xmlDocPtr doc = xmlParseFile(filename); - if (doc == nullptr) - { - exit(2); - } - - xmlNodePtr top = xmlDocGetRootElement(doc); - if (top == nullptr) - { - exit(2); - } - - if (xmlStrcmp(top->name, (const xmlChar*) "world")) - { - exit(2); - } - - xmlChar* startxKey = xmlGetProp(top, (xmlChar*) "startx"); - if (startxKey == 0) exit(2); - startX = atoi((char*) startxKey); - xmlFree(startxKey); - - xmlChar* startyKey = xmlGetProp(top, (xmlChar*) "starty"); - if (startyKey == 0) exit(2); - startY = atoi((char*) startyKey); - xmlFree(startyKey); - - xmlChar* startmapKey = xmlGetProp(top, (xmlChar*) "startmap"); - if (startxKey == 0) exit(2); - startMap = atoi((char*) startmapKey); - xmlFree(startmapKey); - - for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) - { - if (!xmlStrcmp(node->name, (const xmlChar*) "map")) - { - xmlChar* idKey = xmlGetProp(node, (xmlChar*) "id"); - if (idKey == 0) exit(2); - int theId = atoi((char*) idKey); - xmlFree(idKey); - - maps.emplace(theId, theId); - Map& map = maps[theId]; - - xmlChar* titleKey = xmlGetProp(node, (xmlChar*) "title"); - if (titleKey == 0) exit(2); - map.setTitle((char*) titleKey); - xmlFree(titleKey); - - for (xmlNodePtr mapNode = node->xmlChildrenNode; mapNode != NULL; mapNode = mapNode->next) - { - if (!xmlStrcmp(mapNode->name, (const xmlChar*) "environment")) - { - xmlChar* key = xmlNodeGetContent(mapNode); - int* mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int)); - mapdata[0] = atoi(strtok((char*) key, ",\n")); - for (int i=1; i<(MAP_WIDTH*MAP_HEIGHT); i++) - { - mapdata[i] = atoi(strtok(NULL, ",\n")); - } - map.setMapdata(mapdata); - xmlFree(key); - } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "entity")) - { - Map::EntityData data; - - xmlChar* typeKey = xmlGetProp(mapNode, (const xmlChar*) "type"); - if (typeKey == 0) exit(2); - data.name = (char*) typeKey; - xmlFree(typeKey); - - xmlChar* xKey = xmlGetProp(mapNode, (const xmlChar*) "x"); - if (xKey == 0) exit(2); - data.position.first = atoi((char*) xKey); - xmlFree(xKey); - - xmlChar* yKey = xmlGetProp(mapNode, (const xmlChar*) "y"); - if (yKey == 0) exit(2); - data.position.second = atoi((char*) yKey); - xmlFree(yKey); - - for (xmlNodePtr entityNode = mapNode->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next) - { - if (!xmlStrcmp(entityNode->name, (xmlChar*) "item")) - { - xmlChar* itemIdKey = xmlGetProp(entityNode, (const xmlChar*) "id"); - if (itemIdKey == 0) exit(2); - std::string itemId = (char*) itemIdKey; - xmlFree(itemIdKey); - - xmlChar* itemIdVal = xmlNodeGetContent(entityNode); - if (itemIdVal == 0) exit(2); - data.items[itemId] = atoi((char*) itemIdVal); - xmlFree(itemIdVal); - } - } - - map.addEntity(data); - } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "adjacent")) - { - Map::MoveDir direction; - Map::MoveType moveType; - int mapId = 0; - - xmlChar* dirKey = xmlGetProp(mapNode, (const xmlChar*) "dir"); - if (dirKey == 0) exit(2); - direction = Map::moveDirForShort((char*) dirKey); - xmlFree(dirKey); - - xmlChar* typeKey = xmlGetProp(mapNode, (const xmlChar*) "type"); - if (typeKey == 0) exit(2); - moveType = Map::moveTypeForShort((char*) typeKey); - xmlFree(typeKey); - - xmlChar* mapIdKey = xmlGetProp(mapNode, (const xmlChar*) "map"); - if (mapIdKey != 0) - { - mapId = atoi((char*) mapIdKey); - } - xmlFree(mapIdKey); - - map.setAdjacent(direction, moveType, mapId); - } - } - } - } - - xmlFreeDoc(doc); -} - -const Map& World::getMap(int id) const -{ - return maps.at(id); -} - -const Map& World::getStartingMap() const -{ - return maps.at(startMap); -} - -std::pair World::getStartingPosition() const -{ - return std::make_pair(startX, startY); -} diff --git a/src/world.h b/src/world.h deleted file mode 100644 index f566487..0000000 --- a/src/world.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef WORLD_H -#define WORLD_H - -#include -#include "map.h" - -class World { - public: - World(const char* filename); - const Map& getMap(int id) const; - const Map& getStartingMap() const; - std::pair getStartingPosition() const; - - private: - std::map maps; - int startMap; - int startX; - int startY; -}; - -#endif /* end of include guard: WORLD_H */ -- cgit 1.4.1