Mobile Device Commands

17-Jun-2016
Tom Mulgrew

This document

This document describes the Basic4GL Mobile commands that related to mobile devices (i.e. phones and tablets), and web applications.

Platform Identification Commands

Basic4GL Mobile strives to run identically on mobile devices as on PC, so that you can write your program once, and have it up and running across devices easily.

But sometimes the differences between PC and mobile devices make difficult or impractical to for a program to run exactly the same. Tablets and phones don't often have keyboards or game controllers, and PCs often don't have touch screens (and Basic4GL Mobile doesn't support them on PC anyway). Sometimes it makes sense to run different code on different platforms. For example, it might make more sense to display "Press space to Start" on PC, and "Touch screen to Start" on mobile, and then wait for the keypress or touch event depending on the type of device.

Basic4GL provides the following commands for identifying the type of platform you are running on.

PlatformName$

Returns the name of the platform the program is running on, as a text string.

Format:

PlatformName$()

The function will return either:

Example:

print "That's a nice "; PlatformName$(); " device you've got there..."

PlatformIsMobile

Returns true if the platform the program is running on is a mobile device.

Format:

PlatformIsMobile()

This returns true on Android and false otherwise.

It's usually a good idea to use PlatformIsMobile() instead of comparing PlatformName$() to "Android", as this means your program will run correctly when support for other platforms is added, such as iOS.

Example:

if PlatformIsMobile() then
	locate 20, 10: print "Touch the screen to start"
	while Touching(): Sleep(100): wend
	while not Touching(): Sleep(100): wend
else
	locate 20, 10: print "Press space to start"
	ClearKeys()
	while inkey$() <> " ": Sleep(100): wend
endif

print 
print "Here we go"

PlatformIsDesktop

Returns true if the platform the program is running on is a PC.

Format:

PlatformIsDesktop()

This returns true on Windows and false otherwise.

Note: "Desktop" here means any type of Windows PC (so laptops, notebooks etc as well).

As with PlatformIsMobile(), it is usually better to use this command rather than comparing PlatformName$() to "Windows" to future-proof your program when support for new platforms is implemented.

PlatformIsWeb

Returns true if the platform the program is running on is a web browser (via WebAssembly).

Format:

PlatformIsWeb()

This returns true in a web browser and false otherwise.

Note also that when running in a web browser PlatformIsMobile() and PlatformIsDesktop() will always return false.

Touch input

Basic4GL Mobile does not support touch input on PC (even those that have touch screen support).

But just as mobile devices provide basic mouse emulation based on touch events, Basic4GL Mobile programs running on PC will emulate touch events based on mouse input, as follows:

The mouse only emulates a single touch at a time (i.e. multi-touch is not emulated).

When running in a web browser input is handled similarly to running on PC. The primary input device is mouse and touch screen events are emulated.

If the browser happens to be running on a mobile phone/tablet things get more complicated. The mobile device emulates mouse input when you touch the screen. Basic4GL Mobile then emulates touch input based on the mouse input. This gives you mouse/touch input but with limitations: essentially you get the lowest common denominator of both, which is one touch point only and no mouse wheel, right click or hovering.

If you are designing a game for the web and you want it to work on mobile devices (in browser) you will need to keep this in mind.

Simple touch

There is a simplified set of functions if you're only interested in single touch events. Although you may find it simpler to use the mouse input commands in this situation (and rely on mouse emulation on touch screen devices).

Touching

Returns true if the user is currently touching the screen.

Format:

Touching()

TouchX,TouchY

Returns the position of the user's finger.

Format:

TouchX()
TouchY()

For TouchX(), 0 is the left hand side of the screen and 1 is the right (0.5 is midway etc).

For TouchY(), 0 is the top of the screen and 1 is the bottom (0.5 is halfway down etc).

If the user is not touching the screen, TouchX() and TouchY() return the position they were last touching.

TouchStartX, TouchStartY

Returns the position of the user's finger when they started touching the screen.

Format:

TouchStartX()
TouchStartY()

Multi-touch

Mobile devices typically support tracking more than one touch point at a time.

This is used for pinch-and-zoom operations, where you use two fingers to stretch or squeeze things on the screen. In an action game you might use one thumb as a virtual joystick, while the other taps a designated button area to shoot or trigger some other action.

Keep in mind that different devices can handle different numbers of touches at one time.

My tablet handles up to 4 simultaneous touch points, whereas my phone only handles 2 for example.

Touch IDs

Every time the user starts a new touch, it is assigned a touch ID. This is a number that uniquely identifies that touch, which may be important if the user is touching the screen in multiple places simultaneously.

The program can use the touch ID to get information about that specific touch, such as where it started, where the user's finger currently is, and whether it is still touching the screen.

The touch ID remains valid while the user is touching the screen, and for a short while after (until the user has touched the screen 16 more times, to be exact). This gives the BASIC program a chance to extract information about the touch after it has finished, such as the last point of contact (useful for detecting swipes for example).

NewTouchID

Checks for new touches and get their unique touch IDs.

A if new touch is available, this returns a non-zero number (touch IDs are always non zero). If no new touches are available it returns 0.

Be aware that touches are buffered much like keystrokes so if the screen has been touched multiple times NewTouchID will return each of the touches in sequence. Also like keystrokes, the touch buffer is a fixed size, and can fill up if the scren is touched many times between NewTouchID() calls. If it does, old touches will be discarded to make room for new ones.

Once the program has a touch ID it can use it with the following commands:

Touching, TouchX, TouchY, TouchStartX, TouchStartY

The multi-touch versions of these commands have the same name as their single touch versions, the only difference is that each one takes a single touch ID parameter.

Format:

Touching(touchID)
TouchX(touchID)
TouchY(touchID)
TouchStartX(touchID)
TouchStartY(touchID)

The multi-touch commands behave exactly the same as the single touch versions (see above).

TouchCount

Returns the number of concurrent touches.

Format:

TouchCount()

TouchID

Gets the touch IDs of the current active touches.

Format:

TouchID(index)

Where index is the index of the active touch and should be between 0 and TouchCount()-1 inclusive.

If you don't care about tracking specific touches, and just want to know how many times the screen is currently being touched and where, then this is probably the easiest way to achieve this.

For example:

SetTextScroll(false)
TextMode(TEXT_BUFFERED)
print "Multi-touch test"
dim i, id
while true
	for i = 0 to TouchCount()-1
		id = TouchID(i)
		locate TouchX(id) * TextCols(), TouchY(id) * TextRows(): print i+1;
	next
	DrawText()
wend

Accelerometer input

Basic4GL Mobile does not support accelerometer input on PCs (even if they actually have an accelerometer).

The accelerometer functions will always return 0 for rotation and the identity matrix as the transformation.

The accelerometer is not supported on web either. The accelerometer functions behave exactly the same as on PC.

AccelerometerRoll

Returns the "roll" angle of the device in degrees.

Format:

dim roll# = AccelerometerRoll()

Rotating the device anticlockwise (tilting it left) gives a negative roll angle. Rotating clockwise (tilting right) is positive.

AccelerometerPitch

Returns the "pitch" angle of the device in degrees.

dim pitch# = AccelerometerPitch()

Tilting the device towards you gives a negative pitch angle. Tilting away is positive.

AccelerometerTransform

Returns a 4x4 transformation matrix representing the rotation of the device.

dim T#(3,3) = AccelerometerTransform()

Note:The transformation matrix reflects the roll and pitch of the device, but not the yaw, as yaw is not handled by the accelerometer.

Suspending and resuming

ProgramSuspended

Detects whether the program has been suspended.

Format:

WasProgramSuspended()

WasProgramSuspended() returns true if the program has been suspended since the last time WasProgramSuspended() was called, or - if it hasn't been called yet - since the program started running.

On Android the program is suspended when you press the standard Android "Home" or "Overview" buttons, or lock the device (including if you've configured it to lock automatically when not in use). While the program is suspended no BASIC commands are executed - it remains frozen at whichever instruction it was executing at the time. When you resume the program it will carry on executing from where it left off.

Sometimes Android will completely shutdown and unload background Apps, such as when the phone/tablet is running low on memory. If this happens to a Basic4GL Mobile App, then the program will not resume from where it left off, but will run from the start. This also happens if you manually shutdown the App using the "Overview" button.

On Windows you can simulate a suspended App by clicking outside the output window, so that it loses focus. The program won't actually be suspended (it will still continue to run), but WasProgramSuspended() will return true.

Example:

A common behaviour for mobile games is to automatically invoke the pause menu after the App has been suspended, so that the player has time to re-orient themselves before the game resumes.

include standard/gameinput.inc
dim gamepad as TGamepadInput
TextMode(TEXT_BUFFERED)
ResizeText(40, 25)
dim x = 20
while CharAt$(x, 10) = " "
	UIBeginInternal()
	gamepad = GetGamepadInput()
	if gamepad.dir#(0) < -.5 and x > 0 then x = x - 1 endif
	if gamepad.dir#(0) > .5 and x < 39 then x = x + 1 endif
	locate x, 10: print "X";
	locate 0, 24: print
	locate 0, 0: print "                    ";
	locate rnd()%40, 23: print"o";
	if UIButton("Pause") or WasProgramSuspended() then gosub PauseMenu endif
	UIEnd()
	WaitTimer(60)
wend

locate x, 10: print "*";: DrawText()
Sleep(3000): run

PauseMenu:
	while true
		UIBeginInternal()
		if UIButton("Resume") then
			WasProgramSuspended()			' To clear the flag
			return
		endif
		UIEnd()
		WaitTimer(20)
	wend