Sign in to follow this  

Seeking assistance - TileMap, TileChunks, Placing terrain tiles

This topic is 681 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am having a surprising amount of difficulty with this stuff. I'll try to give a super brief breakdown, in the form of code definitions, of the concepts at play.

struct Terrain
{
  std::vector<short> m_Space;
};

class TileChunk
{
  friend class TileMap;
  std::vector<short> m_Region;
};

class TileMap
{
  std::map<uint64, TileChunk*> m_Map;
public:
  void Place(Terrain* t, uint32 x, uint32 y);
};

Alright that should be adequate for understanding the structure of things. Now for the coordinate systems...

 

All three classes have their own coordinate systems. The TileMap can be considered to be using the "world" coordinate system, as it needs to map tile coordinates to the correct locations inside the appropriate objects.

 

*The Problem*

I am having a problem with the class method below. The calculations I am performing provide the correct values if I avoid coordinate underflows in the tile map; I know this from a unit test designed to test the calculations when/if placing across 6 TileChunks, moving forward on the coordinate system. As soon as an underflow takes place however the Current_Terrain_Offsets have the wrong values. I am only able to make one transition between two separate terrains, so I can't inspect the behaviour as deeply as I'd like to. Otherwise I'd see if errors happened if I reached a new TileChunk or what would happen if I traveled many many screens of TileChunks. The terrains usually intersect a 0 boundary before I can make it very far. So the only inspecting I can really do is to move leftward or downward and force an underflow, or move in the other directions and wait for the terrain to intersect across that boundary.

 

I don't know what I hope to achieve posting this here, but maybe somebody can take a look and make sense of the calculations and figure out the logical flaw in the math/code.

 

One more thing, the result of the miscalculations is a subscript out of bounds error with the Terrain's vector; located inside the SetTiles method of the TileChunk being configured. Since the terrain is likely below 15 tiles on either axis, and the offset is massively huge due to the underflow.

void TileMap::Place( Terrain* t, uint32 starting_tile_x, uint32 starting_tile_y )
{
	uint32 increment = IncrementAtBit<uint32>( 0, LOWBITS + 1 );
	const coordinate Starting_Chunk( MapLocalCoord( starting_tile_x ), MapLocalCoord( starting_tile_y ) );
	const coordinate Starting_Chunk_Offset( ChunkLocalCoord( starting_tile_x ), ChunkLocalCoord( starting_tile_y ) );

	const uint8 c_cw = TileChunk::width; //Width of a Chunk
	const uint8 c_ch = TileChunk::height; //Height of a Chunk
	const uint16 c_ChunkColumns = (uint16)ceil( ( Starting_Chunk_Offset.x + t->width ) / (float)c_cw );
	const uint16 c_ChunkRows = (uint16)ceil( ( Starting_Chunk_Offset.y + t->height ) / (float)c_ch );

	coordinate Current_Chunk;
	coordinate Current_Chunk_Offset;
	coordinate Current_Chunk_Offset_Tile;
	coordinate Current_Terrain_Offset;

	TileChunk* chunk = nullptr;
	for ( uint32 r = 0; r < c_ChunkRows; ++r )
	{
		for ( uint32 c = 0; c < c_ChunkColumns; ++c )
		{
			Current_Chunk.x = Starting_Chunk.x + ( c * increment );
			Current_Chunk.y = Starting_Chunk.y + ( r * increment );

			Current_Chunk_Offset.x = ( c == 0 ? Starting_Chunk_Offset.x : 0 );
			Current_Chunk_Offset.y = ( r == 0 ? Starting_Chunk_Offset.y : 0 );

			Current_Chunk_Offset_Tile.x = Current_Chunk.x + Current_Chunk_Offset.x;
			Current_Chunk_Offset_Tile.y = Current_Chunk.y + Current_Chunk_Offset.y;

			Current_Terrain_Offset.x = Current_Chunk_Offset_Tile.x - Starting_Chunk_Offset.x;
			Current_Terrain_Offset.y = Current_Chunk_Offset_Tile.y - Starting_Chunk_Offset.y;

			uint64 key = MergeIntegers( Current_Chunk.x, Current_Chunk.y );
			auto it = m_Map.find( key );
			if ( it == m_Map.end() )
			{
				chunk = new TileChunk();
				chunk->m_TileSet = m_TileSet;
				it = m_Map.emplace( key, chunk ).first;
			}
			else
			{
				chunk = it->second;
			}
			chunk->SetTiles( t, Current_Chunk_Offset, Current_Terrain_Offset );
		}
	}
}
Edited by coope

Share this post


Link to post
Share on other sites

It doesn't seem like anybody was likely able to figure it out, or perhaps even try. Either way, I eventually figured out the fallacy.

 

The problem was I was subtracting an offset. When what I really needed to do was subtract the starting tile coordinates

Current_Terrain_Offset.x = Current_Chunk_Offset_Tile.x - starting_tile_x;
Current_Terrain_Offset.y = Current_Chunk_Offset_Tile.y - starting_tile_y;

edit:
Not sure replying to one's own post with the solution a day later is bad, but I don't like incomplete things. Maybe this thread will be good for a laugh to someone someday or help that 1 in 20 billion person working on the exact same situation in 20 years?

Edited by coope

Share this post


Link to post
Share on other sites
I hadn't had the chance to reply yet, but I don't think its bad form to reply to your own post when you find a solution at all, in fact in many threads there's a lot of competing advice (good) but no follow up as to what the resolution was (could be better).

Glad you figured it out. Sometimes just the process of explaining the problem to outsiders helps us find the problem.

Share this post


Link to post
Share on other sites

This topic is 681 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this