#include "transform_system.h" #include "game.h" #include "map.h" void TransformSystem::initSprite(int spriteId, vec2i loc) { Sprite& sprite = game_.getSprite(spriteId); sprite.loc = loc; spritesByY_.emplace(loc.y(), spriteId); } void TransformSystem::setUpCollision(int spriteId, vec2i offset, vec2i size) { Sprite& sprite = game_.getSprite(spriteId); sprite.collidable = true; sprite.collisionOffset = offset; sprite.collisionSize = size; addCollidable(spriteId); } void TransformSystem::moveSprite(int spriteId, vec2i newLoc) { Sprite& sprite = game_.getSprite(spriteId); if (sprite.collidable) { removeCollidable(spriteId); } bool changedY = (sprite.loc.y() != newLoc.y()); if (changedY) { spritesByY_.erase(std::make_tuple(sprite.loc.y(), spriteId)); } sprite.loc = newLoc; if (changedY) { spritesByY_.emplace(newLoc.y(), spriteId); } if (sprite.collidable) { addCollidable(spriteId); } } CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Direction dir) { CollisionResult result; Sprite& sprite = game_.getSprite(spriteId); const Map& map = game_.getMap(); bool blocked = false; vec2i oldColUL = sprite.loc + sprite.collisionOffset; vec2i oldColDR = oldColUL + sprite.collisionSize; vec2i newColUL = newLoc + sprite.collisionOffset; vec2i newColDR = newColUL + sprite.collisionSize; vec2i oldTileUL = oldColUL / map.getTileSize(); vec2i newTileUL = newColUL / map.getTileSize(); 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::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; 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; 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; break; } } } return result; } void TransformSystem::addCollidable(int spriteId) { Sprite& sprite = game_.getSprite(spriteId); vec2i colUL = sprite.loc + sprite.collisionOffset; vec2i colDR = colUL + sprite.collisionSize; leftCollidables_.emplace(std::piecewise_construct, std::tie(colDR.x(), spriteId), std::tie(colUL.y(), colDR.y())); rightCollidables_.emplace(std::piecewise_construct, std::tie(colUL.x(), spriteId), std::tie(colUL.y(), colDR.y())); upCollidables_.emplace(std::piecewise_construct, std::tie(colDR.y(), spriteId), std::tie(colUL.x(), colDR.x())); downCollidables_.emplace(std::piecewise_construct, std::tie(colUL.y(), spriteId), std::tie(colUL.x(), colDR.x())); } void TransformSystem::removeCollidable(int spriteId) { Sprite& sprite = game_.getSprite(spriteId); vec2i colUL = sprite.loc + sprite.collisionOffset; vec2i colDR = colUL + sprite.collisionSize; leftCollidables_.erase({ colDR.x(), spriteId }); rightCollidables_.erase({ colUL.x(), spriteId }); upCollidables_.erase({ colDR.y(), spriteId }); downCollidables_.erase({ colUL.y(), spriteId }); }