[solved] Issues setting tilesource image during runtime

I am trying to set the tilesource (as in, replace the whole texture) to an image determined at runtime (the image dimensions are the same as the compiled tilesource).

i tried following along Changing texture for a tilesource at runtime to determine the location of the texture, but there’s not too much that was shown in that thread

here is the code i am running:



function settilemaptexture(texturedata)
	resource.set_texture("/main/tiles.t.texturesetc", texturedata.header, texturedata.buffer)
end

<different file>

	newtiledata=loaddata("testtextures/tiles.png") --this just reads data from a file relative to the script folder.
	if newtiledata then
		imgres=imageloader.load{data=newtiledata}
		if imgres then
			settilemaptexture(imgres)
		end
	end

currently, what i am doing crashes the engine

ERROR:CRASH: CALL STACK:

ERROR:CRASH:  0 0x7FF78206D3A0 dmCrash::GenerateCallstack D:\a\defold\defold\engine\crash\src\backtrace_win32.cpp:144
ERROR:CRASH:  1 0x7FF78242B838 raise /tmp/job8834229921072479505/minkernel/crts/ucrt/src/appcrt/misc/signal.cpp:547
ERROR:CRASH:  2 0x7FF78241BDC0 abort /tmp/job8834229921072479505/minkernel/crts/ucrt/src/appcrt/startup/abort.cpp:71
ERROR:CRASH:  3 0x7FF78241B0A4 common_assert_to_stderr<wchar_t> /tmp/job8834229921072479505/minkernel/crts/ucrt/src/appcrt/startup/assert.cpp:186
ERROR:CRASH:  4 0x7FF78241ABBC _wassert /tmp/job8834229921072479505/minkernel/crts/ucrt/src/appcrt/startup/assert.cpp:443
ERROR:CRASH:  5 0x7FF7820BFDF0 dmDDF::LoadMessage D:\a\defold\defold\engine\ddf\src\ddf\ddf.cpp:164
ERROR:CRASH:  6 0x7FF7820BFDD0 dmDDF::LoadMessage D:\a\defold\defold\engine\ddf\src\ddf\ddf.cpp:158
ERROR:CRASH:  7 0x7FF7821D1DD0 dmGameSystem::ResTextureSetRecreate D:\a\defold\defold\engine\gamesys\src\gamesys\resources\res_textureset.cpp:184
ERROR:CRASH:  8 0x7FF7820AD660 dmResource::SetResource D:\a\defold\defold\engine\resource\src\resource.cpp:1097
ERROR:CRASH:  9 0x7FF7821FC450 dmGameSystem::SetTexture D:\a\defold\defold\engine\gamesys\src\gamesys\scripts\script_resource.cpp:1493
ERROR:CRASH: 10 0x7FF781FE790E lj_BC_FUNCC <unknown>:0
ERROR:CRASH: 11 0x7FF7820648D0 lua_pcall <unknown>:0
ERROR:CRASH: 12 0x7FF7820968A0 dmScript::PCallInternal D:\a\defold\defold\engine\script\src\script.cpp:1401
ERROR:CRASH: 13 0x7FF7820FC690 dmGameObject::RunScript D:\a\defold\defold\engine\gameobject\src\gameobject\comp_script.cpp:142
ERROR:CRASH: 14 0x7FF7820FAF30 dmGameObject::CompScriptInit D:\a\defold\defold\engine\gameobject\src\gameobject\comp_script.cpp:183
ERROR:CRASH: 15 0x7FF7820CDA30 dmGameObject::InitComponents D:\a\defold\defold\engine\gameobject\src\gameobject\gameobject.cpp:1700
ERROR:CRASH: 16 0x7FF7820CA290 dmGameObject::InitCollection D:\a\defold\defold\engine\gameobject\src\gameobject\gameobject.cpp:1769
ERROR:CRASH: 17 0x7FF782150080 dmEngine::Init D:\a\defold\defold\engine\engine\src\engine.cpp:1340
ERROR:CRASH: 18 0x7FF78214EFC0 dmEngineCreate D:\a\defold\defold\engine\engine\src\engine.cpp:2152
ERROR:CRASH: 19 0x7FF782154CD0 dmEngine::RunLoop D:\a\defold\defold\engine\engine\src\engine_loop.cpp:68
ERROR:CRASH: 20 0x7FF78205ACB0 engine_main D:\a\defold\defold\engine\engine\src\engine_main.cpp:152
ERROR:CRASH: 21 0x7FF7823D44C4 __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
ERROR:CRASH: 22 0x7FF80D047330 BaseThreadInitThunk <unknown>:0
ERROR:CRASH: 23 0x7FF80DBE2690 RtlUserThreadStart <unknown>:0

i’m not really sure what to do here

I would start by using resource properties, as that is the simplest way to replace the texture. Here’s how to do it for a tilemap:

go.property("tilesource1", resource.tilesource("/assets/tilesource1.tilesource"))

function init(self)
    go.set("#mytilemap", "tile_source", self.tilesource1)
end

If you really need to load the image from disk then you need to make sure that you are loading the image from the correct location and then create a texture buffer from it and then use the correct APIs to replace. Here’s an example (shows how to replace a sub-image, but can be used to replace the entire image too):

2 Likes

i’ve gotten it to swap textures succesfully by using an atlas, however, the texture itself shows up invisible with tiles (i’m using a collectionfactory to make tiles so that i can chunk the map for better performance). the image shows up just fine loading it into a sprite, which uses very similar code.

still, i’d say it’s a step in the right direction considering the game doesn’t crash

updated code here:


---[[[<this script defines map-related functions>]]]

local _TEX
local _ATL

function settilemaptexture(texturedata)
	
	if not _TEX then
		_TEX=resource.create_texture("/main/_TILES_.texturec", texturedata.header, texturedata.buffer)
	else
		resource.set_texture(_TEX, texturedata.header, texturedata.buffer)
	end

		
	local wid,hei = texturedata.header.width,texturedata.header.height

	local atlasparams = {
		texture = _TEX,
		animations = {
			{
				id     = "tile",
				flip_horizontal = false,
				height = hei,
				fps = 1,
				flip_vertical = false,
				width = wid,
				playback = 0,
				frame_start = 1,
				frame_end = 2
			}
		},
		geometries = {
			{
				vertices  = {
					0,   0,
					0,   hei,
					wid, hei,
					wid, 0
				},
				uvs = {
					0,   0,
					0, hei,
					wid, hei,
					wid, 0
				},
				indices = {0,1,2,0,2,3}
			}
		}
	}

	if not _ATL then
		_ATL=resource.create_atlas("/main/_TILES_.texturesetc", atlasparams)
	else
		resource.set_atlas(_ATL, atlasparams)
	end

	_MAP_TEXTURE=_ATL


...

--[[<this part of a different script sets the texture for chunks>]]
		for i=1,#loadedchunks+1 do
			if loadedchunks[i] then
				local chunkchunk=loadedchunks[i][3]
				local tmp=msg.url(nil,chunkchunk,"chunk")
				if tmp then
				
					go.set(tmp, "tile_source", _MAP_TEXTURE)

				end
			end
		end

edit update: i have tried using the same parameter table that the tilesource atlas uses (using go.get and resource.get_atlas) and the issue still occurs

I’m not sure if this is relevant (didn’t read through all the code), but one thing to keep in mind is that the top-left of a tilesource image is id: 1, but that position on the image resource itself is at y = image_height, so the y axis is flipped. Sometimes I see people trying to do some dynamic writing and reading from a tilesource or atlas and ending up with nothingness because they’re actually doing these operations on the bottom-left of the image, instead of the top-left.

…but that position on the image resource itself is at y = image_height, so the y axis is flipped…

well, i’ve switched the posted atlas paramater table to use the same one that the existing tilesource uses, so i don’t imagine that’s what the issue is.
really what i’m doing at this point now is swapping the texture of the atlas and keeping everything else the same.

ok so it turns out i wasn’t following the example close enough
though i find it weird that i can’t override the tilemap atlas but i can replace its texture just fine.