This is the easiest way to add gamepads to an app.
It provides four functions: sandbox
, element
, document
, application
that replace those in the elm/browser
package.
These functions require an additional Config argument, which tells them what to do with gamepads.
import Gamepad
import Gamepad.Simple
import GamepadPort
type Msg
= OnAnimationFrame Gamepad.Simple.FrameStuff
config : Gamepad.Simple.Config Msg
config =
{ onAnimationFrame = OnAnimationFrame
, onBlob = GamepadPort.onBlob
, saveToLocalStorage = GamepadPort.saveToLocalStorage
, controls =
[ ( "Move LEFT", Gamepad.LeftStickLeft )
, ( "Move RIGHT", Gamepad.LeftStickRight )
, ( "Move UP", Gamepad.LeftStickUp )
, ( "Move DOWN", Gamepad.LeftStickDown )
--
, ( "Aim LEFT", Gamepad.RightStickLeft )
, ( "Aim RIGHT", Gamepad.RightStickRight )
, ( "Aim UP", Gamepad.RightStickUp )
, ( "Aim DOWN", Gamepad.RightStickDown )
--
, ( "FIRE", Gamepad.RightTrigger )
, ( "Alt FIRE", Gamepad.RightBumper )
, ( "Transform", Gamepad.A )
, ( "Rally", Gamepad.B )
, ( "Menu", Gamepad.Start )
]
}
main =
Gamepad.Simple.sandbox
config
{ init = init
, view = view
, update = update
}
update msg model =
case msg of
OnAnimationFrame { gamepads, timestamp, dt } ->
...
You will need to manually add port code. See Adding Ports for how to do it.
The remapping tool can be toggled with the Escape
key, but will pop up
automatically when the user tries to use an unrecognized gamepad.
While the remapping tool is open, the wrapped app will continue to receive its
own messages normally, but will NOT receive onAnimationFrame
.
User mappings are saved to localStorage.
Platform.Program flags (Model model) (Msg msg)
A Program wrapped by this module
{ onBlob : (Gamepad.Advanced.Blob -> Msg msg) -> Platform.Sub.Sub (Msg msg)
, saveToLocalStorage : String -> Platform.Cmd.Cmd Basics.Never
, onAnimationFrame : FrameStuff -> msg
, controls : List ( String
, Gamepad.Digital )
}
The additional parameters needed to create a wrapped Program
onBlob
should be always set to GamepadPort.onBlob
saveToLocalStorage
should be always set to GamepadPort.saveToLocalStorage
onAnimationFrame
will give you timing and gamepad informationcontrols
specifies which controls you want and which name to use when asking the user to configure them{ gamepads : List Gamepad
, timestamp : Time.Posix
, dt : Basics.Float
}
Gamepad polling should happen at every animation frame, so timing information and gamepad state information arrive together in this record.
Use the functions in the Gamepad
module to make sense of the Gamepad
objects.
The timestamp
and dt
fields are exactly what you would expect if you were using
Browser.Events.onAnimationFrame
and
Browser.Events.onAnimationFrameDelta
respectively.
sandbox : Config msg -> { init : model, view : model -> Html msg, update : msg -> model -> model } -> Program () model msg
Same as Browser.sandbox
element : Config msg -> { init : flags -> ( model, Platform.Cmd.Cmd msg ), view : model -> Html msg, update : msg -> model -> ( model, Platform.Cmd.Cmd msg ), subscriptions : model -> Platform.Sub.Sub msg } -> Program flags model msg
Same as Browser.element
document : Config msg -> { init : flags -> ( model, Platform.Cmd.Cmd msg ), view : model -> Browser.Document msg, update : msg -> model -> ( model, Platform.Cmd.Cmd msg ), subscriptions : model -> Platform.Sub.Sub msg } -> Program flags model msg
Same as Browser.document
application : Config msg -> { init : flags -> Url -> Browser.Navigation.Key -> ( model, Platform.Cmd.Cmd msg ), view : model -> Browser.Document msg, update : msg -> model -> ( model, Platform.Cmd.Cmd msg ), subscriptions : model -> Platform.Sub.Sub msg, onUrlRequest : Browser.UrlRequest -> msg, onUrlChange : Url -> msg } -> Program flags model msg
Same as Browser.application
basicControls : List ( String, Gamepad.Digital )
If you don't know yet which controls to use for your game, you can use
this list: Gamepad.Simple
will use the list to ask the user to configure
the Left Stick and two buttons, A and B.
basicControls =
[ ( "Up", Gamepad.LeftStickUp )
, ( "Down", Gamepad.LeftStickDown )
, ( "Left", Gamepad.LeftStickLeft )
, ( "Right", Gamepad.LeftStickRight )
, ( "A", Gamepad.A )
, ( "B", Gamepad.B )
]
This means that inside your app, you will be able to use:
leftStickPosition
isPressed
, wasClicked
, wasReleased
with LeftStickUp
, LeftStickDown
, LeftStickLeft
, LeftStickRight
, A
, B
value
with LeftX
, LeftY