Last week I shared my decision—in the name of more fun games for the world— to make good use of my commute time and build a Amazon Fire TV and Fire Stick game using GameMaker: Studio.
The GameMaker documentation gives a general overview of supporting game controllers. Finding details on how game controller support works with Amazon Fire TV proved to be a little more difficult. In the next few posts in the series I will provide the missing information, focusing on:
- Basic Controller Detection
- Handling Controllers and Controls
- Using the Amazon Fire TV Remote and Controller Selection
Let’s dive into basic controller detection.
Handling the game controller and remote control on Amazon Fire TV and Fire TV Stick
Using YoYo Games GameMaker: Studio to build PC games that use the keyboard or even a USB game controller is pretty easy and many developers choose to first get their game up and running on their PC. This offers the convenience of easy debugging and very fast edit-build-test cycles. When you want to move to a mobile device or a platform like Amazon Fire TV, however, you are going to have to invest some time to build in proper support for game controller detection.
Basic controller detection
GameMaker provides a “System” event on objects. While it may do more in the future, currently the only thing this provides is game controller detection through async functions. This means that whenever a game controller is connected or disconnected, if you have a system event on an object, that code will run.
You don’t need to put this code on every game object. Typically, a game has a title or menu screen, which in GameMaker would be implemented as a room. Additional play screens are implemented as additional rooms. It is also common that in each of these rooms you will have a controller (not to be confused with the game controller) or state management object that lives the entire time the room is active. Often this is the object that will do things like draw the GUI for the game with the score, health, lives, etc. This is the object where you should include the code to detect the controller.
The System event returns a ds_map structure of name/value pairs. This will contain basically two pieces of information whenever a controller is connected or lost: which controller ID was affected (called the “pad_index”) and what happened, with the key “event_type”. The event_type will be either “gamepad discovered” or “gamepad lost”.
On Amazon Fire TV, this ds_map will also return information for the remote control, so you will need to take this into account if you want to support using the remote in your game or if you specifically do not want to support the remote.
In my single-player game, I created a global variable for the controller the player had selected to use. For a multiplayer game, you’d need to track this in multiple variables or an array and provide a means for each user to select their controller.
In the “Create” event for the state object on your first interaction screen (menu, title, etc.), add this code:
for (var id = 0; id < 10; id++;)
player[id] = noone;
This code creates an array of 10 elements to hold controller IDs and sets all the elements to the built-in GML value representing nothing. Support for 10 devices is far more than you would typically ever find connected to an Amazon Fire TV, but better to support more and not have the possibility of a crash in the extreme case.
In the “System” event of the same object, add this code to detect the controllers being added and removed. This code will end up populating our player array with an element for the remote control as well as for each controller.
switch (async_load[? "event_type"])
case "gamepad discovered":
// get the value associated with key pad_index
var pad = async_load[? "pad_index"];
// set the deadzones for the axis and analog buttons on the controller
// as the code is written this will be set for the remote control
// also, but will be ignored, so no harm
// if the controller slot is already in use, assign the pad ID
// set the selected gamepad to this pad
pad_num = pad;
case "gamepad lost":
// when a controller disconnect, clear its slot in the player array
var pad = async_load[? "pad_index"];
player[pad] = noone;
If you want to only detect game controllers without remotes, add this line at “// *1*” above:
if (string_pos("ontroller", gamepad_get_description(pad)) !=0)
And a closing brace at “// *2*”
This code simply ignores any controller connection that doesn’t contain “ontroller” in the controller description.
Stay tuned for next week’s installment where I take a close look at handling controllers.
Don't miss the rest of the Building Retroids with GameMaker blog series!
Part 1: Studio
Part 3: Handling Controllers
Part 4: Fire TV Remote and Controller Selection