Collision and Touch on 16+ instancied on moving screen

Hello,
I’m trying, as an old pet project, to do a 4x game in space (think Master of Orion).

On the screen, there is Stars : Instancied objects each with CollisionObject, Script and Sprite.
Can be 100+ of these stars, all created by a Factory.
Each Star has it’s own personality (one of seven sprites, position, ID…).

No problem here : I have a beautiful multicolored starfield.

The starfield is bigger than the screen. But I worked a little (two days), and now the starfield move with the cursor keys (well, It move an Ortho camera, but still).

I added Zoom. Had to understand you can’t put negative as zoom, that’s 0.x value is for. But now I can zoom in and out and move my starfield as I want.
Neat.

So much easier that Godot !

And then, and then… Why can’t I click on my stars ?
I can’t have more that 16 input focus, when I can have dozens of star objects on the screen.

Trying to Touch the star with the mouse don’t work, since the star’s object can’t listen inputs, and the machine cursor don’t have CollisionObject.

Created an Object called “Cursor”, added it a Collision Object, and make it in his update function to change it’s position for the “machine” cursor.
But between the lag and the fact I can’t understand how to translate Screen and World coordinates in each other, particularly with the camera moving and zooming, nothing work.

I looked at some “3rd parties” scripts, but I’m not really sure of how it works.

I tried to look at that “input manager” thing, but Im’ sure… I understand nothing (well, there is not a lot of doc on that, apparently).

I read Gui objects can be clicked, then I think trying to put some invisible GUI button on top of each star (with the Screen position). I didn’t try the GUI part of Defold, then I don’t know if that’s possible.

Worked all day on it, but I’m stuck.
Is it really not possible ?

Did you try these:

The recommendation is to centralise input handling, like an “Input manager”, or “game” or “player” script. It is much easier to deal with one or only a few scripts having focus, especially when you need to block input for instance while showing a modal popup or something. It is also not very efficient to have hundreds of scripts all dealing with input every frame. Turn things around and have one script detecting input on many game objects!

This is a good approach!

Here’s two examples of screen to world translation given a camera:

Here’s also a cursor implementation I made:

The repo comes with an example project showing how it can be used.

1 Like

Another option is to use ray casts and cast a very short ray from the screen to world translated mouse position to see if you clicked on a planet.

Thank you for your answers. I’m going to look at all that.

Okay, I moved on. Thank to you and some videos, and the Defold site (I didn’t know every element has an internal ID you can call. Neat for the instances).

I used the cursor script as central for manage inputs, since it’s basicaly the serial-clicker in this game.
And there is the instancied script for the stars objects.

I put the datas from the stars in a Table, created in a Lua. I write/read it with function put in this lua. No problem here.

I put CollisionObjects for the cursor and the sprite objects, with a triger type, because it let me know if the collision stopped.

On the sprite script, I just have :

	if message_id == hash("trigger_response") then
		if message.enter then
			-- take action for entry
			go.set_scale(2)
			msg.post(message.other_id, "etoile_click", {click = true, id = self.id})
		else
			-- take action for exit
			go.set_scale(1)
			msg.post(message.other_id, "etoile_click", {click = false, id = self.id})
		end
	end

The script wait for a message from the system telling him if a collision start (for now any collision, since only the cursor move).
Send them a “I’m collisioned, you can click me” or “Don’t even think of it” to the other object (here the cursor), and the game id (table “Systeme” key) of the clicked object with “message.other_id”.

Curseur.script (cursor)
Init :

	self.objetclicked = nil

Update

	self.collision_id = nil

Set some variables, and in Update but the self.collision_id (the id from the object cursor collisionned with) to nil.

Message

	if message_id == hash("etoile_click") then
		if message.click == true then
			self.objetclicked = message
		else
			self.objetclicked = nil
		end
	end

In message, if Cursor receive a message from a Star, put the entire value “message” if the Star say she’s accepting click, or “nil” else, in the self.objetclicked variable

Input

	if not action_id or action_id == hash("touch") then
		if action_id == hash("touch") and self.objetclicked then
			local tmp = lua_lire_systeme(self.objetclicked.id, "couleur")
			pprint (tmp)
		end

In, finaly, in Input, Cursor listen if a click is done, read in the “systeme” table a value from the key sent by the Star object collisioned, and print it in the console.

Thoughs ?

For the moment, it’s all good, the only thind that fail being puting Game cursor and Machine cursor at the same coordonates

If it works it works!

How are you positioning the cursor? Is it a game object with a sprite and a collision shape? If you correctly detect clicks then I see no reason why the cursor wouldn’t be positioned correctly…

I’m positioning the cursor by making an error in copy/past the “screen to world” function.
Because I can.
As an Evil Genius, I’m entitled to.