diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index d4c6560a..8ff4f70e 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -1993,6 +1993,8 @@ void AiL::InitializeLevel(std::string mapFile,MapName map){ if(MAP_TILESETS.find("assets/maps/"+baseSourceDir)==MAP_TILESETS.end()){ TSXParser tileset(baseDir+tag.data["source"]); Renderable*r=NEW Renderable(); + + if(tileset.GetData().tilewidth==0||tileset.GetData().tileheight==0)ERR(std::format("WARNING! Failed to load map {}! Found a tileset {} with a width of {} and height of {}. Zero values are not allowed!",map,"assets/maps/"+baseSourceDir,tileset.GetData().tilewidth,tileset.GetData().tileheight)); MAP_TILESETS["assets/maps/"+baseSourceDir].tilewidth=tileset.GetData().tilewidth; MAP_TILESETS["assets/maps/"+baseSourceDir].tileheight=tileset.GetData().tileheight; MAP_TILESETS["assets/maps/"+baseSourceDir].tileset=r; @@ -2053,6 +2055,8 @@ void AiL::InitializeLevel(std::string mapFile,MapName map){ SetDrawTarget(nullptr); r->Decal()->Update(); } + + ComputeModeColors(MAP_TILESETS["assets/maps/"+baseSourceDir]); } } @@ -2509,18 +2513,24 @@ TilesheetData AiL::GetTileSheet(MapName map,int tileID){ if(tileData.size()==1){ size_t slashMarkerSourceDir = tileData[0].data["source"].find_last_of('/'); std::string baseSourceDir=tileData[0].data["source"].substr(slashMarkerSourceDir+1); - return {&MAP_TILESETS["assets/maps/"+baseSourceDir],1}; + return {&MAP_TILESETS["assets/maps/"+baseSourceDir],1,MAP_TILESETS["assets/maps/"+baseSourceDir].tilecols[tileID]}; } else { for (int i=1;iAiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){ - if(pos.x<0||pos.y<0||pos.x>=GetCurrentMapData().width*game->GetCurrentMapData().tilewidth||pos.y>=GetCurrentMapData().height*game->GetCurrentMapData().tilewidth)return NO_COLLISION; - if(GetCurrentMap().optimizedTile)return NO_COLLISION; //Overworld map has no collision. + MapTag&mapData=MAP_DATA[map].MapData; + if(pos.x<0||pos.y<0||pos.x>=mapData.width*mapData.tilewidth||pos.y>=mapData.height*mapData.tilewidth)return NO_COLLISION; + if(MAP_DATA[map].optimizedTile)return NO_COLLISION; //Overworld map has no collision. bool hasTerrain=false; - for(const LayerTag&layer:GetCurrentMap().LayerData){ //Figure out if any tile at this position is terrain. If so, we have a collision box to check. + for(const LayerTag&layer:MAP_DATA[map].LayerData){ //Figure out if any tile at this position is terrain. If so, we have a collision box to check. if(Unlock::IsUnlocked(layer.unlockCondition)){ - int tileID=layer.tiles[pos.y/GetCurrentMapData().tilewidth][pos.x/GetCurrentMapData().tilewidth]-1; + int tileID=layer.tiles[pos.y/mapData.tilewidth][pos.x/mapData.tilewidth]-1; if(tileID==-1)continue; - const TilesheetData&data=GetTileSheet(GetCurrentLevel(),tileID); + const TilesheetData&data=GetTileSheet(map,tileID); if(data.tileset->isTerrain){ hasTerrain=true; break; } } } - if(!hasTerrain)return geom2d::rect({0.f,0.f},{float(GetCurrentMapData().tilewidth),float(GetCurrentMapData().tilewidth)}); //We assume no terrain means we can't walk on this. + if(!hasTerrain)return geom2d::rect({0.f,0.f},{float(mapData.tilewidth),float(mapData.tilewidth)}); //We assume no terrain means we can't walk on this. #pragma region Lower Bridge Collision Check if(!upperLevel){ //We are looking for lower bridge collisions. for(ZoneData&zone:MAP_DATA[map].ZoneData["LowerBridgeCollision"]){ if(geom2d::contains(zone.zone,pos)){ - return {{0,0},{float(game->GetCurrentMapData().tilewidth),float(game->GetCurrentMapData().tilewidth)}}; + return {{0,0},{float(mapData.tilewidth),float(mapData.tilewidth)}}; } } } #pragma endregion //The logic here is, if there's a tile on the bridge, we respect that tile instead if we're on the upper level. So we don't check other layers when we are on the upper level and there is a tile below us. if(upperLevel&&bridgeLayerIndex!=-1){ - int tileID=MAP_DATA[map].LayerData[bridgeLayerIndex].tiles[int(pos.y)/GetCurrentMapData().tilewidth][int(pos.x)/GetCurrentMapData().tilewidth]-1; + int tileID=MAP_DATA[map].LayerData[bridgeLayerIndex].tiles[int(pos.y)/mapData.tilewidth][int(pos.x)/mapData.tilewidth]-1; if(tileID!=-1){ if (GetTileSheet(map,tileID%1000000).tileset->collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset->collision.end()){ return GetTileSheet(map,tileID%1000000).tileset->collision[tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1].collision; @@ -2581,7 +2592,7 @@ geom2d::rectAiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){ if(Unlock::IsUnlocked(layer.unlockCondition)){ //auto HasNoClass=[&](){return layer.tag.data.find("class")==layer.tag.data.end();}; if(counter!=bridgeLayerIndex){ - int tileID=layer.tiles[int(pos.y)/GetCurrentMapData().tilewidth][int(pos.x)/GetCurrentMapData().tilewidth]-1; + int tileID=layer.tiles[int(pos.y)/mapData.tilewidth][int(pos.x)/mapData.tilewidth]-1; if(tileID!=-1&&GetTileSheet(map,tileID%1000000).tileset->collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset->collision.end()){ geom2d::rectcollisionRect=GetTileSheet(map,tileID%1000000).tileset->collision[tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1].collision; if(foundRect==NO_COLLISION){ @@ -2601,6 +2612,25 @@ geom2d::rectAiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){ return foundRect; } +Pixel AiL::GetTileColor(MapName map,vf2d pos,bool upperLevel){ + MapTag&mapData=MAP_DATA[map].MapData; + if(pos.x<0||pos.y<0||pos.x>=mapData.width*mapData.tilewidth||pos.y>=mapData.height*mapData.tilewidth)return BLANK; + if(MAP_DATA[map].optimizedTile)return BLANK; //Overworld map has no collision. + + + bool hasTerrain=false; + for(const LayerTag&layer:MAP_DATA[map].LayerData){ //Figure out if any tile at this position is terrain. If so, we have a collision box to check. + if(Unlock::IsUnlocked(layer.unlockCondition)){ + int tileID=layer.tiles[pos.y/mapData.tilewidth][pos.x/mapData.tilewidth]-1; + if(tileID==-1)continue; + const TilesheetData&data=GetTileSheet(map,tileID); + return data.tilecol; + } + } + + return BLANK; +} + const MapName&AiL::GetCurrentLevel()const{ if(GameState::STATE!=nullptr&&GameState::STATE==GameState::states[States::STORY]){ //If we're inside a story, we expect the map/level name to be from the visual novel itself. Right now currentLevel would be WORLD_MAP which is not useful for a function like this. return VisualNovel::novel.storyLevel; @@ -3994,4 +4024,28 @@ void AiL::SetCompletedStageFlag(){ } void AiL::ResetCompletedStageFlag(){ prevStageCompleted=false; +} +void AiL::ComputeModeColors(TilesetData&tileset){ + for(int y=0;ySprite()->height/tileset.tileheight;y++){ + for(int x=0;xSprite()->width/tileset.tilewidth;x++){ + #pragma region Individual tile iteration + std::unordered_mappixelCounts; + Pixel modeCol=BLANK; + int maxCount=0; + vi2d pixelOffset=vi2d{x,y}*tileset.tilewidth; + for(int pixelY=0;pixelYSprite()->GetPixel(targetPixel); + pixelCounts[tileCol.n]++; + if(pixelCounts[tileCol.n]>maxCount){ + modeCol=tileCol; + pixelCounts[tileCol.n]=maxCount; + } + } + } + tileset.tilecols.push_back(modeCol); + #pragma endregion + } + } } \ No newline at end of file diff --git a/Adventures in Lestoria/AdventuresInLestoria.h b/Adventures in Lestoria/AdventuresInLestoria.h index 8e428054..54593108 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.h +++ b/Adventures in Lestoria/AdventuresInLestoria.h @@ -190,6 +190,8 @@ private: void ValidateGameStatus(); void _PrepareLevel(MapName map,MusicChange changeMusic); + //This function assigns the mode tile colors of each loaded tileset. + void ComputeModeColors(TilesetData&tileset); #ifndef __EMSCRIPTEN__ ::discord::Result SetupDiscord(); #endif @@ -252,6 +254,7 @@ public: TilesheetData GetTileSheet(MapName map,int tileID); //Gets the rectangle of the tile collision at this tile. If upperLevel is set to true, the collision tile must be in a Bridge class layer for the tile to hit. Also, zones containing LowerBridgeCollision will apply when upperLevel is set to false. geom2d::rectGetTileCollision(MapName map,vf2d pos,bool upperLevel=false); + Pixel GetTileColor(MapName map,vf2d pos,bool upperLevel=false); //Checks if the point resides inside of a collision tile. bool HasTileCollision(MapName map,vf2d pos,bool upperLevel=false); const MapName&GetCurrentLevel()const; diff --git a/Adventures in Lestoria/Map.h b/Adventures in Lestoria/Map.h index 3f1535a0..339940a0 100644 --- a/Adventures in Lestoria/Map.h +++ b/Adventures in Lestoria/Map.h @@ -64,11 +64,13 @@ struct TilesetData{ std::mapstaircaseTiles; std::map>animationData; std::setreflectiveData; + std::vectortilecols; }; struct TilesheetData{ TilesetData*tileset; int firstgid; + Pixel tilecol; bool operator==(const TilesheetData&rhs){ return tileset==rhs.tileset&&firstgid==rhs.firstgid; } diff --git a/Adventures in Lestoria/Minimap.cpp b/Adventures in Lestoria/Minimap.cpp index ba7b0728..10c2305a 100644 --- a/Adventures in Lestoria/Minimap.cpp +++ b/Adventures in Lestoria/Minimap.cpp @@ -60,18 +60,27 @@ void Minimap::Initialize(){ for(int x=0;xGetCurrentMapData().width;x++){ for(int y=0;yGetCurrentMapData().height;y++){ bool tileFound=false; + bool collision=false; + Pixel tileCol; for(const LayerTag&layer:game->MAP_DATA[game->GetCurrentLevel()].GetLayers()){ if(Unlock::IsUnlocked(layer.unlockCondition)){ int tileID=layer.tiles[y][x]-1; if(tileID!=-1){ tileFound=true; if(game->GetTileCollision(game->GetCurrentMapName(),vf2d{float(x),float(y)}*game->GetCurrentMapData().tilewidth)!=game->NO_COLLISION){ - minimap.Sprite()->SetPixel({x,y},BLACK); + game->SetPixelMode(Pixel::ALPHA); + minimap.Sprite()->SetPixel({x,y},BLANK); + game->SetPixelMode(Pixel::NORMAL); + collision=true; } - break; + tileCol=game->GetTileColor(game->GetCurrentMapName(),vf2d{float(x),float(y)}*game->GetCurrentMapData().tilewidth); } } } + if(tileFound&&!collision){ + if(tileCol==BLANK)ERR("WARNING! A tile should not be blank as we should have handled all conditions that would've caused that in a different color! THIS SHOULD NOT BE HAPPENING!") + minimap.Sprite()->SetPixel({x,y},tileCol); + }else if(!tileFound){ game->SetPixelMode(Pixel::ALPHA); minimap.Sprite()->SetPixel({x,y},BLANK); @@ -88,5 +97,11 @@ void Minimap::Update(){ } void Minimap::Draw(){ + for(int y=-1;y<=1;y++){ + for(int x=-1;x<=1;x++){ + if(x==0&&y==0)continue; + else game->DrawDecal(vf2d{float(game->ScreenWidth()-minimap.Sprite()->width),0}+vf2d{float(x),float(y)},minimap.Decal(),{1.f,1.f},BLACK); + } + } game->DrawDecal(vf2d{float(game->ScreenWidth()-minimap.Sprite()->width),0},minimap.Decal()); } \ No newline at end of file diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index 3287a2f9..15d219c0 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -19,9 +19,6 @@ Steel Weapons appear in the demo for Chapter 2. Update display counters on the overworld map. Pressing movement keys that negate each other shouldn't cause a walking animation to occur. ->Start with a completely white image. ->Iterate through all tiles, no tile means set to transparent. Collision tile means set to black. ->Generate a blank map cover image. >As the player navigates around the map, the blank map canvas gets updated based on distance. >If a chunk has not been explored yet, it gets flagged as explored (probably unlock the chunks around the player as well). diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index dcf327df..3d5af4ac 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 1 #define VERSION_MINOR 1 #define VERSION_PATCH 0 -#define VERSION_BUILD 8675 +#define VERSION_BUILD 8703 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/Campaigns/1_2.tmx b/Adventures in Lestoria/assets/Campaigns/1_2.tmx index 4ce4dec1..5687bf86 100644 --- a/Adventures in Lestoria/assets/Campaigns/1_2.tmx +++ b/Adventures in Lestoria/assets/Campaigns/1_2.tmx @@ -1,5 +1,5 @@ - + diff --git a/Adventures in Lestoria/assets/Campaigns/1_3.tmx b/Adventures in Lestoria/assets/Campaigns/1_3.tmx index e9065997..dd341b16 100644 --- a/Adventures in Lestoria/assets/Campaigns/1_3.tmx +++ b/Adventures in Lestoria/assets/Campaigns/1_3.tmx @@ -1,5 +1,5 @@ - + diff --git a/Adventures in Lestoria/assets/Campaigns/Boss_1_B.tmx b/Adventures in Lestoria/assets/Campaigns/Boss_1_B.tmx index b574d1cd..4906a505 100644 --- a/Adventures in Lestoria/assets/Campaigns/Boss_1_B.tmx +++ b/Adventures in Lestoria/assets/Campaigns/Boss_1_B.tmx @@ -1,5 +1,5 @@ - + diff --git a/Adventures in Lestoria/assets/Campaigns/World_Map.tmx b/Adventures in Lestoria/assets/Campaigns/World_Map.tmx index c6684729..91e84986 100644 --- a/Adventures in Lestoria/assets/Campaigns/World_Map.tmx +++ b/Adventures in Lestoria/assets/Campaigns/World_Map.tmx @@ -9,8 +9,7 @@ - - + 713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,2147,82,82,82,239,256,256,256,256,256,256, diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 04243f26..6f7f0471 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ