DEV Community

Graham Long
Graham Long

Posted on

Implementing the Xbox Controller

Before you read this.

While re-reading this post, I noticed an oversight in handling the movement controls. I shall address this in a subsequent post.

Abstracted control

Following from the last devlog I created the LookControlInterface, MoveControlInterface, ButtonControlInterface and the GameContolHub class.
The XboxController class implemented the three control interfaces and a new instance of it was created in the activities onCreate method, which was then passed to the GameControlHub instance as each of the interfaces.

instantiation of new classes
The GameControlHub instance was then passed to the VrRenderer instance via the VrGlSurfaceView to allow the renderer to process game controls.

The XboxController class

This class was based on the Android handling controller actions guide with the following exceptions:

  • I did not implement the code to check if there was a game controller connected as the class would just return identity matrices if there was no controller, this is an area of possible future improvement
  • I worked out which MotionEvent axis equated to the left and right joystick's up/down and left/right axis and hard coded these, I am assuming all xbox controllers use the same control scheme so this should be fine.

Processing the stick inputs

This code only updates the Android device when a stick has changed position, if the stick is kept in the same position then there will be no updates via the onGenericMotionEvent function, to make this usable, I kept a local copy of the last reported position of the sticks as mTranslationMatrix for both the left stick axis and mPitchDelta for the right stick's up/down axis and mYawDelta for the right stick's left/right axis.
Whenever the getLatestTranslationMatrix function is called, I simply return a copy of mTranslationMatrix.
Whenever the getLatestRotationMatrix function is called, the current mPitchAngle is adjusted by mPitchDelta, making sure it is capped at looking directly up or directly down and mYawAngle is adjusted by mYawDelta, making sure to wrap the angle from 360° to 0° for incrementing angles or 0° to 360° for decrementing angles.
These new values of mPitchAngle and mYawAngle are used to generate the rotation matrix which is returned.
When calculating the rotation matrix, the mPitchAngle is rotated first, as the pitch won't be skewed by a subsequent yaw rotation but a yaw rotation would be skewed by a subsequent pitch rotation.

Doing something with this control input

Now that we have a method of receiving control input from the player, what are we going to do with it?
Initially we are going to move the camera position and look direction.
To do this we need to add a function to the GameCamera class to allow adjustments to the position and we need to finish off the setCameraRotation method.
The adjustPosition function is pretty simple and just adds the passed x, y and z delta's to the current x, y and z positions.
Screen capture of adjustPosition method
The setCameraRotation method creates a forward matrix which represents a translation of 1 unit forward and an up matrix which represents a translation of 1 unit up.
forward and up matrix creation
Each of these matrices are multiplied by the passed rotation matrix rotMat and the 12th, 13th and 14th elements are extracted from the matrices to set the mLookDirectionX, mLookDirectionY, mLookDirectionZ, mUpDirectionX, mUpDirectionY and mUpDirectionZ values.
rotating the forward and up matrices and setting local variables
Once all this was implemented I added a few extra triangles to the scene so I could get a better sense of how I was moving around.
The Source code at this point of the process has been captured in pre-release B1.3 on Github.

The next steps

Next, I plan on implementing a skybox/cubemap to add a bit of background to the scene, this is not something I have done before but sounds pretty straight forward, I also plan on adding some more complex models and some lighting effects to the opengl shaders.

Top comments (0)