How to achieve collision between two seperate collisionproxy loaded worlds

Hi everyone

Inside my character i do have a collectionproxy with a collectionfactory to create different weapon factories. The reason why i have it in a collectionproxy is mainly to use the set_timout() function on all projectiles. Is there a better approach to pause all of them at the same time? If not i got the following questions:

Due to the collectionproxy generated weaponsfactory they will be in a different physical world and the projectiles collision does not work anymore with the enemies that are spawned with the level collextionproxy.

I did try and research and i was wondering how this could be achieved? is it with physics.set_listener? And if so how?

How to achieve collision between two seperate collisionproxy loaded worlds

This is not possible, as they get a separate physics world contexts.

You mean “set_time_step”?

How are you moving the projectiles? If they are kinematic objects and you move them in an update() loop then perhaps set a flag that to pause them?

I do have them as trigger collision but i could as Kinematic aswell. So i would have to flag all the bullets that are created from the factories? how would i achieve that?

Ok thanks for helping me understand that.

I thought about creating a table in a lua module add all the bullets there when created so i have their instance and then set their dt = 0 on pause and then back to normal? or what would be the best approach to this?

No, are you moving them in update() or using go.animate() or using forces (no, since you said they are triggers)?

Yes, tracking the bullets in a table like that is a good idea. I assume that is the way you are moving them anyway? Or do you have a script on each bullet? If so, then it would be more efficient (especially with many bullets) if you have one script and a list of bullets and move them one by one that way instead.

1 Like

Thank you for your answer.

the bullet object has a script on it with its own update function and this takes care of the movement.

I do not really undersand how i can achieve this with one script and a list of bullets. Lets say the factory creates the prototype bullet and right now this will move due to the update function of the script on the prototype. How could i achieve that the bullets would move with one script and a list?

Could you make an example? Is it like me register the bullet on creation and one script will go over the table of bullets in the update and moves them accordingly to the type of bullet it is? since there different type of bullets aswell (Thats why i have the collection factory.

But isn’t the update script responsible for the one object only it is attached too? or how can i update all bullets in just one script?

I was thinking about and I wondered if it would make sense to have one bullet controller for each type of bullet? Lets say there 10 different bullets it seems one script would be a bit to convoluted? then it would be 10 update functions instead of one per bullet?

Will the bullet script also handle the collision detection? or should that be done on the enemies? they are also factory created and have their own update function I assume i should make one script for each enemy type aswell? and follow a similair approach

Sure, here’s some untested code. It will manage a list of bullets, move them in update and delete them after some time has elapsed. You can spawn new bullets using a factory on an input event. There’s also a message handler for a “remove_bullet” message which you can send from other places (enemy collision code perhaps) to remove bullets.

-- spawn a bullet using a factory
-- store the game object id and some information about
-- the bullet in a table
local function spawn_bullet(self, position, direction)
	local id = factory.create("#bulletfactory", position)
	local bullet = {
		id = id,
		direction = direction,
		speed = 300,	-- pixels per second
		lifetime = 3,	-- seconds before it gets removed
	}
	table.insert(self.bullets, bullet)
end

function init(self)
	-- list of all bullets
	self.bullets = {}
	-- direction to fire bullets
	self.direction = vmath.vector(0, 1, 0)
end

function update(self, dt)
	-- iterate over the list of bullets back to front
	-- we do it this way so that we can safely remove
	-- bullets and keep iterating through the list
	-- for each bullet we move it according to speed
	-- and direction
	-- decrease lifetime and remove when done
	for i=#self.bullets,1,-1 do
		-- get a bullet from the list, move it!
		local bullet = self.bullets[i]
		local pos = go.get_position(bullet.id)
		pos = pos + bullet.direction * bullet.speed * dt
		go.set_position(pos, bullet.id)

		-- decrease bullet lifetime and remove when done
		bullet.lifetime = bullet.lifetime - dt
		if bullet.lifetime <= 0 then
			table.remove(self.bullets, i)
			go.delete(bullet.id)
		end
	end
end

function on_input(self, action_id, action)
	if action_id == hash("fire") and action.released then
		spawn_bullet(self, go.get_position(), self.direction)
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash("remove_bullet") then
		for i=1,#self.bullets do
			local bullet = self.bullets[i]
			if bullet.id == message.id then
				table.remove(self.bullets, i)
				go.delete(bullet.id)
				break
			end
		end
	end
end
1 Like

thank you so much i did something similair like this:


local speed = 3
local attack = 5
local bullets = {}
local pos = vmath.vector3()

local player = require "main.player_data"
local game_state = require "main.game_state"

function init(self)
	print("init knife controller")

	game_state.add_weapon_url(msg.url())
	self.weapon_timer = timer.delay(1, true, function ()
		add_bullet(pos)
	end)
end

function update(self, dt)

	-- update position of factory to be on player
	pos = go.get_position(game_state.player)
	go.set_position(pos)
	
	if next(bullets) ~= nil then
		move_bullets(self,dt)
	end
end
-- Function to add the bullet to the table
function add_bullet(self,position)

	local bullets_table = {}
	local rotation = math.atan2(player.angle_vector.x, player.angle_vector.y)
	local bullet = factory.create("#factory", position)


	local player_pos = go.get_position(game_state.player)
	print(player_pos)
	
	bullets_table.bullet = bullet
	bullets_table.speed = speed
	bullets_table.attack = attack
	bullets_table.rotation = rotation
	bullets_table.direction = player.angle_vector -- problem with getting the direction vectors from direction 
	

	go.set(bullet, "euler.z", math.deg(rotation) * -1)
	
	table.insert(bullets, bullets_table)
end

function move_bullets(self,dt)
	
	for key, bullet in pairs(bullets) do 

		local pos = go.get_position(bullet.bullet)
		print("bullet direction:",bullet.direction)
		pos = pos + bullet.direction * bullet.speed 
		go.set_position(pos, bullet.bullet)	
		
	end

end

I think i understood the concept of it thank you very much!

I have now another question i can rotate the sprite in the direction i am facing on the creation, but i have a problem to move the bullet in the same direction as the rotation. what am i missing?

Edit: How can i get the direction Vector3(x,y,z) in all 8 directions from the player.script?

Have a look here: Move forward

Thank you it did help me a bit and i figured it out. I definitly have to revisit some vector math.

I do have now one script working for the bullets thank you. So i assume i should do the same for Spawning enemies?

Would i have to handle the collision in these controller scripts aswell?

It depends :slight_smile:

You can have a global handler of all collisions using physics.set_listener() or you can handle collisions in individual scripts. For performance reasons the general rule is to centralise as much as possible, but it completely depends on your target platform and the amount of objects. Example:

If you have 1000 bullets and 10 enemies then it would be inefficient to have 1000 instances of bullet.script to handle movement code for the bullets. It makes more sense to have a centralised handler for bullet movement OR let the engine move the bullets using go.animate() (for bullets that fly in a straight line).

For the same scenario it would make sense to have 10 instances of enemy.script to handle enemy movement behavior AND to detect collisions with bullets. When an enemy detects a collision with a bullet it does whatever damage calculation needed and it also removes the bullet, either using go.delete() or by sending a message to the central handler for bullets.

If you on the other hand only have 10 bullets and 1000 enemies then the opposite situation would apply.

And for moderately low numbers (less than 100) of both it probably doesn’t matter much which approach you take. You can most likely have scripts on everything.

Ok thanks for that it makes sense! I had now a script on the bullets just for the collision. I look into physics.set_listener() this seems to override all the collision messages. So i would have to manage all collisions in the same physics world. Thanks a lot for the fast answers and help!

Yes, that is the drawbacks but depending on your game it might work well.

1 Like