Hello, I’m trying to make a draggable object stay only in a specific zone or return to its original position. I’ve already implemented the return functionality, but I can’t figure out how to detect collisions with the target zone. I’ve tried setting up triggers, checking group/mask properties via messaging, but nothing works. Please guide me in the right direction and correct my example so I can understand what I’m doing wrong. Thank you in advance.
I downloaded your example and indeed there was no interaction between cursor and drop zone.
Luckily the issue is easy to fix
Your cursor’s collision object have group “cursor” and mask “drop_zone, draggable”.
Your draggable object’s collision object have group “draggable” and mask “cursor, drop_zone”.
Your drop zone’s collision object have group “drop_zone” and mask “draggable”.
I believe that there are collisions happening between draggable object and drop zone. However your script is connected only to the cursor object, therefore only messages related to cursor are routed to it.
Since cursor is not in the drop zone’s mask, there is no collision between drop zone and cursor.
Simply change drop zone’s collision object mask from “draggable” to “draggable, cursor” or just “cursor” and your print statement will work:
DEBUG:SCRIPT: зона сброса
However remember that trigger will only emit message when collision between kinematic and trigger object changes. You may have to track there messages to decide if cursor is inside trigger zone.
Luckily again, only 2 lines have to be changed. You have to add proper flag and set it state in response to the message. Find the modified cursor script below. Modified line are number 8 and 38.
function init(self)
msg.post(".", "acquire_input_focus")
self.collision_id = nil -- id of gameobject which the cursor collided with
self.dragged_id = nil -- id of gameobject currently being dragged
self.dragged_pos = nil -- The position of the dragged_id game object
self.pressed = false -- Binary flag indicating if the user has touched the screen
self.is_inside = false
end
function update(self, dt)
-- Add update code here
-- Learn more: https://defold.com/manuals/script/
-- Remove this function if not needed
-- Set the render clear color--aka, screen color when nothing is rendered
msg.post("@render:", "clear_color",
{ color = vmath.vector4(95 /256, 129 / 256, 161 / 256, 1 ) })
-- Get the current position of the cursor
local pos = go.get_position()
-- Set the label to echo the cursor position (pos.x and pos.y)
label.set_text("#cursorLabel", "---- x: " .. pos.x .. " y: " .. pos.y)
-- Reset the control variable for collision_id each frame
self.collision_id = nil
if not self.pressed and self.dragged_id then
local s1 = vmath.vector3(1.0)
go.set_scale(s1, self.dragged_id)
self.dragged_id = nil
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("trigger_response") and message.other_group == hash("drop_zone") then
self.is_inside = not self.is_inside
print('Is inside drop zone?', self.is_inside)
elseif message_id == hash("collision_response") then
if not self.collision_id or
go.get_position(self.collision_id).z < message.other_position.z then
self.collision_id = message.other_id
self.touchedGroup = message.other_group
end
end
end
function on_input(self, action_id, action)
-- Add input-handling code here. The game object this script is attached to
-- must have acquired input focus:
--
-- msg.post(".", "acquire_input_focus")
--
-- All mapped input bindings will be received. Mouse and touch input will
-- be received regardless of where on the screen it happened.
-- Learn more: https://defold.com/manuals/input/
-- Remove this function if not needed
if not action_id or action_id == hash("touch") then
local action_pos = vmath.vector3(action.x, action.y, 0)
go.set_position(action_pos)
if action.pressed then
msg.post("#collisionobject", "enable")
self.pressed = true
print("TOUCH")
elseif action.released then
msg.post("#collisionobject", "disable")
self.pressed = false
print("DROP")
end
-- Обработка выбора объекта
if self.pressed and self.collision_id and not self.dragged_id then
self.dragged_id = self.collision_id
self.dragged_pos = action_pos
go.set_scale(vmath.vector3(1.2), self.dragged_id)
end
-- Активация перетаскивания при смещении
if self.dragged_id and not self.dragging then
if vmath.length(self.dragged_pos - action_pos) > 20 then
self.dragging = true
end
end
-- Перемещение объекта
if self.dragging then
go.set_position(action_pos, self.dragged_id)
end
end
end
Expected console output:
The rest is up to you, you just need to implement object return to original position if it was dropped outside dropzone, but I’m sure you can do it yourself. Nevertheless, do not hestiate to ask for more help if needed