Jump to content

Recommended Posts

Is there something to read about?

 

What size of game screen (how it handles "coordinates" for UI elements, i believe its not just pixels, its some kind of bigger units). What size of screen in this units, how it handle different screen sizes?

 

how objects on ground is represent in game logic? do they have absolute coordinates (pixels) or whole map is just some kind of matrix of elements which have static size in units (where 1 unit = X pixels)?

 

i remember i read some topic which explain how different turfs mixed on land and way to detect them. But cant find it.

 

Want to make mod with some kind of plague, which slowly convert all biomes to marsh (for example).

If anyone can point to something similar (topic/mod) - will be great.

This was actually the very first thing I looked into when modding for Don't Starve.

There are two types of coordinates, tile coordinates and world coordinates. World coordinates are what entity Transform's use, and point (0,0,0) is the very center of the map (note: the y component is the vertical axis [pretty much unused in Don't Starve]). However, for tile coordinates (which only the ground uses), tile (0,0) is the very top left of the map.

To get tile coordinates from world coordinates you can use:

GetWorld().Map:GetTileCoordsAtPoint(x,y,z)
To get world coordinates from tile coordinates you can use:

-- Convert tile coordinates to world coordinatesfunction GetTileCenterPointAtCoords( x, y, world )	world = world or GetWorld()	-- pt 0,0,0 is the center point of the tile in the center of the map	local midx, midy = world.Map:GetTileCoordsAtPoint(0,0,0)	-- tile coord's y component corresponds to vector's z component	return Vector3( (x-midx) * TILE_SCALE, 0, (y-midy) * TILE_SCALE )end
To change the type of a tile, you can use the following:

-- gross copy of a table from terraformerGROUND_TURFS ={	[GROUND.ROCKY]		= "turf_rocky",	[GROUND.ROAD]		= "turf_road",	[GROUND.DIRT]		= "turf_dirt",	[GROUND.SAVANNA]	= "turf_savanna",	[GROUND.GRASS]		= "turf_grass",	[GROUND.FOREST]		= "turf_forest",	[GROUND.MARSH]		= "turf_marsh",	[GROUND.WOODFLOOR]	= "turf_woodfloor",	[GROUND.CARPET]		= "turf_carpetfloor",	[GROUND.CHECKER]	= "turf_checkerfloor",	[GROUND.CAVE]		= "turf_cave",	[GROUND.FUNGUS]		= "turf_fungus",	[GROUND.SINKHOLE]	= "turf_sinkhole",	[GROUND.UNDERROCK]	= "turf_underrock",	[GROUND.MUD]		= "turf_mud",	webbing				= "turf_webbing",}GLOBAL.GROUND_TURFS = GROUND_TURFS-- another gross copy from terraformerfunction SpawnTurf( turf, pt )	if turf then		local loot = SpawnPrefab(turf)		loot.Transform:SetPosition(pt.x, pt.y, pt.z)		if loot.Physics then			local angle = math.random()*2*GLOBAL.PI			loot.Physics:SetVel(2*math.cos(angle), 10, 2*math.sin(angle))		end	endendGLOBAL.SpawnTurf = SpawnTurf-- yet another gross copy from terraformerfunction ConvertTile(x, y, original_tile_type, new_tile_type, spawn_turf)	assert( x and y and original_tile_type and new_tile_type, "All ConvertTile parameters need to be non-nil" )	local ground = GetWorld()	ground:PushEvent("tileconverted", {x=x, y=y, old_tile_type=original_tile_type, new_tile_type=new_tile_type})	ground.Map:SetTile( x, y, new_tile_type )	ground.Map:RebuildLayer( original_tile_type, x, y )	ground.Map:RebuildLayer( new_tile_type, x, y )		local minimap = TheSim:FindFirstEntityWithTag("minimap")	if minimap then		minimap.MiniMap:RebuildLayer( original_tile_type, x, y )		minimap.MiniMap:RebuildLayer( new_tile_type, x, y )	end		if spawn_turf then		local pt = GetTileCenterPointAtCoords(x,y)		SpawnTurf( GROUND_TURFS[original_tile_type], pt )	endendGLOBAL.ConvertTile = ConvertTile

Note that tile conversion is pretty expensive (due to the Map and MiniMap RebuildLayer calls). Don't expect to be able to convert many tiles at once (really, it becomes expensive very quickly; I've found that limiting it to 1 conversion per frame is ok but still can cause some noticable slowdowns).

Edited by squeek

Oh thx for answer, about RebuildLayer i guess its possible to call it once per few changes to reduce number of slowdowns.

Or how game make new map then, cant believe that such method will be called for each chunk of turf :)

 

So actually there no limitation on placing objects? They just should not cross each other?

Just thought that there is a certain minimum unit that can take an object and which objects are aligned.

 

And if not difficult, what are the coordinates of the user interface? I'm talking about those that are used for buttons and other UI elements, whether they have the same "virtual screen" size for any resolution?

Oh thx for answer, about RebuildLayer i guess its possible to call it once per few changes to reduce number of slowdowns.

Or how game make new map then, cant believe that such method will be called for each chunk of turf :-)

I'm not sure about this. RebuildLayer takes both a tile type and tile coordinates, so I'm not sure if you could just tell it to 'rebuild all.' Would need a developer to clarify how this stuff works, as Map and MiniMap are both userdata.

 

So actually there no limitation on placing objects? They just should not cross each other?

Just thought that there is a certain minimum unit that can take an object and which objects are aligned.

Note sure what you mean by this. If you mean that two entities could share the same world coordinates, then, yeah, it's possible but I think an entity's Physics might handle collisions and push them apart. There's no grid system for world coordinates, only for tiles (each tile is 4 units apart in world coordinates [see variable TILE_SCALE]).

 

And if not difficult, what are the coordinates of the user interface? I'm talking about those that are used for buttons and other UI elements, whether they have the same "virtual screen" size for any resolution?

This I'm unsure about (I knew more when I was working on Better Console/Holidays but forgot it). I do know that it's a completely separate coordinate system (0,0 to TheSim:GetScreenSize()) and I'm not sure there's any methods in the Lua code that convert from screen space coordinates to world coordinates (the function that gets the entity under the mouse is userdata [TheInput:GetWorldEntityUnderMouse()] so who knows how that works).

UI element scaling by resolution and all that stuff is handled by a mixture of Lua and userdata; you can see examples of it in pretty much any widget/screen file.

 

oh damn i just got it, all what i need actually - is emulation of pitchfork and placing turf.

its not so hard how i expected :-)

Yep. :-) Edited by squeek

I do know that it's a completely separate coordinate system (0,0 to TheSim:GetScreenSize()) and I'm not sure there's any methods in the Lua code that convert from screen space coordinates to world coordinates (the function that gets the entity under the mouse is userdata [TheInput:GetWorldEntityUnderMouse()] so who knows how that works).

This answer comes a bit late, but since I just happened to check this out I though I'd post it here.

Screen coordinates are pixel coordinates, with (0, 0) at the lower left corner of the screen (unlike the usual convention that it is the top left corner), though of course widgets are usually positioned relative to some other widget, and by specifying an anchor their position may be expressed relative to some other "virtual" origin which may change on screen resizing (as I'm sure you know, I'm just documenting :razz:).

Screen coordinates can be converted to world coordinates and vice versa (using letters u and v to denote screen coordinates and letters x, y and z to denote world coordinates) by

x, y, z = TheSim:ProjectScreenPos(u, v)u2, v2 = TheSim:GetScreenPos(x, y, z)assert( math.abs(u - u2) < 0.2 )assert( math.abs(v - v2) < 0.2 )
(I'm not entirely sure about this error bound, this just seems to hold based on my tests)

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
×
  • Create New...