Orientation based device input
Since this is a relatively simple game, I wanted it to be accessible across all devices, which means enabling smartphone inputs. A smartphone has no buttons, and I didn't want to put simulated buttons on the screen to obscure the gameplay, so I decided to receive input from the myriad sensors that a modern smartphone has. However, receiving orientation data from the web browser in a smartphone is another beast entirely.
To simplify, I will only target an updated Chrome browser on an Android. The attempt is to implement as much of the input logic in Javascript as possible so that the main game loop does not need to adapt to different input paradigms. This will enable the same code to be built for different platforms, and a conditional check will ensure that the orientation input is only considered if built for HTML5. The strategy is as follows:
- Record the initial orientation of the device, and set it as 0.
- Set up an Event Listener that listens to changes in orientation.
- Whenver an orientation change event is triggered, calculate the distance from the initial orientation, and accelerate the Player accordingly.
Step 2 and 3 are easy, and can be set up as follows:
var Javascript = JavaScriptBridge
func _ready():
if !OS.has_feature('web'): return
Javascript.eval("""
var initOrient = {x: 0., y: 0.}
var orient = {x: 0., y: 0.}
function registerMotionListener() {
window.ondeviceorientation = function(event) {
orient.x = event.gamma - initOrient.x
orient.y = 2.5*(event.beta - initOrient.y)
}
}
if (typeof DeviceOrientationEvent.requestPermission === 'function') {
DeviceOrientationEvent.requestPermission().then(function(state) {
if (state === 'granted') registerMotionListener()
})
}
else {
registerMotionListener()
}
""", true)
func get_orientation() -> Vector2:
if !OS.has_feature('web'): return Vector2.ZERO
return Vector2(Javascript.eval('orient.x'), Javascript.eval('orient.y'))
The event.gamma
and event.beta
variables return the tilt along the x
and y
axes respectively, so the Vector2
returned by get_orientation()
can be added to the usual Input
axis to encapsulate all possible inputs that the Player object can receive. Rest of the code can use the overall Input
axis as usual.
However, setting the initial orientation values is not so simple. Since JS does not allow you to synchronously pause the execution of a program until an event is received, my solution (inspired by this StackOverflow question) was to add a Boolean to the initOrient
dictionary called freeze
set to false
, and set it to true
the first time an event is received. Further executions will simply check this freeze
variable and calculate the distance from initOrient
if it is set to true
. The registerMotionListener
function then changes to
function registerMotionListener() {
window.ondeviceorientation = function(event) {
if(!initOrient.freeze) {
initOrient.x = event.gamma
initOrient.y = event.beta
initOrient.freeze = true
}
orient.x = event.gamma - initOrient.x
orient.y = 2.5*(event.beta - initOrient.y)
}
}
This seems to work.
Get Size Matters in Space
Size Matters in Space
Status | Prototype |
Authors | Sir Unknown, absurdlyam, Thdragoon |
Genre | Shooter |
Languages | English |
Leave a comment
Log in with itch.io to leave a comment.