Guest User

CLevel.cpp

a guest
Feb 5th, 2015
18
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.79 KB | None | 0 0
  1. #include "Level.h"
  2. #include "ParticleLoader.h"
  3. #include "ParticleManager.h"
  4.  
  5. CLevel::CLevel()
  6. {
  7.     Initialize();
  8. }
  9.  
  10. CLevel::CLevel(const std::string& levelFilename, CLevelLoader* levelLoader)
  11. {
  12.     Initialize();
  13.  
  14.     // Sets the level loader.
  15.     m_LevelLoader = levelLoader;
  16.  
  17.     LoadLevel(levelFilename, ELevelFileFormat::TMX);
  18. }
  19.  
  20. CLevel::~CLevel()
  21. {
  22.     delete m_LevelStats;
  23.     delete m_LevelObjectStorage;
  24. }
  25.  
  26. /*
  27. Sets the offset of the level.
  28. */
  29. void CLevel::SetLevelOffset(TVector2 offset)
  30. {
  31.     m_LevelStats->m_LevelOffset = offset;
  32. }
  33.  
  34. /*
  35. Returns the size of the level.
  36. */
  37. TVector2 CLevel::GetLevelSize()
  38. {
  39.     return m_LevelStats->m_LevelSize;
  40. }
  41.  
  42. /*
  43. Sets the size of the level.
  44. */
  45. void CLevel::SetLevelSize(TVector2 size)
  46. {
  47.     m_LevelStats->m_LevelSize = size;
  48. }
  49.  
  50. /*
  51. Returns the object storage of the level.
  52. */
  53. SLevelObjectStorage* CLevel::GetLevelObjectStorage()
  54. {
  55.     return m_LevelObjectStorage;
  56. }
  57.  
  58. /*
  59. Sets the debug state of the level.
  60. */
  61. void CLevel::SetDebugState(bool value)
  62. {
  63.     m_LevelStats->m_DebugState = value;
  64. }
  65.  
  66. /*
  67. Sets if the offset should be clamped to level borders. Used mainly for CutScenes.
  68. */
  69. void CLevel::SetOffsetClamp(bool value)
  70. {
  71.     m_LevelStats->m_LevelOffsetClampEnabled = value;
  72. }
  73.  
  74. /*
  75. Returns the offset of the level.
  76. */
  77. TVector2 CLevel::GetLevelOffset()
  78. {
  79.     if (m_LevelStats->m_LevelOffsetClampEnabled)
  80.     {
  81.         TVector2 offset = TVector2(m_LevelStats->m_LevelOffset);
  82.  
  83.         // Clamps the level offset to the size of the level (adjusted with the size of the viewport).
  84.         TVector2 levelMin((-(m_LevelStats->m_LevelSize)) + TVector2(CGameWindow::GetWindowViewport()->W / CRenderer::GetResolutionRenderScale().X, CGameWindow::GetWindowViewport()->H / CRenderer::GetResolutionRenderScale().Y));
  85.         TVector2 levelMax(0, 0);
  86.         offset.Clamp(levelMin, levelMax);
  87.  
  88.         return offset;
  89.     }
  90.     return m_LevelStats->m_LevelOffset;
  91. }
  92.  
  93. /*
  94. Initializes the level.
  95. */
  96. void CLevel::Initialize()
  97. {
  98.     m_LevelStats = new SLevelStats();
  99.     m_LevelStats->m_LevelGridColor = TColor(TColor::White);
  100.     m_LevelStats->m_LevelGridColor.A = 80;
  101.     m_LevelParallaxStats = new SLevelParallaxStats();
  102.     m_LevelObjectStorage = new SLevelObjectStorage();
  103.  
  104.     // Initializes the parallax scrolling elements.
  105.     m_LevelParallaxStats->m_ParallaxSkyColor = TColor::SkyBlue;
  106.     AddParallaxLayer(new SLevelParallax(m_LevelParallaxStats, "Background2Large.png", new SRect(0.0f, 0.0f, 2560.0f, 960.0f), 0.8f, 0.1f, -320, -100), 0);
  107.     AddParallaxLayer(new SLevelParallax(m_LevelParallaxStats, "Background1Large.png", new SRect(0.0f, 0.0f, 2560.0f, 960.0f), 0.7f, 0.15f, -320, -250), 1);
  108.     AddParallaxLayer(new SLevelParallax(m_LevelParallaxStats, "Background2Large.png", new SRect(0.0f, 0.0f, 2560.0f, 960.0f), 0.6f, 0.2f, -420, -50), 2);
  109. }
  110.  
  111. /*
  112. Returns a BoundingBox from the object.
  113. */
  114. CBoundingBox* CLevel::ObjectToBoundingBox(CLevelObjectTMX* object)
  115. {
  116.     return new CBoundingBox((float)object->GetX(), (float)object->GetY(), (float)object->GetWidth(), (float)object->GetHeight());
  117. }
  118.  
  119. /*
  120. Adds an entity to the level.
  121. */
  122. void CLevel::AddEntity(CEntity* entity, DEntityStorageType storageType, int zModifier)
  123. {
  124.     // Z is used for depth sorting in the entity sets.
  125.     entity->SetZ(m_LevelStats->m_LevelLayerZ + zModifier);
  126.  
  127.     // Adds the entity's collision box to the level's collision boxes.
  128.     if (storageType & COLLISION)
  129.     {
  130.         m_LevelObjectStorage->m_BoundingBoxes.push_back(entity->GetBoundingBox());
  131.     }
  132.     // Adds the entity to the static entities.
  133.     if (storageType & STATIC)
  134.     {
  135.         m_LevelObjectStorage->m_StaticEntities.push_back(entity);
  136.     }
  137.     // Adds the entity to the dynamic entities.
  138.     if (storageType & DYNAMIC)
  139.     {
  140.         m_LevelObjectStorage->m_DynamicEntities.push_back(entity);
  141.     }
  142.  
  143.     // Adds the entity to the renderable entities.
  144.     m_LevelObjectStorage->m_Entities.push_back(entity);
  145.  
  146.     entity->SpawnEntity(this);
  147. }
  148.  
  149. /*
  150. Removes an entity from the level.
  151. */
  152. void CLevel::RemoveEntity(CEntity* entity)
  153. {
  154.     entity->KillEntity(this);
  155.     // Pushes the entity to an array, to clear all the entities at once after
  156.     // the updating has been done.
  157.     m_LevelObjectStorage->m_RemovedEntities.push_back(entity);
  158. }
  159.  
  160. /*
  161. Adds a parallax layer to the level.
  162. */
  163. void CLevel::AddParallaxLayer(SLevelParallax* parallaxLayer, int z)
  164. {
  165.     // Sets the Z of the layer.
  166.     parallaxLayer->m_LayerZ = z;
  167.     // Adds the layer.
  168.     m_LevelParallaxStats->m_ParallaxLayers.push_back(parallaxLayer);
  169.     // Sorts the layer by their Z value.
  170.     std::sort(m_LevelParallaxStats->m_ParallaxLayers.begin(), m_LevelParallaxStats->m_ParallaxLayers.end(), SLevelParallaxSort());
  171. }
  172.  
  173. /*
  174. Deletes and clears the entities that have been removed by RemoveEntity().
  175. */
  176. void CLevel::ClearRemovedEntities()
  177. {
  178.     // If there's no entities to remove.
  179.     if (m_LevelObjectStorage->m_RemovedEntities.size() == 0)
  180.     {
  181.         return;
  182.     }
  183.  
  184.     // Loops over all entities to be removed.
  185.     for (auto entity : m_LevelObjectStorage->m_RemovedEntities)
  186.     {
  187.         // Finds the locations for the entity in the entity containers.
  188.         auto entityLocation = std::find(m_LevelObjectStorage->m_Entities.begin(), m_LevelObjectStorage->m_Entities.end(), entity);
  189.         auto entityStaticLocation = std::find(m_LevelObjectStorage->m_StaticEntities.begin(), m_LevelObjectStorage->m_StaticEntities.end(), entity);
  190.         auto entityDynamicLocation = std::find(m_LevelObjectStorage->m_DynamicEntities.begin(), m_LevelObjectStorage->m_DynamicEntities.end(), entity);
  191.  
  192.         // Removes the entity from the general entity list if it was found.
  193.         if (!(entityLocation == m_LevelObjectStorage->m_Entities.end()))
  194.         {
  195.             m_LevelObjectStorage->m_Entities.erase(entityLocation);
  196.         }
  197.         // Removes the entity from the static entity list if it was found.
  198.         if (!(entityStaticLocation == m_LevelObjectStorage->m_StaticEntities.end()))
  199.         {
  200.             m_LevelObjectStorage->m_StaticEntities.erase(entityStaticLocation);
  201.         }
  202.         // Removes the entity from the dynamic entity list if it was found.
  203.         if (!(entityDynamicLocation == m_LevelObjectStorage->m_DynamicEntities.end()))
  204.         {
  205.             m_LevelObjectStorage->m_DynamicEntities.erase(entityDynamicLocation);
  206.         }
  207.  
  208.         // Finds the location of the collision box of the entity if the entity has a bounding box.
  209.         if (entity->GetBoundingBox())
  210.         {
  211.             auto collisionBoxLocation = std::find(m_LevelObjectStorage->m_BoundingBoxes.begin(), m_LevelObjectStorage->m_BoundingBoxes.end(), entity->GetBoundingBox());
  212.  
  213.             // Removes the collision box if it was found.
  214.             if (!(collisionBoxLocation == m_LevelObjectStorage->m_BoundingBoxes.end()))
  215.             {
  216.                 m_LevelObjectStorage->m_BoundingBoxes.erase(collisionBoxLocation);
  217.             }
  218.         }
  219.  
  220.         // Now the entity has been removed from all containers and will be deleted.
  221.         // (Actually there is still a pointer to it in m_RemovedEntities, but it will
  222.         //  be cleared real soon)
  223.         delete entity;
  224.     }
  225.  
  226.     // Clears the list as all the entities are removed above.
  227.     m_LevelObjectStorage->m_RemovedEntities.clear();
  228. }
  229.  
  230. /*
  231. Sorts the entities in the object storage.
  232. */
  233. void CLevel::SortLevelObjectStorage()
  234. {
  235.     // Sorts the entities.
  236.     std::sort(m_LevelObjectStorage->m_Entities.begin(), m_LevelObjectStorage->m_Entities.end(), SEntitySort());
  237.     // Sorts the static & dynamic entities. Sorting these is not necessary, so this can be a possible performance improvement.
  238.     // TODO: Possibly disable sorting these.
  239.     std::sort(m_LevelObjectStorage->m_StaticEntities.begin(), m_LevelObjectStorage->m_StaticEntities.end(), SEntitySort());
  240.     std::sort(m_LevelObjectStorage->m_DynamicEntities.begin(), m_LevelObjectStorage->m_DynamicEntities.end(), SEntitySort());
  241. }
  242.  
  243. /*
  244. Handles events and passes them to entities.
  245. */
  246. void CLevel::EventLevel(SDL_Event* event)
  247. {
  248.     // Passes the events to the entities. Only dynamic entities receive events.
  249.     for (auto entity : m_LevelObjectStorage->m_DynamicEntities)
  250.     {
  251.         entity->Event(event);
  252.     }
  253. }
  254.  
  255. /*
  256. Updates the entities in the level. Returns true if the level end trigger has been reached.
  257. */
  258. void CLevel::UpdateLevel(float deltaTime)
  259. {
  260.     // Updates the entities.
  261.     for (auto& entity : m_LevelObjectStorage->m_DynamicEntities)
  262.     {
  263.         entity->Update(deltaTime, this);
  264.     }
  265.  
  266.     // After all the entities have been updated, updates the triggers.
  267.     for (auto trigger : m_LevelObjectStorage->m_Triggers)
  268.     {
  269.         // If the condition on the trigger is met, the trigger is then executed.
  270.         if (trigger->ConditionTrigger(this))
  271.         {
  272.             trigger->ExecuteTrigger(this);
  273.         }
  274.     }
  275.  
  276.     // Clears the entities that have been removed during the frame.
  277.     ClearRemovedEntities();
  278. }
  279.  
  280. /*
  281. Renders the entities in the level and the parallax background levels.
  282. */
  283. void CLevel::RenderLevel(CRenderer* renderer)
  284. {
  285.     // Renders the sky.
  286.     renderer->Clear(m_LevelParallaxStats->m_ParallaxSkyColor);
  287.  
  288.     // Calculates the center of the screen to "loop" the parallax layer.
  289.     float wrapPosition = 320.0f;
  290.  
  291.     // Renders the parallax layers to the background.
  292.     for (auto parallaxLayer : m_LevelParallaxStats->m_ParallaxLayers)
  293.     {
  294.         // Calculates the position of the parallax layer.
  295.         TVector2 parallaxOffset = GetLevelOffset() * parallaxLayer->m_ParallaxFactor;
  296.  
  297.         // Wraps the layer (as they loop in parts).
  298.         while (abs(parallaxOffset.X) >= wrapPosition)
  299.         {
  300.             if (parallaxOffset.X < 0)
  301.             {
  302.                 parallaxOffset.X += wrapPosition;
  303.             }
  304.             else
  305.             {
  306.                 parallaxOffset.X -= wrapPosition;
  307.             }
  308.         }
  309.  
  310.         // Renders the layer.
  311.         renderer->SetRenderBatchOffset(parallaxOffset);
  312.         renderer->Render(parallaxLayer->m_ParallaxRenderDescription);
  313.     }
  314.  
  315.     // Renders various debug info if the debug mode is enabled.
  316.     if (m_LevelStats->m_DebugState)
  317.     {
  318.         RenderLevelGrid(renderer);
  319.     }
  320.  
  321.     renderer->SetRenderBatchOffset(GetLevelOffset());
  322.  
  323.     // Renders the entities.
  324.     for (auto entity : m_LevelObjectStorage->m_Entities)
  325.     {
  326.         renderer->Render(entity->GetRenderDescription());
  327.     }
  328.  
  329.     if (m_LevelStats->m_DebugState)
  330.     {
  331.         for (auto box : m_LevelObjectStorage->m_BoundingBoxes)
  332.         {
  333.             renderer->RenderBox(TColor::Red, box, false, true, true);
  334.         }
  335.     }
  336.  
  337.     // Resets the offset.
  338.     renderer->SetRenderBatchOffset(TVector2());
  339. }
  340.  
  341. /*
  342. Renders the debug grid of the level.
  343. */
  344. void CLevel::RenderLevelGrid(CRenderer* renderer)
  345. {
  346.     // Sets the offset.
  347.     renderer->SetRenderBatchOffset(GetLevelOffset());
  348.  
  349.     // Renders the grid.
  350.     for (int y = 0; y < GetLevelSize().Y; y += m_LevelStats->m_LevelTileSize)
  351.     {
  352.         for (int x = 0; x < GetLevelSize().X; x += m_LevelStats->m_LevelTileSize)
  353.         {
  354.             renderer->RenderBox(m_LevelStats->m_LevelGridColor, (float)x, (float)y, (float)m_LevelStats->m_LevelTileSize, (float)m_LevelStats->m_LevelTileSize);
  355.         }
  356.     }
  357.  
  358.     renderer->SetRenderBatchOffset(TVector2());
  359. }
  360.  
  361. /*
  362. Loads the level.
  363. */
  364. void CLevel::LoadLevel(const std::string& levelFileName, ELevelFileFormat levelFileFormat)
  365. {
  366.     m_LevelStats->m_LevelFileName = levelFileName;
  367.  
  368.     // Loads the level with the given format.
  369.     switch (levelFileFormat)
  370.     {
  371.         // Loads .TMX files.
  372.         case ELevelFileFormat::TMX:
  373.         {
  374.             // Creates a level loader for the TMX data format.
  375.             CLevelLoaderTMX* levelLoader = new CLevelLoaderTMX(levelFileName);
  376.  
  377.             // Loads the tilesets.
  378.             for (auto tileset : levelLoader->GetTilesets())
  379.             {
  380.                 LoadTileset(tileset);
  381.             }
  382.  
  383.             // Checks if the amount of layers is too big. This should never happen,
  384.             // but you never know... This is to ensure that overlaid entities
  385.             // are always overlaid.
  386.             if (levelLoader->GetLayers().size() > MAX_LAYER_COUNT)
  387.             {
  388.                 GPrint("Max Layer Amount exceeded in file: ", levelFileName);
  389.             }
  390.  
  391.             // Loads the layers.
  392.             for (auto layer : levelLoader->GetLayers())
  393.             {
  394.                 // Only loads visible layers.
  395.                 if (layer->GetLayerVisible())
  396.                 {
  397.                     LoadLayer(layer);
  398.                 }
  399.             }
  400.  
  401.             // Loads the object groups.
  402.             for (auto objectGroup : levelLoader->GetObjectGroups())
  403.             {
  404.                 LoadObjectGroup(objectGroup);
  405.             }
  406.  
  407.             // Sorts the entities.
  408.             SortLevelObjectStorage();
  409.  
  410.             // Marks the level as loaded.
  411.             m_LevelStats->m_LevelLoaded = true;
  412.             break;
  413.         }
  414.         default:
  415.             break;
  416.     }
  417. }
  418.  
  419. /*
  420. Loads a layer.
  421. */
  422. void CLevel::LoadLayer(CLevelLayerTMX* layer)
  423. {
  424.     // Initializes the level size if it's not calculated yet.
  425.     if (m_LevelStats->m_LevelSize == TVector2())
  426.     {
  427.         m_LevelStats->m_LevelSize = TVector2(layer->GetLayerWidth(), layer->GetLayerHeight()) * (float)m_LevelStats->m_LevelTileSize;
  428.     }
  429.  
  430.     // Tiles on the "EntityOverlay" layer should be drawn on top of everything.
  431.     int layerAddition = layer->GetLayerName() == "EngineOverlay" ? MAX_LAYER_COUNT : 0;
  432.  
  433.     // Loads the layer data.
  434.     for (auto tile : layer->GetLevelTileData())
  435.     {
  436.         // Calculates the position for the tile.
  437.         float xTilePos = (float)tile->GetX() * (float)m_LevelStats->m_LevelTileSize;
  438.         float yTilePos = (float)tile->GetY() * (float)m_LevelStats->m_LevelTileSize;
  439.  
  440.         // Creates the tile entity.
  441.         CEntityTile* tileEntity = new CEntityTile(tile->GetTileID(), xTilePos, yTilePos);
  442.  
  443.         // Adds the entity.
  444.         AddEntity(tileEntity, STATIC_NOCOLLISION, layerAddition);
  445.     }
  446.  
  447.     // Increments the Z Count to render the entities in the correct order.
  448.     m_LevelStats->m_LevelLayerZ++;
  449. }
  450.  
  451. /*
  452. Loads a tileset and sets it to the tileset that all the tiles in the game will use.
  453. This is not foolproof, as if a level that uses a different tileset is loaded after
  454. this tileset, the tileset the tile uses is overridden.
  455. */
  456. void CLevel::LoadTileset(CLevelTilesetTMX* tileset)
  457. {
  458.     // Loads the spritesheet.
  459.     CSpriteSheet* tileSpriteSheet = CContentLoader::LoadSpriteSheet(tileset->GetTilesetSourcePath(), tileset->GetTileWidth(), tileset->GetTileHeight());
  460.     // Sets the spritesheet for the tiles.
  461.     CEntityTile::SetSpriteSheet(tileSpriteSheet);
  462.  
  463.     // Sets the tile size.
  464.     // TODO: Doesn't support non-square tiles.
  465.     m_LevelStats->m_LevelTileSize = tileset->GetTileWidth();
  466. }
  467.  
  468. /*
  469. Loads an object group.
  470. */
  471. void CLevel::LoadObjectGroup(CLevelObjectGroupTMX* objectGroup)
  472. {
  473.     // These names are used from the engine, and unless a use that they offer is wanted
  474.     // the names should be avoided
  475.     bool triggerGroup = (objectGroup->GetObjectGroupName() == "EngineTrigger");
  476.     bool collisionGroup = (objectGroup->GetObjectGroupName() == "EngineCollision");
  477.  
  478.     // Loads the objects in the object group.
  479.     for (auto object : objectGroup->GetObjectGroupObjectData())
  480.     {
  481.         // Adds triggers to the level. Triggers define different areas that can be checked against and then
  482.         // different modifiers and methods can be executed.
  483.         if (triggerGroup)
  484.         {
  485.             m_LevelObjectStorage->m_Triggers.push_back(new CTrigger(ObjectToBoundingBox(object), object->GetName()));
  486.         }
  487.         // Adds collision boxes to the level. These boxes are drawn in the level editor to allow
  488.         // basically tessellation of small collision boxes into bigger ones..
  489.         else if (collisionGroup)
  490.         {
  491.             m_LevelObjectStorage->m_BoundingBoxes.push_back(ObjectToBoundingBox(object));
  492.         }
  493.         // Passes all objects to the level loader (if one exists).
  494.         if (m_LevelLoader)
  495.         {
  496.             // Loads the entity.
  497.             m_LevelLoader->LoadEntity(this, object, objectGroup);
  498.         }
  499.     }
  500. }
Advertisement
Add Comment
Please, Sign In to add comment