I know this is supposed to be easy.
Since my WIP is time based for score (mostly), I want to be able to state in my level files the number of seconds for target time for the level. And I want the time it takes to move the sprite from one point to the next to be the same (given constant inputs) regardless of the actual FPS of the device.
I have tried using StepPhysics with desired time frame time multiplied by ratio of desired to actual FPS, and using the same ratio to modify the speed used when setting the velocity or impulse (depending on method used to move).
But I just cannot get it constant.
So, I created a test to try different things and to demonstrate the problem.
// set up basic stuff
setInitialConditions()
// create the 'player'
createRunner()
// create the buttons
createButtons()
// set current state to menu
iState = 1
// main loop
do
// get current FPS
fps# = ScreenFPS()
// calculate adjustment for actual vs desired FPS
step_adj# = 60.0 / fps#
// are we testing?
if iState > 1
// get current time
stopTime# = Timer()
// get player position
atX# = GetSpriteXByOffset(1)
// get the speed (pixels moved per frame)
speed# = atX# - oldX#
// check for maximum speed
if speed# > maxSpeed#
// set max
maxSpeed# = speed#
// check for 10.0 (this being observed to be the most pixels per frame)
if (maxSpeed# >= 10.0) and (hit10# < 0.0) then hit10# = stopTime# - startTime#
endif
// store the new position
oldX# = atX#
// check for reaching the edge
if atX# > 934.0
// stop the player
SetSpritePhysicsVelocity(1,0.0,0.0)
// change state back to button test
iState = 1
// reset speed
speed# = 0.0
endif
endif
// display the FPS
PrintC("FPS: ")
Print(Str(fps#,0))
// display adjustment
PrintC("Adjust: ")
Print(Str(step_adj#,1))
// display the speed
PrintC("Speed: ")
Print(Str(speed#,1))
PrintC("Max Speed: ")
Print(Str(maxSpeed#,1))
// display velocity
PrintC("Velocity: ")
Print(Str(GetSpritePhysicsVelocityX(1),1))
// Display time
PrintC("Time: ")
Print(Str((stopTime# - startTime#),1))
// did we hit maximum speed?
if hit10# > 0.0
// display time it happened
PrintC("Time to Top Speed: ")
Print(Str(hit10#,3))
endif
// do something based on state
Select iState
Case 1:
// check for button press
Select GetButtonPressed(1,5)
Case 1:
// exit the app
Exit
EndCase
Case 2:
// set FPS 30
SetSyncRate(30.0,0)
EndCase
Case 3:
// set FPS 60
SetSyncRate(60.0,0)
EndCase
Case 4:
// make the sprite run via velocity
initRunner(2)
EndCase
Case 5:
// make the sprite run via impulse
initRunner(3)
EndCase
EndSelect
EndCase
Case 2:
// velocity test
// assume pointer always pressed at the far edge
// get the difference between current and target
diffX# = 960.0 - atX#
// calculate the speed
spd# = (diffX# / 10.0) * step_adj#
// calculate the vector
vX# = diffX# * spd#
// set the velocity
SetSpritePhysicsVelocity(1,vX#,0.0)
EndCase
Case 3:
// impulse test
// assume direction is straight right
// and accelerometer tilt is at maximum
dirX# = 1.0
dirspd# = 1.0
// calculate the speed based on tilt
spd# = dirspd# * 1000.0 * step_adj#
// calculate the vector based on direction and speed
vX# = dirX# * spd#
// apply the impulse
SetSpritePhysicsImpulse(1,atX#,400.0,vX#,0.0)
EndCase
EndSelect
// set the Physics Step to our adjusted value
StepPhysics(step_phys#*step_adj#)
// update
Sync()
loop
// done, close up shop
end
// the functions
function initRunner(newState)
global iState
global startTime#,stopTime#,oldX#,maxSpeed#,hit10#
// change the state
iState = newState
// reset its position to starting point
SetSpritePositionByOffset(1,25.0,400.0)
// set init run time
startTime# = Timer()
// initialise some other values
stopTime# = startTime#
hit10# = -1.0
maxSpeed# = 0.0
oldX# = 25.0
endfunction
function getButtonPressed(iMin,iMax)
// check buttons
for ib = iMin to iMax
// check the button
if GetVirtualButtonPressed(ib) = 1 then exitfunction ib
next ib
// if we are here, nothing pressed
endfunction 0
function createAVirtualButton(iButt,fAtX#,fAtY#,fWid#,sTxt$)
AddVirtualButton(iButt,fAtX#,fAtY#,fWid#)
SetVirtualButtonText(iButt,sTxt$)
SetVirtualButtonVisible(iButt,1)
endfunction
function createButtons()
createAVirtualButton(1,160.0,580.0,100.0,"Exit")
createAVirtualButton(2,320.0,580.0,100.0,"30FPS")
createAVirtualButton(3,480.0,580.0,100.0,"60FPS")
createAVirtualButton(4,640.0,580.0,100.0,"V Tst")
createAVirtualButton(5,820.0,580.0,100.0,"I Tst")
endfunction
function createRunner()
// make basic sprite
CreateSprite(1,0)
// set its size
SetSpriteSize(1,50.0,50.0)
// give it a color
SetSpriteColor(1,204,102,255,255)
// set its offset to center
SetSpriteOffset(1,25,25)
// make it a physics sprite and set characteristics
SetSpritePhysicsOn(1,2)
SetSpriteShape(1,2)
SetSpritePhysicsFriction(1,0.2);
SetSpritePhysicsRestitution(1,0.5);
SetSpritePhysicsDamping(1,0.25);
SetSpritePhysicsAngularDamping(1,0.5)
// set initial position and initial state to menu
initRunner(1)
endfunction
function setInitialConditions()
global step_phys#
// set up the display
SetVirtualResolution(960,640)
SetOrientationAllowed(0,0,1,1)
// turn off gravity
SetPhysicsGravity(0.0,0.0)
// turn off walls
SetPhysicsWallBottom(0)
SetPhysicsWallTop(0)
SetPhysicsWallLeft(0)
SetPhysicsWallRight(0)
// Set initial speed
SetSyncRate(60.0,0)
// set step rate
step_phys# = 1.0 / 60.0
endfunction
It is okay for the times to be different getting the spriteacross the screen for the different methods (velocity vs impulse, selected with the 'V TST' and 'I TST' buttons).
The issue is getting the same time for the different frame rates (selected with the '60FPS' and '30FPS' buttons).
It appears that you cannot get a sprite to move more than 10 pixels per frame.
I am open to advice and suggestions.
Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master