/** GDevelop - Tile Map Extension Copyright (c) 2014-2016 Victor Levasseur (victorlevasseur52@gmail.com) This project is released under the MIT License. */ #include "RuntimeTileMapObject.h" #include #include "GDCore/Tools/Localization.h" #include "GDCpp/Runtime/Project/Object.h" #include "GDCpp/Runtime/Project/Project.h" #include "GDCpp/Runtime/RuntimeScene.h" #include "GDCpp/Runtime/RuntimeGame.h" #include "GDCpp/Runtime/ImageManager.h" #include "GDCpp/Runtime/FontManager.h" #include "GDCpp/Runtime/Project/InitialInstance.h" #include "GDCpp/Runtime/Polygon2d.h" #include "GDCpp/Runtime/PolygonCollision.h" #include "GDCpp/Runtime/RuntimeObjectsListsTools.h" #include "GDCpp/Runtime/Serialization/SerializerElement.h" #include "GDCpp/Runtime/CommonTools.h" #include "TileMapObject.h" #include "TileMap.h" #include "TileSet.h" #include "TileMapTools.h" RuntimeTileMapObject::RuntimeTileMapObject(RuntimeScene & scene, const TileMapObject & tileMapObject) : RuntimeObject(scene, tileMapObject), tileSet(), tileMap(), vertexArray(sf::Quads), oldX(0), oldY(0), needGeneration(false) { tileSet = tileMapObject.tileSet; tileMap = tileMapObject.tileMap; //Load the tileset and generate the vertex array tileSet.Get().LoadResources(*(scene.game)); vertexArray = TileMapExtension::GenerateVertexArray(tileSet.Get(), tileMap.Get()); hitboxes = TileMapExtension::GenerateHitboxes(tileSet.Get(), tileMap.Get()); } /** * Render object at runtime */ bool RuntimeTileMapObject::Draw( sf::RenderTarget& window ) { if(needGeneration) { //Re-generate the vertex array and the hitboxes vertexArray = TileMapExtension::GenerateVertexArray(tileSet.Get(), tileMap.Get()); hitboxes = TileMapExtension::GenerateHitboxes(tileSet.Get(), tileMap.Get()); for(std::vector::iterator it = hitboxes.begin(); it != hitboxes.end(); it++) { it->Move(GetX(), GetY()); } needGeneration = false; } //Don't draw anything if hidden if ( hidden ) return true; //Get the current view sf::View currentView = window.getView(); sf::Vector2f centerPos = currentView.getCenter(); //Construct the transform sf::Transform transform; transform.translate((int)GetX() + centerPos.x - floor(centerPos.x), (int)GetY() + centerPos.y - floor(centerPos.y)); //Unsmooth the texture bool wasSmooth = tileSet.Get().GetTexture().isSmooth(); tileSet.Get().GetTexture().setSmooth(false); //Draw the tilemap window.draw(vertexArray, sf::RenderStates(sf::BlendAlpha, transform, &tileSet.Get().GetTexture(), NULL)); tileSet.Get().GetTexture().setSmooth(wasSmooth); return true; } float RuntimeTileMapObject::GetWidth() const { if(tileSet.Get().IsDirty() || tileMap.Get().GetColumnsCount() == 0 || tileMap.Get().GetRowsCount() == 0) return 200.f; else return tileMap.Get().GetColumnsCount() * tileSet.Get().tileSize.x; } float RuntimeTileMapObject::GetHeight() const { if(tileSet.Get().IsDirty() || tileMap.Get().GetColumnsCount() == 0 || tileMap.Get().GetRowsCount() == 0) return 150.f; else return tileMap.Get().GetRowsCount() * tileSet.Get().tileSize.y; } void RuntimeTileMapObject::OnPositionChanged() { //Moves all hitboxes (use the previous pos to move them) for(std::vector::iterator it = hitboxes.begin(); it != hitboxes.end(); it++) { it->Move(GetX() - oldX, GetY() - oldY); } oldX = GetX(); oldY = GetY(); } #ifdef GD_IDE_ONLY void RuntimeTileMapObject::GetPropertyForDebugger(std::size_t propertyNb, gd::String & name, gd::String & value) const { } bool RuntimeTileMapObject::ChangeProperty(std::size_t propertyNb, gd::String newValue) { return true; } std::size_t RuntimeTileMapObject::GetNumberOfProperties() const { return 0; } #endif std::vector RuntimeTileMapObject::GetHitBoxes() const { return hitboxes; } float RuntimeTileMapObject::GetTileWidth() const { return tileSet.Get().tileSize.x; } float RuntimeTileMapObject::GetTileHeight() const { return tileSet.Get().tileSize.y; } float RuntimeTileMapObject::GetMapWidth() const { return static_cast(tileMap.Get().GetColumnsCount()); } float RuntimeTileMapObject::GetMapHeight() const { return static_cast(tileMap.Get().GetRowsCount()); } void RuntimeTileMapObject::SetMapSize(int width, int height) { if(width < 0 || height < 0 || (GetMapWidth() == width && GetMapHeight() == height)) //Avoid changing the size if the same return; tileMap.Get().SetSize(width, height); vertexArray = TileMapExtension::GenerateVertexArray(tileSet.Get(), tileMap.Get()); hitboxes = TileMapExtension::GenerateHitboxes(tileSet.Get(), tileMap.Get()); } float RuntimeTileMapObject::GetTile(int layer, int column, int row) { if(layer < 0 || layer > 2 || column < 0 || column >= tileMap.Get().GetColumnsCount() || row < 0 || row >= tileMap.Get().GetRowsCount()) return -1.f; return static_cast(tileMap.Get().GetTile(layer, column, row)); } void RuntimeTileMapObject::SetTile(int layer, int column, int row, int tileId) { if(layer < 0 || layer > 2 || column < 0 || column >= tileMap.Get().GetColumnsCount() || row < 0 || row >= tileMap.Get().GetRowsCount()) return; //Just update a single tile in the tile map tileMap.Get().SetTile(layer, column, row, tileId); TileMapExtension::UpdateVertexArray(vertexArray, layer, column, row, tileSet.Get(), tileMap.Get()); TileMapExtension::UpdateHitboxes(hitboxes, sf::Vector2f(GetX(), GetY()), layer, column, row, tileSet.Get(), tileMap.Get()); } float RuntimeTileMapObject::GetColumnAt(float x) { return static_cast(floor((x - GetX())/tileSet.Get().tileSize.x)); } float RuntimeTileMapObject::GetRowAt(float y) { return static_cast(floor((y - GetY())/tileSet.Get().tileSize.y)); } gd::String RuntimeTileMapObject::SaveAsString() const { return tileMap.Get().SerializeToString(); } void RuntimeTileMapObject::LoadFromString(const gd::String &str) { tileMap.Get().UnserializeFromString(str); needGeneration = true; } void RuntimeTileMapObject::ChangeTexture(const gd::String &textureName, RuntimeScene &scene) { tileSet.Get().textureName = textureName; tileSet.Get().LoadResources(*(scene.game)); needGeneration = true; } bool GD_EXTENSION_API SingleTileCollision(std::map*> tileMapList, int layer, int column, int row, std::map*> objectLists, bool conditionInverted) { return TwoObjectListsTest(tileMapList, objectLists, conditionInverted, [layer, column, row](RuntimeObject* tileMapObject_, RuntimeObject * object) { RuntimeTileMapObject *tileMapObject = dynamic_cast(tileMapObject_); if(!tileMapObject || tileMapObject->tileSet.Get().IsDirty()) return false; //Get the tile hitbox int tileId = tileMapObject->tileMap.Get().GetTile(layer, column, row); if(tileId < 0 || tileId >= tileMapObject->tileSet.Get().GetTilesCount()) return false; Polygon2d tileHitbox = tileMapObject->tileSet.Get().GetTileHitbox(tileId).hitbox; tileHitbox.Move(tileMapObject->GetX() + column * tileMapObject->tileSet.Get().tileSize.x, tileMapObject->GetY() + row * tileMapObject->tileSet.Get().tileSize.y); //Get the object hitbox std::vector objectHitboxes = object->GetHitBoxes(); for(std::vector::iterator hitboxIt = objectHitboxes.begin(); hitboxIt != objectHitboxes.end(); ++hitboxIt) { if(PolygonCollisionTest(tileHitbox, *hitboxIt).collision) { return true; } } return false; }); }