so, i've been playing with a "virtual trackball". it's not perfect (at all), but its a starting point:
// Project: trackball
// Created: 2019-04-04
// show all errors
SetErrorMode(2)
SetPhysicsDebugOn()
DW = 720 : DH = 1080
// set window properties
SetWindowTitle( "trackball" )
SetWindowSize( DW, DH, 0 )
SetWindowAllowResize( 0 ) // allow the user to resize the window
// set display properties
SetVirtualResolution( DW, DH )
SetOrientationAllowed( 1, 0,0,0)
SetSyncRate( 60, 0 )
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
BallI = CreateRenderImage(320,320,0,0)
tball = CreateObjectSphere(320,12,12)
SetObjectColor(tball,192,192,192,255)
MoveCameraLocalZ(1,-290)
SetCameraRange(1,0.1,2000)
SetCameraAspect(1,1)
SetImageTransparentColor( BallI, 255,0,255)
BallSpr = CreateSprite(ballI)
SetSpriteSize(BallSpr,160,160)
SetSpritePosition(BallSpr,DW-192,DH-192)
SetSpriteTransparency(BallSpr,1)
SetSpriteShapeCircle(BallSpr,0,0,72)
SetSpriteColorAlpha(BallSpr,192)
Player = CreateSprite(0)
SetSpriteSize(Player,48,48)
SetSpriteColor(Player,255,0,0,255)
SetSpritePosition(Player,DW/2,1000)
SetSpriteShapeBox(Player,-24,-24,24,24,0)
SetSpritePhysicsOn(Player,2)
SetSpritePhysicsCanRotate( Player, 0 )
Wall = CreateSprite(0)
SetSpriteSize(Wall,DW,10)
SetSpritePosition(Wall,0,800)
SetSpritePhysicsOn(Wall,1)
SetSpriteVisible(Wall,0)
do
mx# = GetPointerX() : my# = GetPointerY()
if GetPointerState() = 1
if washit = 0
SetSpritePosition(BallSpr,mx#-80,my#-80)
SetSpriteVisible(BallSpr,1)
washit = 1
lastx# = mx#
lasty# = my#
else
if GetSpriteHit(mx#,my#) = BallSpr
xdiff# = (lastx#-mx#)
ydiff# = (lasty#-my#)
lastx# = mx#
lasty# = my#
else
SetSpriteVisible(BallSpr,0)
endif
endif
else
xdiff# = xdiff# * 0.8 : ydiff# = ydiff# * 0.8
washit = 0
if GetSpriteVisible(BallSpr) = 1 then SetSpriteVisible(BallSpr,0)
endif
SetSpritePhysicsVelocity( Player, -xdiff#*200, -ydiff#*200 )
SetRenderToImage(BallI,0)
SetClearColor(255,0,255)
ClearScreen()
SetObjectVisible(tball,1)
`rotate the ball! :)
Render3D()
SetObjectVisible(tball,0)
SetClearColor(128,0,0)
SetRenderToScreen()
Sync()
loop
the idea gives the user the choice of where to put their finger (IE, away from the player).
an alternative is to stick it near one of the bottom corners. if the player presses near the bottom left, that's where the sprite appears. press near the bottom right, you get it...

at 1 of 2 fixed locations (maybe both?). just keep it maybe 24px away from the edges.
the "roll" is in there but it needs tweaking, too (a flag to just let it fade when the sprite's hidden, i think). alas, my phone

died testing, so i'll go get that sorted

in the meantime, it has precise movement, and then think "short swipes" to roll/drift the player, takes a little getting used to but the effect is there.