From 1abc8894c2378596542e5772cd7594492eeecb27 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sat, 6 Feb 2021 13:03:01 -0500 Subject: Added collision with other sprites --- src/main.cpp | 1 + src/transform_system.cpp | 130 ++++++++++++++++++++++++++++++++++++----------- src/transform_system.h | 3 ++ 3 files changed, 105 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 4d8f52d..8363995 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -49,6 +49,7 @@ void loop(Renderer& renderer) { int flintSprite = game.emplaceSprite(); game.getSystem().initSprite(flintSprite, {35*16, 19*16}); + game.getSystem().setUpCollision(flintSprite, {-8, -8}, {12, 8}); game.getSystem().initSprite(flintSprite, "../res/sprites/flint_anim.txt", renderer); game.getSystem().setFollowingSprite(lucasSprite); diff --git a/src/transform_system.cpp b/src/transform_system.cpp index d6df5fa..3d65acb 100644 --- a/src/transform_system.cpp +++ b/src/transform_system.cpp @@ -54,50 +54,122 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Dire vec2i oldTileDR = oldColDR / map.getTileSize(); vec2i newTileDR = newColDR / map.getTileSize(); - if (dirHasDir(sprite.dir, Direction::right) && - newTileDR.x() > oldTileDR.x()) { - for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { - if (map.isBlocked(newTileDR.x(), y)) { - result.horiz.blocked = true; - result.horiz.dir = Direction::right; - - break; + if (dirHasDir(sprite.dir, Direction::right)) { + if (newTileDR.x() > oldTileDR.x()) { + for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { + if (map.isBlocked(newTileDR.x(), y)) { + result.horiz.blocked = true; + result.horiz.dir = Direction::right; + + break; + } + } + } + + if (!result.horiz.blocked) { + auto it = rightCollidables_.lower_bound({oldColDR.x(), INT_MAX}); + for (; + (it != std::end(rightCollidables_) && + std::get<0>(it->first) <= newColDR.x()); + it++) { + if (newColDR.y() >= it->second.lower && + newColUL.y() <= it->second.upper) { + result.horiz.blocked = true; + result.horiz.dir = Direction::right; + result.horiz.colliderSprite = std::get<1>(it->first); + + break; + } } } } - if (dirHasDir(sprite.dir, Direction::left) && - newTileUL.x() < oldTileUL.x()) { - for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { - if (map.isBlocked(newTileUL.x(), y)) { - result.horiz.blocked = true; - result.horiz.dir = Direction::left; + if (dirHasDir(sprite.dir, Direction::left)) { + if (newTileUL.x() < oldTileUL.x()) { + for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { + if (map.isBlocked(newTileUL.x(), y)) { + result.horiz.blocked = true; + result.horiz.dir = Direction::left; + + break; + } + } + } - break; + if (!result.horiz.blocked) { + auto it = leftCollidables_.lower_bound({oldColUL.x(), 0}); + for (; + (it != std::end(leftCollidables_) && + std::get<0>(it->first) >= newColUL.x()); + it++) { + if (newColDR.y() >= it->second.lower && + newColUL.y() <= it->second.upper) { + result.horiz.blocked = true; + result.horiz.dir = Direction::left; + result.horiz.colliderSprite = std::get<1>(it->first); + + break; + } } } } - if (dirHasDir(sprite.dir, Direction::down) && - newTileDR.y() > oldTileDR.y()) { - for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { - if (map.isBlocked(x, newTileDR.y())) { - result.vert.blocked = true; - result.vert.dir = Direction::down; + if (dirHasDir(sprite.dir, Direction::down)) { + if (newTileDR.y() > oldTileDR.y()) { + for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { + if (map.isBlocked(x, newTileDR.y())) { + result.vert.blocked = true; + result.vert.dir = Direction::down; - break; + break; + } + } + } + + if (!result.vert.blocked) { + auto it = downCollidables_.lower_bound({oldColDR.y(), INT_MAX}); + for (; + (it != std::end(downCollidables_) && + std::get<0>(it->first) <= newColDR.y()); + it++) { + if (newColDR.x() >= it->second.lower && + newColUL.x() <= it->second.upper) { + result.vert.blocked = true; + result.vert.dir = Direction::down; + result.vert.colliderSprite = std::get<1>(it->first); + + break; + } } } } - if (dirHasDir(sprite.dir, Direction::up) && - newTileUL.y() < oldTileUL.y()) { - for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { - if (map.isBlocked(x, newTileUL.y())) { - result.vert.blocked = true; - result.vert.dir = Direction::up; + if (dirHasDir(sprite.dir, Direction::up)) { + if (newTileUL.y() < oldTileUL.y()) { + for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { + if (map.isBlocked(x, newTileUL.y())) { + result.vert.blocked = true; + result.vert.dir = Direction::up; + + break; + } + } + } - break; + if (!result.vert.blocked) { + auto it = upCollidables_.lower_bound({oldColUL.y(), 0}); + for (; + (it != std::end(upCollidables_) && + std::get<0>(it->first) >= newColUL.y()); + it++) { + if (newColDR.x() >= it->second.lower && + newColUL.x() <= it->second.upper) { + result.vert.blocked = true; + result.vert.dir = Direction::up; + result.vert.colliderSprite = std::get<1>(it->first); + + break; + } } } } diff --git a/src/transform_system.h b/src/transform_system.h index 1ad661c..a7294ce 100644 --- a/src/transform_system.h +++ b/src/transform_system.h @@ -14,6 +14,7 @@ class Game; struct AxisResult { Direction dir; bool blocked = false; + int colliderSprite = -1; }; struct CollisionResult { @@ -54,6 +55,8 @@ private: Collidable(int lower, int upper) : lower(lower), upper(upper) {} }; + // The way these work is that the key is (axis position, entity ID). The + // entity ID being there makes the mapping unique and makes removal easy. using asc_collidables_type = std::map< std::tuple, -- cgit 1.4.1