How to distinguish between 2 game objects built by a factory?

Hello Guys,

I was studying about the apply_force method. and i can’t solve this problem situation.

Project Object:
Game Object to a ball object with dynamic object collision
A factory to create balls
some static collision object.

Problem Describe

i’m handling the apply_force by my on_input function, but when clicked over one of balls each ball inside canvas receive the command. But i want to move only that clicked ball.

ball script:

function on_input(self, action_id, action)
    if action_id == hash("click") and action.pressed then
	print('click')
	msg.post(".", "apply_force", {force = vmath.vector3(100000, -10000, -1), position = go.get_world_position()})
	
	end
end

Grafic sample

What i made wrong?

Thank you guys.

First off, you need to detect which object you clicked on. You can do that by iterating through your spawned objects and do a simple radius check since you are using spheres.

When you have that object, you can send the force to it. E.g.

local object_hash = factory.create( ... )
...
msg.post(msg.url(nil, object_hash, "collisionobject"), "apply_force", {force = ... })

Sorry @Mathias_Westerdahl but your hint isn’t clear for me yet.

I have these components in my project :

There are these elements included in my main.collection:

All Balls are included automatically and randomically by the ball_factory.script.
ball_factory script

function update(self, dt)
	self.timer = self.timer - dt
	if self.timer <= 0 and limit < 3 then
		self.timer = 1/frequency
		local p = go.get_position()
		p.y = vmath.lerp(math.random(), min_y, max_y)
		local component = "#ball_factory"
		factory.create(component, p)
		limit = limit + 1
	end
end

I’m handling the apply_force and capturing the click event on “ball.script”

Ball.script:

function on_input(self, action_id, action)
    if action_id == hash("click") and action.pressed then
	print('click')
	msg.post(".", "apply_force", {force = vmath.vector3(100000, -10000, -1), position = go.get_world_position()})
	
	end
end

So… if factory it is putting automatically new balls inside world… and i don’t know what is the correct #GameObjectId from the clicked object…

  1. How can I send the apply force to clicked object(ball)
  2. How can I get access to #GameObjectId from the clicked object (inside their own script)?

Your action_id == hash("click") means only that the user pressed mouse button somewhere, and every ball recieves that event. You have to manualyl check if the player clicked on current ball or not. Just simply do something like this

-- in on_input() call
local obj_pos = go.get_position()
local d = vmath.vector3(action.x, action.y, obj_pos.z) - obj_pos -- vector between ball center and mouse position
if vmath.length(d) < ball_radius then
  -- Click successful, apply force
end
-- Pseudocode, might be mistakes (!)
3 Likes

The code looks good. One thing that might become a problem is that every ball seems to be acquiring input focus. There is a limit to the number of game objects that can have input at the same time (16 IIRC). I would recommend that you let the script that is spawning the balls acquire input focus, and when it detects a click it goes through the list of spawned balls to detect which one the user clicked on and applies a force to that specific ball.

4 Likes

Updated question about 16 game object max. So I have a simple demo that spawns up to X objects. Each object can be dragged and dropped on the screen. Right now I’m processing all of the dragging and dropping code at the game.object level not the spawning script level. It works fine. It’s only one game object, and only 1 script but a factory can spawn multiple instances of them.

Except if I go X>16 which I did and it just doesn’t let you touch the others given what you say here.

I tried to refactor it to something like you describe and it technically worked but was too slow because unlike detecting a specific click only it requires grabbing and moving the object continuously until later released which means if you had so many objects it’s touch to cycle through them all.

I have a few more ideas on how to fix this issue and pull the code back such that it only moves one object… but essentially the heart of the problem is continuously pumping the equivalent of action.x , action.y to a grabbed object through messaging vs. using on_input direct to the object.

While I work on a couple ideas I have on how to handle this… was curious how others would handle having a screen with dozens of sprites you could grab and drop from one area of the screen to another.

I would solve this using collision objects instead. Have a small collision object follow the mouse and check for collisions against the objects you wish to be draggable. Input and dragging is handled by a script attached to the cursor game object. I have this setup in an example, but I ramped it up a bit and spawned 200 Defold logos that you can drag around:

DEMO: http://britzl.github.io/publicexamples/click_and_drag/index.html
CODE: https://github.com/britzl/publicexamples/tree/examples/click_and_drag

2 Likes

ok will look at it. I was going to currently take my sprites and give them an “am_I_selected” property and then if they are they chase the cursor around and if not they execute code required upon being de_selected.

Thanks - this was helpful. I did roll-my-own here and can happily report I’ve got it working and so far was able to do it with 50 sprites with no problem. Now working on optimizing. FWIW I didn’t use a collision object instead just using X1,Y1 - X2,Y2 bounding checking using a “sprite table” that holds all of them. I’m going to use your code I think and try to implement the entire system using collision objects as well.

2 Likes