Detection of terrain types.

main
sigonasr2 3 months ago
parent 6822a4916c
commit 32f6165f7d
  1. 7
      assets/HamsterGame.tiled-project
  2. 1
      assets/HamsterGame.tiled-session
  3. 2100
      assets/Terrain.tsx
  4. 53
      assets/propertytypes.json
  5. 8
      hamster.vcxproj
  6. 6
      hamster.vcxproj.filters
  7. 4
      src/Hamster.cpp
  8. 2
      src/Hamster.h
  9. 20
      src/HamsterGame.cpp
  10. 8
      src/HamsterGame.h
  11. 4
      src/TMXParser.h
  12. 60
      src/TSXParser.h
  13. 76
      src/Terrain.cpp
  14. 61
      src/Terrain.h

@ -13,9 +13,10 @@
{
"id": 1,
"name": "TerrainType",
"storageType": "string",
"storageType": "int",
"type": "enum",
"values": [
"Void",
"Rock",
"Grass",
"Sand",
@ -42,8 +43,8 @@
{
"name": "Terrain Type",
"propertyType": "TerrainType",
"type": "string",
"value": "Rock"
"type": "int",
"value": 0
}
],
"name": "TileProps",

@ -26,6 +26,7 @@
},
"frame.defaultDuration": 200,
"last.imagePath": "C:/Users/sigon/source/repos/hamster/assets",
"last.objectTypesPath": "C:/Users/sigon/source/repos/hamster/assets/propertytypes.json",
"map.lastUsedFormat": "tmx",
"map.tileHeight": 16,
"map.tileWidth": 16,

File diff suppressed because it is too large Load Diff

@ -0,0 +1,53 @@
[
{
"id": 1,
"name": "TerrainType",
"storageType": "int",
"type": "enum",
"values": [
"Void",
"Rock",
"Grass",
"Sand",
"Swamp",
"Lava",
"Shore",
"Ocean",
"Forest",
"Tunnel",
"Ice"
],
"valuesAsFlags": false
},
{
"color": "#ffa0a0a4",
"drawFill": true,
"id": 2,
"members": [
{
"name": "Solid",
"type": "bool",
"value": false
},
{
"name": "Terrain Type",
"propertyType": "TerrainType",
"type": "int",
"value": 10
}
],
"name": "TileProps",
"type": "class",
"useAs": [
"property",
"map",
"layer",
"object",
"tile",
"tileset",
"wangcolor",
"wangset",
"project"
]
}
]

@ -329,6 +329,10 @@ if %errorlevel% neq 0 goto :VCEnd</Command>
</SubType>
</ClCompile>
<ClCompile Include="src\Hamster.cpp" />
<ClCompile Include="src\Terrain.cpp">
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="src\util.cpp" />
</ItemGroup>
<ItemGroup>
@ -366,6 +370,10 @@ if %errorlevel% neq 0 goto :VCEnd</Command>
<ClInclude Include="src\olcUTIL_Animate2D.h" />
<ClInclude Include="src\olcUTIL_Camera2D.h" />
<ClInclude Include="src\olcUTIL_Geometry2D.h" />
<ClInclude Include="src\Terrain.h">
<SubType>
</SubType>
</ClInclude>
<ClInclude Include="src\TMXParser.h">
<SubType>
</SubType>

@ -19,6 +19,9 @@
<ClCompile Include="src\Border.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Terrain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\CMakeLists.txt" />
@ -82,5 +85,8 @@
<ClInclude Include="src\TSXParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Terrain.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -180,4 +180,8 @@ void Hamster::HandleCollision(){
const float Hamster::GetRadius()const{
return collisionRadius;
}
const Terrain::TerrainType Hamster::GetTerrainStandingOn()const{
return HamsterGame::Game().GetTerrainTypeAtPos(GetPos());
}

@ -40,6 +40,7 @@ All rights reserved.
#include <vector>
#include "olcUTIL_Geometry2D.h"
#include "olcUTIL_Animate2D.h"
#include "Terrain.h"
class Hamster{
enum PlayerControlled{
@ -90,4 +91,5 @@ public:
void MoveHamster();
void HandleCollision();
const float GetRadius()const;
const Terrain::TerrainType GetTerrainStandingOn()const;
};

@ -7,7 +7,7 @@ geom2d::rect<float>HamsterGame::SCREEN_FRAME{{96,0},{320,288}};
std::unordered_map<std::string,Animate2D::Animation<HamsterGame::AnimationState>>HamsterGame::ANIMATIONS;
std::unordered_map<std::string,Renderable>HamsterGame::GFX;
const std::string HamsterGame::ASSETS_DIR{"assets/"};
PixelGameEngine*HamsterGame::self{nullptr};
HamsterGame*HamsterGame::self{nullptr};
std::unordered_map<uint32_t,Animate2D::FrameSequence>HamsterGame::ANIMATED_TILE_IDS;
HamsterGame::HamsterGame(){
@ -71,6 +71,7 @@ void HamsterGame::LoadLevel(const std::string_view mapName){
const vf2d levelSpawnLoc{50,50}; //TEMPORARY
currentMap=TMXParser{ASSETS_DIR+std::string(mapName)};
currentTileset=TSXParser{ASSETS_DIR+std::string("Terrain.tsx")};
Hamster::LoadHamsters(levelSpawnLoc);
camera.SetTarget(Hamster::GetPlayer().GetPos());
@ -87,6 +88,21 @@ void HamsterGame::DrawGame(){
DrawLevelTiles();
Hamster::DrawHamsters(tv);
border.Draw();
DrawStringDecal(SCREEN_FRAME.pos+vf2d{1,1},"Terrain Type: "+Terrain::TerrainToString(Hamster::GetPlayer().GetTerrainStandingOn()),BLACK);
DrawStringDecal(SCREEN_FRAME.pos,"Terrain Type: "+Terrain::TerrainToString(Hamster::GetPlayer().GetTerrainStandingOn()));
}
const Terrain::TerrainType HamsterGame::GetTerrainTypeAtPos(const vf2d pos)const{
Terrain::TerrainType tileType{Terrain::VOID};
if(pos.x<=0.f||pos.y<=0.f||pos.x>=currentMap.value().GetData().GetMapData().width*16||pos.y>=currentMap.value().GetData().GetMapData().height*16)return tileType;
for(const LayerTag&layer:currentMap.value().GetData().GetLayers()){
int tileX{int(floor(pos.x)/16)};
int tileY{int(floor(pos.y)/16)};
int tileID{layer.tiles[tileY][tileX]-1};
if(tileID==-1)continue;
if(currentTileset.value().GetData().GetTerrainData().count(tileID))tileType=currentTileset.value().GetData().GetTerrainData().at(tileID).second;
}
return tileType;
}
void HamsterGame::DrawLevelTiles(){
@ -138,7 +154,7 @@ bool HamsterGame::OnUserDestroy(){
return true;
}
PixelGameEngine&HamsterGame::Game(){
HamsterGame&HamsterGame::Game(){
return *self;
}

@ -43,6 +43,8 @@ All rights reserved.
#include "olcUTIL_Camera2D.h"
#include "Border.h"
#include "TMXParser.h"
#include "TSXParser.h"
#include "Terrain.h"
class HamsterGame : public olc::PixelGameEngine
{
@ -62,9 +64,10 @@ public:
static const Renderable&GetGFX(const std::string_view img);
static const Animate2D::Animation<HamsterGame::AnimationState>&GetAnimations(const std::string_view img);
static PixelGameEngine&Game();
static HamsterGame&Game();
static std::unordered_map<uint32_t,Animate2D::FrameSequence>ANIMATED_TILE_IDS;
const double GetRuntime()const;
const Terrain::TerrainType GetTerrainTypeAtPos(const vf2d pos)const;
private:
void UpdateGame(const float fElapsedTime);
void DrawGame();
@ -75,9 +78,10 @@ private:
void _LoadImage(const std::string_view img);
static std::unordered_map<std::string,Renderable>GFX;
static std::unordered_map<std::string,Animate2D::Animation<HamsterGame::AnimationState>>ANIMATIONS;
static PixelGameEngine*self;
static HamsterGame*self;
Border border;
void DrawLevelTiles();
std::optional<TMXParser>currentMap;
std::optional<TSXParser>currentTileset;
double runTime{};
};

@ -129,7 +129,7 @@ struct Property{
class TMXParser{
public:
Map&GetData();
const Map&GetData()const;
private:
Map parsedMapInfo;
std::string fileName;
@ -256,7 +256,7 @@ class TMXParser{
rhs.FormatLayerData(os,rhs.LayerData) <<"\n";
return os;
}
Map&TMXParser::GetData() {
const Map&TMXParser::GetData()const{
return parsedMapInfo;
}
void TMXParser::ParseTag(std::string tag) {

@ -38,6 +38,7 @@ All rights reserved.
#pragma once
#include <sstream>
#include "TMXParser.h"
#include "Terrain.h"
using namespace olc;
@ -53,17 +54,20 @@ struct Tileset{
bool isTerrain=false;
std::unordered_map<int,TileCollisionData>CollisionData;
std::unordered_map<int,std::vector<int>>AnimationData;
std::unordered_map<int,std::pair<Terrain::SolidType,Terrain::TerrainType>>TerrainData;
friend std::ostream& operator << (std::ostream& os, Tileset& rhs);
public:
const std::unordered_map<int,std::pair<Terrain::SolidType,Terrain::TerrainType>>&GetTerrainData()const;
};
class TSXParser{
public:
Tileset&GetData();
const Tileset&GetData()const;
private:
Tileset parsedTilesetInfo;
void ParseTag(std::string tag);
std::string previousTag;
int previousTagID;
std::vector<std::string> previousTag;
std::vector<int> previousTagID;
public:
TSXParser(std::string file);
};
@ -73,13 +77,16 @@ class TSXParser{
#ifdef TSX_PARSER_SETUP
#undef TSX_PARSER_SETUP
extern bool _DEBUG_MAP_LOAD_INFO;
Tileset&TSXParser::GetData() {
const Tileset&TSXParser::GetData()const{
return parsedTilesetInfo;
}
std::ostream&operator<<(std::ostream& os, Tileset& rhs){
os<<rhs.ImageData.FormatTagData(rhs.ImageData.data)<<"\n";
return os;
}
const std::unordered_map<int,std::pair<Terrain::SolidType,Terrain::TerrainType>>&Tileset::GetTerrainData()const{
return TerrainData;
}
void TSXParser::ParseTag(std::string tag) {
XMLTag newTag;
//First character is a '<' so we discard it.
@ -138,25 +145,42 @@ class TSXParser{
parsedTilesetInfo.imageheight=newTag.GetInteger("height");
} else
if (newTag.tag=="tile"){
previousTag=newTag.tag;
previousTagID=newTag.GetInteger("id");
previousTag.emplace_back(newTag.tag);
previousTagID.emplace_back(newTag.GetInteger("id"));
} else
if(newTag.tag=="frame"){
//The way animation data is stored is every "animation_tile_precision" ms indicating which frame we should be on.
for(int&tagID:previousTagID){
for(int i=0;i<newTag.GetInteger("duration")/100;i++){
parsedTilesetInfo.AnimationData[tagID].push_back(newTag.GetInteger("tileid"));
}
}
} else
if (newTag.tag=="frame"){
if(newTag.tag=="property"&&newTag.data["propertytype"]=="TerrainType"){
//The way animation data is stored is every "animation_tile_precision" ms indicating which frame we should be on.
for(int i=0;i<newTag.GetInteger("duration")/100;i++){
parsedTilesetInfo.AnimationData[previousTagID].push_back(newTag.GetInteger("tileid"));
for(int&tagID:previousTagID){
std::pair<Terrain::SolidType,Terrain::TerrainType>&tileData{parsedTilesetInfo.TerrainData[tagID]};
tileData.second=Terrain::TerrainType(newTag.GetInteger("value"));
}
} else
if(newTag.tag=="property"&&newTag.data["propertytype"]=="Solid"){
//The way animation data is stored is every "animation_tile_precision" ms indicating which frame we should be on.
for(int&tagID:previousTagID){
std::pair<Terrain::SolidType,Terrain::TerrainType>&tileData{parsedTilesetInfo.TerrainData[tagID]};
tileData.first=Terrain::SolidType(newTag.GetBool("value"));
}
}
if (newTag.tag=="object"&&previousTag=="tile"){
TileCollisionData data;
data.collision=geom2d::rect<float>{{newTag.GetFloat("x"),newTag.GetFloat("y")},{newTag.GetFloat("width"),newTag.GetFloat("height")}};
if(!parsedTilesetInfo.CollisionData.count(previousTagID)){
parsedTilesetInfo.CollisionData[previousTagID]=data;
if (newTag.tag=="object"&&previousTag.size()>0&&previousTag[0]=="tile"){
for(int&tagID:previousTagID){
TileCollisionData data;
data.collision=geom2d::rect<float>{{newTag.GetFloat("x"),newTag.GetFloat("y")},{newTag.GetFloat("width"),newTag.GetFloat("height")}};
if(!parsedTilesetInfo.CollisionData.count(tagID)){
parsedTilesetInfo.CollisionData[tagID]=data;
}
}
}
}
TSXParser::TSXParser(std::string file)
:previousTagID(-1){
TSXParser::TSXParser(std::string file){
std::ifstream f(file,std::ios::in);
std::string accumulator="";
@ -178,6 +202,10 @@ class TSXParser{
//Beginning of XML tag.
accumulator=data;
if(accumulator.length()>1&&accumulator.at(1)=='/'){
if(accumulator.starts_with("</tile>")){
previousTag.clear();
previousTagID.clear();
}
accumulator=""; //Restart because this is an end tag.
}
if(accumulator.length()>1&&accumulator.find('>')!=std::string::npos){

@ -0,0 +1,76 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "Terrain.h"
const std::string Terrain::TerrainToString(const TerrainType type){
switch(type){
case ROCK:{
return "Rock";
}break;
case GRASS:{
return "Grass";
}break;
case SAND:{
return "Sand";
}break;
case SWAMP:{
return "Swamp";
}break;
case LAVA:{
return "Lava";
}break;
case SHORE:{
return "Shore";
}break;
case OCEAN:{
return "Ocean";
}break;
case FOREST:{
return "Forest";
}break;
case TUNNEL:{
return "Tunnel";
}break;
case ICE:{
return "Ice";
}break;
default:{
return "Void";
}
}
}

@ -0,0 +1,61 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#pragma once
#include <string>
namespace Terrain{
enum class SolidType{
SOLID=true,
WALKABLE=false,
};
#undef VOID
enum TerrainType{
VOID,
ROCK,
GRASS,
SAND,
SWAMP,
LAVA,
SHORE,
OCEAN,
FOREST,
TUNNEL,
ICE,
};
const std::string TerrainToString(const TerrainType type);
}
Loading…
Cancel
Save