I am looking to move a large project from Flex/ActionScript. Mouse detection was relatively straightforward on all of the objects. From the docs here, " gui_node will return true or false depending on if the specified coordinate is within the bounds of a gui node or not" but what is really needed is detection based on non-transparent textures (tilesource in my case) for the node(s). In fact if the node has children, it would be best if I make the call with the top level node and let the internal logic walk the relationships. Iâve searched everywhere for a nice, clean solution. Even the wonderful defold-input package doesnât seem to cover âodd shapesâ. Note: polygons wonât be enough for what I need. Consider an object such as a chair. Thanks for suggestions.
Ok, so you have images of irregular shaped objects and you need to detect input? How large are the individual images?
Furniture objects are 50x150 pixels in a tile of 16 parts (8 directions as well as a forward and backward component - eg a chair has a portion behind a player when sitting as well as in front). One use case is clicking on a player vs the chair they are sitting in. ( I use the term chair loosely, as it could be a roller coaster cart, bumper car, canoe, âŚ)
I even tried using clipping but the pick_node still used the bounding box.
Yes, the gui nodes and picking is always rectangular.
If you put them in a tilesource and use the same image as collision source youâll get something that is at least not rectangular in shape, but youâd have to use tilemaps to make use of the traced collision shapes.
@britzl Could he theoretically load the images separately and get the rgba value of a pixel from the buffer?
Of course the simple solution is to use game objects and build accurate collision out of however many shapes you need. This could be a lot of work depending on how picky you are and how many objects you have.
Iâve heard of plenty of programs that generate collision polygons from a textureâs alpha, but none that can deal with internal holes.
Yes, that could possibly work. Or render the scene to a render target with a special shader that assigns a color per clickable item and then do picking by checking the pixels in the render target somehow.
The project has thousands of images so pre-building collisions is rather out of the question. Support for holes may not be critical. Can you give me references to these programs? Are any usable at runtime as an asset is changed?
Would anyone have a simple example of leveraging tilemaps? I tried to follow the documentation on masking, hoping it would âspill overâ to the pick_node logic but no luck. (future enhancement?) All of the images are already in a format suitable to make tilesources.
All of this assumes I can load assets, ie images, from http calls to act as textures for the tilesources and tilemaps. Until I can get clicking to work, no sense trying the rest of the aspects to convert, and there is a lot!
Iâve got high hopes for Defold.
PhysicsEditor is the first thing that came to mind, and Iâm pretty sure Unity has this built into their sprite importer or something. Defoldâs physics only allows convex polygons with 16 vertices max though.
But if you want to do this dynamically at runtime, that changes things . . . You canât dynamically generate collision shapes with Defoldâs built-in physics. Load images from the web, sure, thereâs an code snippet of doing that for GUI here. Getting that into a tilemapâŚIâm not so sure. IMO all the things you want to do are Defoldâs weak points. You should expect to do a lot of work and experimentation yourself if you want to get this project to work.
Oh, so youâre downloading images on the fly?! That puts things in a different perspective. Your best bet is to load the image (using image.load), create a texture, assign it to a gui node but also keep the pixel data from image.load() and read from that when the user clicks. Start with gui.pick_node() and if that detects a click then go and sample pixel data to know for sure.
Since the image really needs to apply to a tilesource, I canât directly assign it to the gui nodeâs texture. I couldnât find how to alter the texture for a tilesource. I donât seen an id or url for tilesources.
Also, is there any further info on the structure of the image buffer? I am guessing it is height * width * 4 (RGBA).
Why? Can you share an example image that you wish to use?
It returns the type: image.load()
Tilesource for directions the item faces as well as animations (player clothing).
Using the image buffer, the location of the click, the placement of the object and the current animation (in my case the direction the item is facing), it only took 2 lines of code to return whether the pixel under the mouse event is transparent or not. Now pick_node can return a real true or false. Now if the buffer could be obtained directly from the objects, this would make for a great enhancement to pick_node, perhaps add an optional boolean argument - consider transparency. This would handle ANY shaped object. No polygons to approximate the shape.
Well, itâs a complete new feature, and while it is surely useful, it is not as simple as this flag might imply
Or render the scene to a render target with a special shader that assigns a color per clickable item and then do picking by checking the pixels in the render target somehow.
And if we were to implement it, it would probably be something along the lines what @britzl suggested.
I donât think it will be in our most immediate road map at least.
So how would I get access to a tilesource in order to load a new image into it? (or should I start a new thread for this topic?) The sprite already points to the proper image (tilesource in this case) and has selected the proper animation. The tilesource already has the proper dimensions and defined set of animations.
By using the image buffer, placement and click information, I can now detect whether the clicked spot is transparent or not. Making progress.
If you wish to change the entire texture used by a sprite you need to load the new one into a buffer object and set that. @sergey.lerg has an ImageLoader extension that loads an image from disk or string/bytes:
Use it like this:
local image_resource = imageloader.load{ data = data }
local image_resource = imageloader.load{ filename = "D:\0001.jpg" }
resource.set_texture(go.get('#spite', 'texture0'), image_resource.header, image_resource.buffer)
Youâre always downloading the images from a server or? You could maybe also look into our LiveUpdate feature and load new assets (game objects, sprites etc) on the fly and use them as needed.
Thanks so much for the info on the extension. I was hoping the following would handle my use case.
http.request(imgurl, âGETâ, function(self, id, response)
img = image.load(response.response)
print(string.format(âimg size %d by %dâ, img.height, img.width))
local image_resource = imageloader.load{data = img.buffer}
pprint(image_resource)
resource.set_texture(go.get('#car2Back', 'texture0'),
image_resource.header,
image_resource.buffer)
However I am getting a fatal error and notice the resource dimensions are both 0. That canât be good!
DEBUG:SCRIPT: img size 1200 by 72
DEBUG:SCRIPT:
{ --[[000000000309D550]]
header = { --[[000000000309D5A0]]
num_mip_maps = 1,
width = 0,
channels = 0,
height = 0,
type = 3553
}
}
ERROR:SCRIPT: /car2/car2.script:110: Wrong type for table attribute âformatâ. Expected number, got nil
stack traceback:
[C]: in function âset_textureâ
Also a minor nuisance, with the extension added as a dependency, I can no longer simply rebuild the project with an open running window and have it work properly. I must close the window with the active executable before rebuilding.
You shouldnât do image.load() and the imageloader.load()
It should be enough to do imageloader.load({ data = response.response })
Thanks, the header looks better. I was using image.load since I need to keep the buffer for my transparency logic.
However, the extension does produce the same results. The first picture is the sprite using a tilesource loaded into the project. The same image file is loaded via http and processed by the extension.
before
after
code
â change texture
http.request(imgurl, âGETâ, function(self, id, response)
local image_resource = imageloader.load{data = response.response}
pprint(image_resource)
resource.set_texture(go.get('#car2Back', 'texture0'),
image_resource.header,
image_resource.buffer)