Any shape of collision object

Hello everyone.
This is my first entry. I have been testing Defold for a few days now. I like it very much !

I have this question. Has anything changed recently when it comes to
possibility to create your own shapes of collision objects ?

I would like to create a semicircle like the letter “C” inside of which the “ball” will move. All with the help of dynamic collisions. I saw some old posts about a shape editor that someone prepared. But it seems to me that it is not developed.

Translated with DeepL.com (free version)

Sounds like you’re thinking of the Defold Polygon Editor, which creates a .convexshape file that can be used as a convex hull shape for collisions.

However because those can only be convex, you couldn’t be able to make a “C” shape as it’s concave. What I think you’d want to do is use multiple primitive shapes in one collision object to make a rough arcing shape.

2 Likes

I wrote a small helper that can extract the convex shape from the alpha of an image. Maybe it can help

3 Likes

There you go!
Note this is just my crappy test and it needs integration into your own workflow.
It is using the PNG extension here:

I could not find a decent png decoder (read working) in pure lua to create an editor extension and I’m not happy with a solution that needs an external app.

-- Convex hull
-- https://www.rosettacode.org/wiki/Convex_hull#Lua
-- MIT license (?)


local function ccw(a,b,c)
	return (b.x - a.x) * (c.y - a.y) > (b.y - a.y) * (c.x - a.x)
end

local function pop_back(ta)
	table.remove(ta,#ta)
	return ta
end

local function convexHull(pl)
	if #pl == 0 then
		return {}
	end
	table.sort(pl, function(left,right)
		return left.x < right.x
	end)

	local h = {}

	-- lower hull
	for i,pt in pairs(pl) do
		while #h >= 2 and not ccw(h[#h-1], h[#h], pt) do
			table.remove(h,#h)
		end
		table.insert(h,pt)
	end

	-- upper hull
	local t = #h + 1
	for i=#pl, 1, -1 do
		local pt = pl[i]
		while #h >= t and not ccw(h[#h-1], h[#h], pt) do
			table.remove(h,#h)
		end
		table.insert(h,pt)
	end

	table.remove(h,#h)
	return h
end

local function get_pixel_rgba(pixels, width, x, y)
	local index = y * width * 4 + x * 4 + 1
	local r = pixels[index + 0]
	local g = pixels[index + 1]
	local b = pixels[index + 2]
	local a = pixels[index + 3]
	return r,g,b,a
end

function init(self)
	local rel_path = "<your image here>"
	local abs_path = "<absolute path where to save>"
	local file = io.open(abs_path, "rb")
	local file = file:read("*a")
	local buf, w, h = png.decode_rgba(file, true)
	local pixels = buffer.get_stream(buf, hash("pixels"))

	local points = {}
	for x = 0, w - 1 do
		for y = 0, h - 1 do
			local r, g, b, a = get_pixel_rgba(pixels, w, x, y)	
			if a > 128 then
				table.insert(points, {x=x, y=y})
			end
		end
	end

	local ch = convexHull(points)

	local data = "shape_type: TYPE_HULL\n"
	for i = 1, #ch do
		data = data .. "data: " .. ch[i].x .. " data: " .. ch[i].y .. " data: 0\n"
	end
	
	-- write the resulting convex hull
	local save_path = "<save path>"
	local save_file = io.open(save_path, "w")
	save_file:write(data)
	save_file:close()

end

1 Like