Strategy game world map like Risk?

Im making a strategy game like Risk game but with many many small regions.
I predict 100-1000 regions per country.

Option 1:
Each region is unique shape so instanced static mesh for each different region is not possible.
So im thinking about having the regions displayed by a huge map image.
And then use very small hidden tiles to define each region, if they are small enough they can define any region whatever the odd shape is, and the shape can even change.
This should work for moving pieces to the right regions.

Sketch/Example:

Other than this I could use a texture for each region, and then use physical material and mask of the material to detect collision on each region. This would then be possible to use in a instanced static mesh i assume, with a texture 2d array.
So we would have a instance for each region and a texture for each one, and we would detect collision by the mask in the texture… Kinda messy…

What do you think?
Any recommendations?

t

Based on that, i would go 100% as ui, every region is just a button, thing like OnMouseOver(hover) would be more practical than a static mesh with constant line trace if there a collision to highlight a region for example.

This will require more thinking ofc, just make sure to compare what you can do or not UI vs StaticMesh method.

1 Like

Thanks. though i dont understand how you would make a button out of the land.
Since the land has an irregular shape and buttons are square shape?

ahh true, i will dig around to see if that possible as am curious too :innocent:

1 Like

Check out this link: Buttons can only be rectangular? - #3 by Supremative

1 Like

Enable mouse clicks and mouse overs

Then you can use events to drive static mesh mouse overs, clicks etc.

obraz

If the tiles are uniform then you could just calculate them via a grid snap, or hexes. No need to split the mesh then.

If you want changes in the color of the tile then you could just add a static mesh above it with an additive material to simulate it lighting up.

If you go the route of “pixels” then you could save out each landmass as an array of coordinates and use that to drive the interaction (can be based if mouse x,y is in the array of land mass).

1 Like

I’d prefer to stay away from using UI for something that could take more than 5.000 regions if its a map of the whole world.

I tested once UI vs Instanced Static Meshes and ISM won in terms of performance.
This was some time ago.

What is stopping you from using the pixel fill of a render target?

It’s probably the most performant of the lot and has flexibility.

Just probe the RT for the color under the cursor to either trigger interaction / detect collision. The only limit is the amount of unique areas (though full range would be around 16581375 so I doubt you would run out)

Have the render target only keep information about the regions not the map itself. Keep it simple and it should work fine.

1 Like

Thats a nice one. Though im really thinking about going with Instanced Static Meshes. The only difference i think is if i use tiny tiles that together make up regions. Or if i use a texture with a mask and then check collision by physical material.
Using UI would be ok if there werent so many regions and subregions.

Also doing it with UI would kind of force the game to be 2D in the strategy map?

This would the amount of regions i would have for France for example:

Thats a nice suggestion. Though this would force the regions to have a color, right?
will study it a bit before, and come back here in a bit.

The color of each region would be more of a math resolver. Think of it as each color combination (1->255 + 1->255+ 1->255) being a unique id for each regon. You use the color information as an information source, you can have a second RT for specific colors (like have all of France red, Britain blue etc)

You can then have a TMap with the key as the color combination and value as the region name.

1 Like

I only worked once with render targets. So then when you click then how do you get the color you are in? By the coordinates?
I think this is the best solution so far.
Its quite similar to the video i posted above.
Where im checking the colors in the texture by each pixel and then creating ISM tiles that together form the shape of the country (each pixel being 1 tile).
Could the render target be better here on some aspect?

Here is an implementation to get the specific pixel color at the texture x,y coordinates.

FColor UColorToolsBPLibrary::ProcessTexture(UTexture2D* InTexture, int32 PixelX, int32 PixelY)
{	
	FTexture2DMipMap* MyMipMap = &InTexture->PlatformData->Mips[0];
	FByteBulkData* RawImageData = &MyMipMap->BulkData;
	FColor* FormatedImageData = static_cast<FColor*>(InTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_ONLY));
	
	uint32 TextureWidth = MyMipMap->SizeX, TextureHeight = MyMipMap->SizeY;
	FColor PixelColor;

	if (PixelX >= 0 && (uint32)PixelX < TextureWidth && PixelY >= 0 && (uint32)PixelY < TextureHeight)
	{
		PixelColor = FormatedImageData[PixelY * TextureWidth + PixelX];
	}		
	RawImageData->Unlock();

	return PixelColor;
}

For an RT in theory this conversion should work. Haven’t tested it out in a project though, just mixing some code for RT to utexture conversion.

FColor UColorToolsBPLibrary::ProcessTextureRT(UObject* WorldContextObject, UTextureRenderTarget2D* RTarget, int32 PixelX, int32 PixelY)
{
	UTexture2D* InTexture = RTarget->ConstructTexture2D(WorldContextObject, "texture", EObjectFlags::RF_NoFlags, CTF_DeferCompression);
	FTexture2DMipMap* MyMipMap = &InTexture->PlatformData->Mips[0];
	FByteBulkData* RawImageData = &MyMipMap->BulkData;
	FColor* FormatedImageData = static_cast<FColor*>(InTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_ONLY));

	uint32 TextureWidth = MyMipMap->SizeX, TextureHeight = MyMipMap->SizeY;
	FColor PixelColor;

	if (PixelX >= 0 && (uint32)PixelX < TextureWidth && PixelY >= 0 && (uint32)PixelY < TextureHeight)
	{
		PixelColor = FormatedImageData[PixelY * TextureWidth + PixelX];
	}

	RawImageData->Unlock();
	return PixelColor;
}

It would probably be wise to cache the render target’s utexture conversion and use it as a lookup instead of constantly writing it per each check. (maybe adding a bool function if you want to update it or something)

Here is an old post where I was getting the values from an SRGB version of a texture for the OP.
If you want to use this on a map then you would need to do a line trace to the map and turn on get uv coordinates for hit detection and then use that information to get the clicked areas uv coordinates and feed it into the function to get the needed value.

1 Like

Thanks a lot :pray::pray:. I can resume work now :pick::pick:

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.