Incremental score+sound while moving object along a path

I’m constructing a game that has the player object moving along an outlined path with transition.to, very similar to what is outlined here (no physics):

https://coronalabs.com/blog/2014/01/07/tutorial-moving-objects-along-a-path/

As described in the link, there’s a cumulative delay for each transition. I have the X & Y coordinates displaying at each junction without issue, using an enterFrame listener call to a display function.

When I try to display an incremental scoring option, where each junction has an associated score (e.g. path[i].score=100) that gets added at each point, only the total score displays instantaneously. I’ve tried using onComplete and onPause with the transition (pause and resume in the called function), and even closure function calls with both of these. I can print the incremental scores, but the on-screen display just shows the total before the moves are finished.

The full implementation will hopefully play a midi note(?) at each junction as well.

Thanks in advance for any assistance!

Hi!

When you say

using an enterFrame listener call to a display function

is this function being used solely to update the score visually or does it relate to something else with the objects themselves?

The onComplete should definitely work fine for updating your score at the end of each transition, and if that’s what you’re doing in the enterFrame then remove it from there and just use onComplete.

If you still can’t resolve it, can you provide related code?

Thanks Siu,

Initially the listener call function was used to display the player coordinates; I just added the score display on another line there.

I just tried breaking it off with a separate listener, but no improvement (had my doubts).

Same result with taking it out of the listener-called function and attempting to update with the OnComplete.

I’ll post some related code sections shortly.

OK hopefully not overkill here but this exhibits the issue. Thanks again.



– main.lua


local perspective = require(“perspective”)
local camera = perspective.createView()

local background = display.newImageRect( “background.png”, 10000, 10000 )
background.x = display.contentCenterX
background.y = display.contentCenterY

moveQueue={}
totMoves=3
score=0

local function initTbls()

for i=1, totMoves do
	moveQueue[i]={}
	moveQueue[i].ttMove=0
	moveQueue[i].points=0
end
	
coroutine.yield()

end

function InitPlayer()
playerObj = display.newRect(160, 240, 10, 10 )
playerObj.alpha = 0.8
playerObj.gravityScale=0
camera:add(playerObj,1)
end

local function initTestJuncts()
P1 = display.newRect (160,40,2,2)
P1:setFillColor(1, .5, 0)
camera:add(P1,1)

P2 = display.newRect (0,40,2,2)
P2:setFillColor(1, .5, 0)
camera:add(P2,1)


P3 = display.newRect (0,120,2,2)
P3:setFillColor(1, .5, 0)
camera:add(P3,1)

end

camera.x, camera.y = 0, 80
camera.damping = 10

camera:add(background,1)

local function truncIT(t)
return math.round(t*10)*0.1
end

local function initDispCoords()

coordDisplayX = display.newText(truncIT(playerObj.x), display.contentCenterX, -40,native.systemFont, 10)
coordDisplayY = display.newText(truncIT(playerObj.y), display.contentCenterX, -30, native.systemFont, 10)
scoreDisplay = display.newText(truncIT(score), display.contentCenterX, -15, native.systemFont, 15)

end

local function DispCoords()

coordDisplayX.text = (truncIT(playerObj.x))
coordDisplayY.text = (truncIT(playerObj.y))

end

local function moved()

scoreDisplay.text=(truncIT(score))
print(" moved")

end

local initT = coroutine.wrap(initTbls)
initT()

InitPlayer()
initDispCoords()

Runtime:addEventListener( “enterFrame”, DispCoords)

local function testMoveQueue()
delay=0
deltaX=playerObj.x
deltaY=playerObj.y
for i=1,3 do
deltaX = deltaX + moveQueue[i].xMove
deltaY = deltaY + moveQueue[i].yMove
score=score + moveQueue[i].points
transition.to (playerObj, {x=deltaX, y=deltaY, time=moveQueue[i].ttMove, delay=delay, onComplete=moved} )
delay = delay + moveQueue[i].ttMove
print(“delay=”…delay)

end

end

camera:setFocus(playerObj)
camera:track()
camera:snap()

initTestJuncts()

playerObj.speed=0.1

moveQueue[1].xMove=0
moveQueue[1].yMove=-200
moveQueue[1].ttMove=200/playerObj.speed
moveQueue[1].points=20
moveQueue[2].xMove=-160
moveQueue[2].yMove=0
moveQueue[2].ttMove=160/playerObj.speed
moveQueue[2].points=16
moveQueue[3].xMove=0
moveQueue[3].yMove=80
moveQueue[3].ttMove=80/playerObj.speed
moveQueue[3].points=8

testMoveQueue()

I suspect the following code below is the issue; you’re executing all transitions in a single loop:

local function testMoveQueue()
	delay=0
	deltaX=playerObj.x
	deltaY=playerObj.y
	for i=1,3 do
	  deltaX = deltaX + moveQueue[i].xMove
 	  deltaY = deltaY + moveQueue[i].yMove
	  score=score + moveQueue[i].points
	  transition.to (playerObj, {x=deltaX, y=deltaY, time=moveQueue[i].ttMove, delay=delay, onComplete=moved} )
	  delay = delay + moveQueue[i].ttMove
	  print(“delay=”…delay)

	end
end

What you’d want to do is basically initiate the first transition, and once that’s completed then call the next transition.

Without making a lot of changes to your code, here’s one way to adjust testMoveQueue function to solve the issue:

local function testMoveQueue()
	local delay = 0
	local deltaX = playerObj.x
	local deltaY = playerObj.y
	
	local function moveComplete()
		print("Move complete")
		moved()
		if #moveQueue > 0 then
			local move = table.remove(moveQueue, 1)
			deltaX = deltaX + move.xMove
			deltaY = deltaY + move.yMove
			score = score + move.points
			transition.to(playerObj, { x = deltaX, y = deltaY, time = move.ttMove, onComplete = moveComplete })
		else
			print("All moves complete")
		end
	end
	moveComplete()  -- Start the first move
end

Side note, for this kind of code you shouldn’t really need coroutines, it’ll certainly complicate things, unless you have something else in mind. :slight_smile:

1 Like

Sorry to say that didn’t do the trick.

Is this where the crux of the issue lies? The delay and the deltas both increment accordingly.

Thanks for digging in :slight_smile:

Based on the code you posted, definitely. :slight_smile:

In the current code, you’re adding all points in the loop right away:

score=score + moveQueue[i].points

So, on your first moved call from onComplete=moved the display object will be updated to current score value, which is already summed up at this point.

Your approach might work even by just resolving the score issue, but it’s probably better not to queue all possible transitions at the same time; it’s best to keep running one transition at a time.

Hello Lance,

Below is built on “siu” suggestion and a simplified version of what you have. It works in my simulator (on windows). Hope this helps.

local function move_object_on_path()
	-- https://forums.solar2d.com/t/incremental-score-sound-while-moving-object-along-a-path/356111/4
	
	local coordDisplayX = display.newText( "", 0, 0, native.systemFont )
	local coordDisplayY = display.newText( "", 150, 0, native.systemFont )
	local scoreDisplay = display.newText( "", 0, 100, native.systemFont )
	local playerObj = display.newCircle( 400, 400, 20 )
	playerObj:setFillColor( 1 )
	playerObj.speed = 0.1
		
	local moveQueue = {}
	moveQueue[ #moveQueue + 1 ] = {}
	moveQueue[ #moveQueue + 1 ] = {}
	moveQueue[ #moveQueue + 1 ] = {}
	moveQueue[ 1 ].xMove = 0
	moveQueue[ 1 ].yMove = -200
	moveQueue[ 1 ].ttMove = 200 / playerObj.speed
	moveQueue[ 1 ].points = 20
	moveQueue[ 2 ].xMove = -160
	moveQueue[ 2 ].yMove = 0
	moveQueue[ 2 ].ttMove = 160 / playerObj.speed
	moveQueue[ 2 ].points = 16
	moveQueue[ 3 ].xMove = 0
	moveQueue[ 3 ].yMove = 80
	moveQueue[ 3 ].ttMove = 80 / playerObj.speed
	moveQueue[ 3 ].points = 8
	local score = 0
	
	local function truncIT( t )
		return math.round( t * 10 ) * 0.1
	end
	
	local function DispCoords()
		coordDisplayX.text = ( truncIT( playerObj.x ) )
		coordDisplayY.text = ( truncIT( playerObj.y ) )
	end

	local function moved( score )
		scoreDisplay.text = "score: " .. tostring( ( truncIT( score ) ) )
	end

	-- sugguestion by "siu"
	local function testMoveQueue()
		local delay = 0
		local deltaX = playerObj.x
		local deltaY = playerObj.y
		
		-- transition move along a path 
		local function moveComplete()
			print( "Move complete", score )
			moved( score )
			if #moveQueue > 0 then
				local move = table.remove( moveQueue, 1 )
				deltaX = deltaX + move.xMove
				deltaY = deltaY + move.yMove
				score = score + move.points
				transition.to( playerObj, { x = deltaX, y = deltaY, time = move.ttMove, onComplete = moveComplete } )
			else
				print( "All moves complete" )
			end
		end
		moveComplete()  -- Start the first move
	end
	testMoveQueue()
	Runtime:addEventListener( "enterFrame", DispCoords )
end 
move_object_on_path()