Can I glue two Collision Object's dynamically? (SOLVED)

So, what if I want to glue two game objects’ collision’s objects, so phycical engine see them as one. Is it possible to do dynamically?

1 Like

No, sorry. Describe the underlying problem a bit, there might be other ways to fix it.

Problem is, I want to have a side scroller where spaceship is upgraded by adding parts to it. And/or make enemies be constructed from random combinations of parts. And those parts have volume and mass.

Have you tried giving each part of the ship a component that has the url of the main ship component, so that on collision you can have those parts send a message to that url informing it of damage?

so this might be a

-- Inside ship_part.script

function on_message(self, message_id, message, sender)
	if message_id == hash("collision_response") then
		-- This ship part has been hit! tell the main ship script.
		msg.post(self.ship_url, "damaged", { damage = ... }
	end
end

that sits on all of your ship parts.

Then you would also have a ship.script somewhere:

-- Inside ship.script

function on_message(self, message_id, message, sender)
	if message_id == hash("damaged") then
		-- Mayday!
		self.health = self.health - message.damage
	end
end

(Disclaimer: I’m new to both Defold and Lua, this might not work. :slight_smile:)

1 Like

If you actually need “mass” (I interpret that as going for a dynamic physics simulation with forces and torques), it’s quite tricky to achieve. If you only need the added collision shapes, something like @NSCharles idea should work well.

I was thinking about something like making all parts Kinematic, which relay impulses to disembodied Dynamic core gameobject, which then sets coordinates of all parts.

Or maybe it would be easier to just make everything Kinematic…

I seem to have largely missed the point of your original post. Forgive me I had just come off a 12 hour shift :slight_smile:

Ok so it depends on how accurately you want your ship to behave. If you’re not concerned with individual parts being affected by forces differently (i.e. you want their mass and positions to affect the behaviour of the whole ship, but dont need the parts to move independently). In that case, oddly, I think my previous post is still not far off.

You could send collision information from each part to a main ship script, this collision information would need to include both the impact vector, and part information (mass, position). Then, essentially you’d just do a bunch of basic vector math and manually apply the resultant force to the ship as a whole.

Yes, probably :slight_smile: You could also have a single game object consisting of many sprites and collision objects and at run-time enable/disable the sprites and collision objets based on the current ship/enemy configuration.

Ok, I have made it work. Here is the prototype.

Spaceship is Dynamic GO with spherical out-of-phase (i.e. with bogus Group) CO. Btw, it’s size matters, because it affects on how fast impact will make it rotate. I have started with a tiny sphere and as a result it was spinning like mad at the tiniest provocation.

Ghosts are Kinetic, I use them for bodies that make up complete collision shape of spaceship.


### spaceship.script ###

function init(self)
...
	self.ghost = factory.create("#ghost_factory")
	msg.post(self.ghost, "set_master", {master_id = go.get_id()})
	go.set_position(vmath.vector3(0, 50, 0) + go.get_position(), self.ghost)
	
	self.ghost2 = factory.create("#ghost_factory")
	msg.post(self.ghost2, "set_master", {master_id = go.get_id()})			
	go.set_position(vmath.vector3(0, -50, 0) + go.get_position(), self.ghost2)	
end

function on_message(self, message_id, message, sender)
	if message_id == hash("ghost_impact") then
		if message.applied_impulse > 0 then
			local push = 60 * message.normal * message.applied_impulse
			msg.post("#shipco", "apply_force", {force = push, position = message.position})
		end
	end	
end

### ghost.script ###

function on_message(self, message_id, message, sender)
	if message_id == msg_contact_point_response then
		msg.post(self.master, "ghost_impact", message)
	elseif message_id == msg_set_master then
                msg.post(".", "set_parent", {parent_id = message.master_id})
		self.master = message.master_id
	end		
end

I’m somewhat confused with having to multiply apply_force value by some number, which seems to be game update frequency.

Also, is it possible to change mass and radius of Collision Object dynamically? And maybe move it relative to parent GO? Not that it’s strictly necessary, but it would make code less WTF when I adjust for new center and size of mass.

1 Like

Great you got it working! The impulse and force are actually different units and applied differently by the physics engine. The force will be applied during the course of the time step, which is why you need to divide the impulse by the time step, roughly equivalent to * 60. More discussion about that in the Box2d forum.
Sorry, but it’s not possible to change the mass and radius at runtime. Mass is problematic because how it’s usually derived from shapes and densities. Radius is tricky because we have not yet decided on a good API to access things below the component level (collision object > collision shape in this case). Unless there is a popular request to do this, they would unfortunately get a low priority.

1 Like

Except it’s not really working well. Because Defold is not even allowing to change Dynamic object position, so I can’t adjust centre of mass when elements are added or removed.

EDIT: Also, I guess, it’s not possible to change time frame for Dynamic Objects either (for slow motion effects)?

Could this be solved using this? http://www.defold.com/ref/collection-proxy/#set_time_step:factor-mode

2 Likes

Actually yes, it does! Thanks. I have seen it, but have assumed that it worked like http://www.defold.com/ref/sys/#set_update_frequency:frequency , which does not change time speed, only frame rate.

1 Like