OK, instead of watching football (Champions League), I’ve decided to solve this. Here is what I came up with. The key was to calculate the drag delta and the velocity, using the update function, apply the velocity to the last action.x and action.y after the drag had ended, and pass the updated action.x and action.y to gooey.static/dynamic_list until velocity becomes 0. Here is the code in case it helps someone.
NOTE: I don’t really like using the update lifecycle function. I do reactive programming with events and message passing to update GUI and game state, and use gui.animate, go.animate where possible. But in this instance using the update function was the quickest to implement a solution. I’d love to use gui.animate to apply the inertia, if anyone can figure it out please let me know.
-- Smooth scrolling
local listVelocity = 0 -- Stores the current velocity
local dragStartY = 0 -- Starting Y position of the drag
local isDragging = false -- Flag for when the user is dragging
local inertia = true -- Enable inertia effect
local deceleration = 0.95 -- How fast inertia slows down
local inputAction = nil -- The current touch/mouse input action
-- The last x and y action positions when the drag ends so we can continue adding the decelerating velocity and pass it to the gooey list
local lastActionX, lastActionY = 0, 0
function on_input(self, action_id, action)
-- Reference the current touch/mouse action
inputAction = action
if action_id == hash("touch") then
-- Keep drag within the stencil bounds
local overListStencil = gui.pick_node(self.avatarsListStencil, action.x, action.y)
if overListStencil then
if action.pressed then
isDragging = true
dragStartY = action.screen_y
listVelocity = 0 -- Reset velocity when starting a new drag
elseif action.released then
isDragging = false
end
if isDragging then
-- Calculate the drag delta
local dragDelta = action.screen_y - dragStartY
dragStartY = action.screen_y
-- Store the velocity for inertia effect
listVelocity = dragDelta
end
else
isDragging = false
end
end
end
function update(self, dt)
-- Apply inertia if the user is not dragging and inertia is enabled
if (not isDragging) and inertia then
listVelocity = listVelocity * deceleration
-- Stop the inertia when velocity is low
if math.abs(listVelocity) < 1 then
listVelocity = 0
end
end
-- Make sure the input action is initialised
if inputAction then
-- If the user is actively dragging, then don't apply any velocity, allow Gooey do it's thing.
if isDragging then
lastActionX, lastActionY = inputAction.x, inputAction.y -- Reference the last drag x and y positions when the drag ends for setting the velocity of the drag
setStaticlist(self, hash('touch'), inputAction)
-- The drag has ended. Apply the velocity to the last action x and y position and pass it to the Gooey's static_list function.
else
-- Update the last action x and y by adding the velocity for the inertia effect
lastActionX = lastActionX + listVelocity
lastActionY = lastActionY + listVelocity
-- Move the Gooey list items based on the calculated action x and y positions
setStaticlist(self, hash('touch'), {x = lastActionX, y = lastActionY})
end
end
end
Here is the smooth scrolling in action. The software I’ve used to record the screen limits to 12fps, the actual implementation is smooth.