From 77be863f4f15d2481a64e4e8dadb4060a6e4e590 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sun, 11 Feb 2018 12:34:52 -0500 Subject: Implemented map rendering and basic collision Only wall and platform collision currently works, and map edges are not currently implemented. --- src/systems/controlling.cpp | 22 ++-- src/systems/mapping.cpp | 143 +++++++++++++++++++++++++ src/systems/mapping.h | 19 ++++ src/systems/pondering.cpp | 248 ++++++++++++++++++++++++++++++++++++++++++-- src/systems/pondering.h | 16 +++ 5 files changed, 431 insertions(+), 17 deletions(-) create mode 100644 src/systems/mapping.cpp create mode 100644 src/systems/mapping.h (limited to 'src/systems') diff --git a/src/systems/controlling.cpp b/src/systems/controlling.cpp index 3647ff8..fa09d11 100644 --- a/src/systems/controlling.cpp +++ b/src/systems/controlling.cpp @@ -123,7 +123,7 @@ void ControllingSystem::walkLeft(id_type entity) auto& animating = game_.getSystemManager().getSystem(); - if (ponderable.getState() == PonderableComponent::state::grounded) + if (ponderable.getState() == PonderableComponent::State::grounded) { animating.startAnimation(entity, "walkingLeft"); } else { @@ -141,7 +141,7 @@ void ControllingSystem::walkRight(id_type entity) auto& animating = game_.getSystemManager().getSystem(); - if (ponderable.getState() == PonderableComponent::state::grounded) + if (ponderable.getState() == PonderableComponent::State::grounded) { animating.startAnimation(entity, "walkingRight"); } else { @@ -156,7 +156,7 @@ void ControllingSystem::stopWalking(id_type entity) ponderable.setVelocityX(0); - if (ponderable.getState() == PonderableComponent::state::grounded) + if (ponderable.getState() == PonderableComponent::State::grounded) { auto& animating = game_.getSystemManager().getSystem(); @@ -173,13 +173,13 @@ void ControllingSystem::jump(id_type entity) { auto& ponderable = game_.getEntityManager().getComponent(entity); - if (ponderable.getState() == PonderableComponent::state::grounded) + if (ponderable.getState() == PonderableComponent::State::grounded) { playSound("res/Randomize87.wav", 0.25); ponderable.setVelocityY(JUMP_VELOCITY(TILE_HEIGHT*4.5, 0.3)); ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*4.5, 0.3)); - ponderable.setState(PonderableComponent::state::jumping); + ponderable.setState(PonderableComponent::State::jumping); } } @@ -187,10 +187,10 @@ void ControllingSystem::stopJumping(id_type entity) { auto& ponderable = game_.getEntityManager().getComponent(entity); - if (ponderable.getState() == PonderableComponent::state::jumping) + if (ponderable.getState() == PonderableComponent::State::jumping) { ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233)); - ponderable.setState(PonderableComponent::state::falling); + ponderable.setState(PonderableComponent::State::falling); } } @@ -199,12 +199,12 @@ void ControllingSystem::drop(id_type entity, bool start) auto& droppable = game_.getEntityManager().getComponent(entity); auto& ponderable = game_.getEntityManager().getComponent(entity); - if (start && (ponderable.getState() == PonderableComponent::state::grounded)) + if (start && (ponderable.getState() == PonderableComponent::State::grounded)) { - ponderable.setState(PonderableComponent::state::dropping); - } else if ((!start) && (ponderable.getState() == PonderableComponent::state::dropping)) + ponderable.setState(PonderableComponent::State::dropping); + } else if ((!start) && (ponderable.getState() == PonderableComponent::State::dropping)) { - ponderable.setState(PonderableComponent::state::grounded); + ponderable.setState(PonderableComponent::State::grounded); } droppable.setDroppable(start); } diff --git a/src/systems/mapping.cpp b/src/systems/mapping.cpp new file mode 100644 index 0000000..8723e16 --- /dev/null +++ b/src/systems/mapping.cpp @@ -0,0 +1,143 @@ +#include "mapping.h" +#include "components/mappable.h" +#include "game.h" +#include "consts.h" + +#include + +template +inline void addBoundary( + Storage& boundaries, + int axis, + int lower, + int upper, + MappableComponent::Boundary::Type type) +{ + boundaries.emplace(std::piecewise_construct, + std::tie(axis), + std::tie(axis, lower, upper, type)); +} + +void MappingSystem::render(Texture& texture) +{ + auto entities = game_.getEntityManager().getEntitiesWithComponents< + MappableComponent>(); + + for (id_type entity : entities) + { + auto& mappable = game_.getEntityManager(). + getComponent(entity); + + const Map& map = game_.getWorld().getMap(mappable.getMapId()); + + for (int i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++) + { + int x = i % MAP_WIDTH; + int y = i / MAP_WIDTH; + int tile = map.getTiles()[i]; + + if (tile > 0) + { + Rectangle dst { + x * TILE_WIDTH, + y * TILE_HEIGHT, + TILE_WIDTH, + TILE_HEIGHT}; + + Rectangle src { + (tile % TILESET_COLS) * TILE_WIDTH, + (tile / TILESET_COLS) * TILE_HEIGHT, + TILE_WIDTH, + TILE_HEIGHT}; + + texture.blit(mappable.getTileset(), std::move(src), std::move(dst)); + } + } + + int startX = ((GAME_WIDTH / TILE_WIDTH) / 2) - (map.getTitle().size() / 2); + for (size_t i = 0; i < map.getTitle().size(); i++) + { + Rectangle src { + (map.getTitle()[i] % FONT_COLS) * TILE_WIDTH, + (map.getTitle()[i] / FONT_COLS) * TILE_HEIGHT, + TILE_WIDTH, + TILE_HEIGHT}; + + Rectangle dst { + (startX + static_cast(i)) * TILE_WIDTH, + 24 * TILE_HEIGHT, + TILE_WIDTH, + TILE_HEIGHT}; + + texture.blit(mappable.getFont(), std::move(src), std::move(dst)); + } + } +} + +void MappingSystem::loadMap(size_t mapId) +{ + id_type mapEntity = game_.getEntityManager().emplaceEntity(); + + auto& mappable = game_.getEntityManager(). + emplaceComponent(mapEntity, + Texture("res/tiles.png"), + Texture("res/font.bmp")); + + mappable.setMapId(mapId); + + const Map& map = game_.getWorld().getMap(mappable.getMapId()); + + for (size_t i = 0; i < MAP_WIDTH * MAP_HEIGHT; i++) + { + size_t x = i % MAP_WIDTH; + size_t y = i / MAP_WIDTH; + int tile = map.getTiles()[i]; + + if ((tile >= 5) && (tile <= 7)) + { + addBoundary( + mappable.getDownBoundaries(), + y * TILE_HEIGHT, + x * TILE_WIDTH, + (x + 1) * TILE_WIDTH, + MappableComponent::Boundary::Type::platform); + } else if ((tile > 0) && (tile < 28)) + { + addBoundary( + mappable.getRightBoundaries(), + x * TILE_WIDTH, + y * TILE_HEIGHT, + (y+1) * TILE_HEIGHT, + MappableComponent::Boundary::Type::wall); + + addBoundary( + mappable.getLeftBoundaries(), + (x+1) * TILE_WIDTH, + y * TILE_HEIGHT, + (y+1) * TILE_HEIGHT, + MappableComponent::Boundary::Type::wall); + + addBoundary( + mappable.getDownBoundaries(), + y * TILE_HEIGHT, + x * TILE_WIDTH, + (x+1) * TILE_WIDTH, + MappableComponent::Boundary::Type::wall); + + addBoundary( + mappable.getUpBoundaries(), + (y+1) * TILE_HEIGHT, + x * TILE_WIDTH, + (x+1) * TILE_WIDTH, + MappableComponent::Boundary::Type::wall); + } else if (tile == 42) + { + addBoundary( + mappable.getDownBoundaries(), + y * TILE_HEIGHT, + x * TILE_WIDTH, + (x+1) * TILE_WIDTH, + MappableComponent::Boundary::Type::danger); + } + } +} diff --git a/src/systems/mapping.h b/src/systems/mapping.h new file mode 100644 index 0000000..53d054b --- /dev/null +++ b/src/systems/mapping.h @@ -0,0 +1,19 @@ +#ifndef MAPPING_H_33FC2294 +#define MAPPING_H_33FC2294 + +#include "system.h" + +class MappingSystem : public System { +public: + + MappingSystem(Game& game) : System(game) + { + } + + void render(Texture& texture); + + void loadMap(size_t mapId); + +}; + +#endif /* end of include guard: MAPPING_H_33FC2294 */ diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index e40db1d..26a6f56 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp @@ -2,6 +2,8 @@ #include "game.h" #include "components/ponderable.h" #include "components/transformable.h" +#include "components/droppable.h" +#include "consts.h" void PonderingSystem::tick(double dt) { @@ -9,17 +11,251 @@ void PonderingSystem::tick(double dt) PonderableComponent, TransformableComponent>(); + auto maps = game_.getEntityManager().getEntitiesWithComponents< + MappableComponent>(); + for (id_type entity : entities) { - auto& transformable = game_.getEntityManager().getComponent(entity); - auto& ponderable = game_.getEntityManager().getComponent(entity); + auto& transformable = game_.getEntityManager(). + getComponent(entity); + + auto& ponderable = game_.getEntityManager(). + getComponent(entity); // Accelerate - ponderable.setVelocityX(ponderable.getVelocityX() + ponderable.getAccelX() * dt); - ponderable.setVelocityY(ponderable.getVelocityY() + ponderable.getAccelY() * dt); + ponderable.setVelocityX( + ponderable.getVelocityX() + ponderable.getAccelX() * dt); + + ponderable.setVelocityY( + ponderable.getVelocityY() + ponderable.getAccelY() * dt); + + const double oldX = transformable.getX(); + const double oldY = transformable.getY(); + const double oldRight = oldX + transformable.getW(); + const double oldBottom = oldY + transformable.getH(); + + double newX = oldX + ponderable.getVelocityX() * dt; + double newY = oldY + ponderable.getVelocityY() * dt; + + if (ponderable.getVelocityY() > 0.0) + { + ponderable.setState(PonderableComponent::State::falling); + } + + for (id_type mapEntity : maps) + { + auto& mappable = game_.getEntityManager(). + getComponent(mapEntity); + + if (newX < oldX) + { + for (auto it = mappable.getLeftBoundaries().lower_bound(oldX); + (it != std::end(mappable.getLeftBoundaries())) && (it->first >= newX); + it++) + { + if ((oldBottom > it->second.getLower()) + && (oldY < it->second.getUpper())) + { + // We have a collision! + processCollision( + entity, + Direction::left, + newX, + newY, + it->first, + it->second.getType()); + + break; + } + } + } else if (newX > oldX) + { + for (auto it = mappable.getRightBoundaries().lower_bound(oldRight); + (it != std::end(mappable.getRightBoundaries())) + && (it->first <= (newX + transformable.getW())); + it++) + { + if ((oldBottom > it->second.getLower()) + && (oldY < it->second.getUpper())) + { + // We have a collision! + processCollision( + entity, + Direction::right, + newX, + newY, + it->first, + it->second.getType()); + + break; + } + } + } + + if (newY < oldY) + { + for (auto it = mappable.getUpBoundaries().lower_bound(oldY); + (it != std::end(mappable.getUpBoundaries())) && (it->first >= newY); + it++) + { + if ((oldRight > it->second.getLower()) + && (oldX < it->second.getUpper())) + { + // We have a collision! + processCollision( + entity, + Direction::up, + newX, + newY, + it->first, + it->second.getType()); + + break; + } + } + } else if (newY > oldY) + { + for (auto it = mappable.getDownBoundaries().lower_bound(oldBottom); + (it != std::end(mappable.getDownBoundaries())) + && (it->first <= (newY + transformable.getH())); + it++) + { + if ((oldRight > it->second.getLower()) + && (oldX < it->second.getUpper())) + { + // We have a collision! + processCollision( + entity, + Direction::down, + newX, + newY, + it->first, + it->second.getType()); + + break; + } + } + } + } // Move - transformable.setX(transformable.getX() + ponderable.getVelocityX() * dt); - transformable.setY(transformable.getY() + ponderable.getVelocityY() * dt); + transformable.setX(newX); + transformable.setY(newY); + } +} + +void PonderingSystem::initializeBody( + id_type entity, + PonderableComponent::Type type) +{ + auto& ponderable = game_.getEntityManager(). + emplaceComponent(entity, type); + + if (type == PonderableComponent::Type::freefalling) + { + ponderable.setAccelY(JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233)); + ponderable.setState(PonderableComponent::State::falling); + } +} + +void PonderingSystem::processCollision( + id_type entity, + Direction dir, + double& newX, + double& newY, + int axis, + MappableComponent::Boundary::Type type) +{ + auto& ponderable = game_.getEntityManager(). + getComponent(entity); + + auto& transformable = game_.getEntityManager(). + getComponent(entity); + + switch (type) + { + case MappableComponent::Boundary::Type::wall: + { + switch (dir) + { + case Direction::left: + { + newX = axis; + ponderable.setVelocityX(0.0); + + break; + } + + case Direction::right: + { + newX = axis - transformable.getW(); + ponderable.setVelocityX(0.0); + + break; + } + + case Direction::up: + { + newY = axis; + ponderable.setVelocityY(0.0); + + break; + } + + case Direction::down: + { + newY = axis - transformable.getH(); + ponderable.setVelocityY(0.0); + + if (ponderable.getState() == PonderableComponent::State::falling) + { + ponderable.setState(PonderableComponent::State::grounded); + } + + break; + } + } + + break; + } + + case MappableComponent::Boundary::Type::platform: + { + if (game_.getEntityManager().hasComponent(entity)) + { + auto& droppable = game_.getEntityManager(). + getComponent(entity); + + if (droppable.isDroppable()) + { + droppable.setDroppable(false); + } else { + newY = axis - transformable.getH(); + ponderable.setVelocityY(0.0); + + if (ponderable.getState() == PonderableComponent::State::falling) + { + ponderable.setState(PonderableComponent::State::grounded); + } + } + } else { + newY = axis - transformable.getH(); + ponderable.setVelocityY(0.0); + + if (ponderable.getState() == PonderableComponent::State::falling) + { + ponderable.setState(PonderableComponent::State::grounded); + } + } + + break; + } + + default: + { + // Not yet implemented. + + break; + } } } diff --git a/src/systems/pondering.h b/src/systems/pondering.h index 44e7600..a16622b 100644 --- a/src/systems/pondering.h +++ b/src/systems/pondering.h @@ -2,6 +2,9 @@ #define PONDERING_H_F2530E0E #include "system.h" +#include "components/mappable.h" +#include "components/ponderable.h" +#include "direction.h" class PonderingSystem : public System { public: @@ -11,6 +14,19 @@ public: } void tick(double dt); + + void initializeBody(id_type entity, PonderableComponent::Type type); + +private: + + void processCollision( + id_type entity, + Direction dir, + double& newX, + double& newY, + int axis, + MappableComponent::Boundary::Type type); + }; #endif /* end of include guard: PONDERING_H_F2530E0E */ -- cgit 1.4.1