00:00
00:00
3p0ch
If you like hard games try my Daxolissian System series

plasmid @3p0ch

Cat

Scientist

Read the manual & try stuff

So Cal

Joined on 2/13/10

Level:
13
Exp Points:
1,650 / 1,880
Exp Rank:
38,330
Vote Power:
5.48 votes
Audio Scouts
1
Rank:
Portal Security
Global Rank:
23,500
Blams:
50
Saves:
375
B/P Bonus:
8%
Whistle:
Normal
Medals:
4,624
Supporter:
3y 3m 14d

Tutorial on using the Gamepad mapper with HaxeFlixel

Posted by 3p0ch - April 3rd, 2022


Here's source code for the demo of using the Gamepad mapper in HaxeFlixel which includes a Gamepad.hx file that should be saved in your root directory next to Main.hx when you're making your game, and the PlayState.hx file which shows how to use it in a game.


Gamepad.hx

package;

import haxe.Json;
import js.Browser;

class Gamepad {
  public static var url = "https://www.newgrounds.com/portal/view/project/1765261";
  public static var key = "gamepad_configuration";
  // Feel free to change the dead zone for axis readings here if you like
  public static var deadZone:Float = 0.1;

  public static var config:Dynamic = null;
  public static var gamepadArray:Array<Dynamic>;
  public static var lastState:Dynamic = {};
  public static var currentState:Dynamic = {};
  
  // These can make it easier to loop through things
  public static var buttonNames:Array<String> = ["ButtonUp", "ButtonDown", "ButtonLeft", "ButtonRight",
      "DUp", "DDown", "DLeft", "DRight", "L1", "L2", "R1", "R2", "Start", "Select",
      "LStickPress", "RStickPress"];
  public static var axisNames:Array<String> = ["LStickUp", "LStickDown", "LStickLeft", "LStickRight",
      "RStickUp", "RStickDown", "RStickLeft", "RStickRight"];
  
  // Read the gamepad configuration from the player's browser memory
  public static function readConfig() {
    config = Json.parse(Browser.window.localStorage.getItem(key));
  }

  // Open the page with the gamepad configuration gizmo
  public static function runConfig() {
    Browser.window.open(url);
  }

  // Call this function to read the current gamepad state
  // Use it at some point during each frame before checking for button presses and axis positions
  public static function update() {
    gamepadArray = Browser.window.navigator.getGamepads();
    // Look for the first gamepadArray index with data
    while ((gamepadArray.length > 0) && (gamepadArray[0] == null)) {
      gamepadArray.shift();
    }
    // If there is an array element with gamepad data,
    // check if it's new compared to the most recent data
    // and only update lastState and currentState if the data is new
    if (gamepadArray.length > 0) {
      if (Reflect.field(gamepadArray[0], "timestamp") == Reflect.field(lastState, "timestamp")) {
        return;
      }
      lastState = currentState;
      currentState = gamepadArray[0];
    } else {
      // If gamepadArray.length reached zero without a gamepadbeing detected, make currentState null
      lastState = currentState;
      currentState = null;
    }
  }

  // Returns true if the indicated button is currently being held down
  public static function isPressed(buttonName:String):Bool {
    if (!buttonNames.contains(buttonName)) {
      trace('Attempted to check isPressed for button $buttonName but there is no button with that name.');
    } else if (Reflect.field( Reflect.field(currentState, "buttons")[Reflect.field(config, buttonName)], "pressed" )) {
      return true;
    }
    return false;
  }

  // Returns true if the indicated button has just been pressed on the latest update
  public static function justPressed(buttonName:String):Bool {
    if (!buttonNames.contains(buttonName)) {
      trace('Attempted to check justPressed for button $buttonName but there is no button with that name.');
    } else if ((Reflect.field( Reflect.field(currentState, "buttons")[Reflect.field(config, buttonName)], "pressed" ))
           && !(Reflect.field( Reflect.field(   lastState, "buttons")[Reflect.field(config, buttonName)], "pressed" ))) {
      return true;
    }
    return false;
  }

  // Returns the value of an axis, only if its absolute value is greater than deadZone
  // Directionality affects the sign, for example if the player is holding the left stick up halfway then
  // Gamepad.axis("LStickUp") would return 0.5
  // Gamepad.axis("LStickDown") would return -0.5
  public static function axis(axisName:String):Float {
    if (!axisNames.contains(axisName)) {
      trace('Attempted to read axis $axisName but there is no axis with that name.');
    } else if (Reflect.field(currentState, "axes")[Reflect.field(config, axisName)] && Reflect.field(config, axisName + "_direction")) {
      if (Math.abs(Reflect.field(currentState, "axes")[Reflect.field(config, axisName)]) > deadZone) {
        return Reflect.field(currentState, "axes")[Reflect.field(config, axisName)] * Reflect.field(config, axisName + "_direction");
      }
    }
    return 0.0;
  }
}


PlayState.hx

package;

// Be sure to import Gamepad.Gamepad
import Gamepad.Gamepad;
import flixel.FlxState;
import flixel.text.FlxText;
import flixel.ui.FlxButton;

class PlayState extends FlxState {
  var configButton:FlxButton;
  var gamepadText:FlxText;
  
  // You should include this in your PlayState.hx so if your game loses and then regains focus
  // (such as if the player ran the gamepad configuration gizmo and now returned to your game)
  // it will read the updated gamepad data from the player's browser
  override public function onFocus() {
    Gamepad.readConfig();
    super.onFocus();
  }
  
  override public function create() {
    // Also be sure to run Gamepad.readConfig() in your PlayState.hx create() function
    Gamepad.readConfig();
    
    // Button to let the player configure their gamepad
    configButton = new FlxButton(10, 10, "Configure", function() {
      Gamepad.runConfig();
    });
    
    gamepadText = new FlxText(10, 50);
    
    add(configButton);
    add(gamepadText);
    
    super.create();
  }

  override public function update(elapsed:Float) {
    // I recommend running Gamepad.update() at the beginning of your PlayState.hx update() function
    Gamepad.update();
    if (Gamepad.currentState == null) {
      gamepadText.text = "No gamepad detected, try plugging in and pressing stuff";
    } else {
      gamepadText.text = "";
      for (axis in Gamepad.axisNames) {
        gamepadText.text += axis + ": " + Gamepad.axis(axis) + "\n";
      }
      gamepadText.text += "\nPressed buttons\n";
      for (button in Gamepad.buttonNames) {
        if (Gamepad.isPressed(button)) {
          gamepadText.text += button + "\n";
        }
      }
    }
    
    super.update(elapsed);
  }
}


The one tricky part is that the gamepad mapper gizmo on NewGrounds will save the gamepad configuration data in Local Storage which is only accessible to webpages running on NewGrounds, so if you're running your game locally using Lime's "test" (so not on NewGrounds) then it won't be able to read the configuration that was set on NewGrounds. So you should copy/paste the gamepad_configuration to Local Storage for your game while it's running locally, and then any time you run your game locally the gamepad will be configured. If you're not already familiar with editing Local Storage directly from your browser, here are super detailed instructions for Firefox and Chrome:


After you've used the Gamepad mapper on NewGrounds, go to any NG page with a game actively running (the Gamepad mapper's page would work) and in your browser's Developer Tools under the tab called Application (on Chrome) or Storage (on Firefox) you should have an option of looking in Local Storage and selecting https://uploads.ungrounded.net. Pick that, then find gamepad_configuration (your browser will probably show a Filter box after you click ungrounded.net under Local Storage, where you can type gamepad_configuration to narrow it down). Right-click on the Value and choose Edit, and you can copy it to your clipboard.


Then while you're running your own game locally to test it, you can go to the Developer Tools tab, Application, Local Storage, whatever it has for your game (probably file://), and click on file:// or whatever it shows. If you're using Firefox: click the + button to the right of the Filter box to add a new item in Local Storage and set its Key to gamepad_configuration and paste the Value in. If you're using Chrome: click on the empty row at the end of the list of Key/Values (which might be the very first row if you haven't been using Local Storage locally), right-click to add a new key called gamepad_configuration, and paste the configuration data as its value. Then reload the page, and it should be able to read the gamepad configuration.


Tags:

1

Comments

Comments ain't a thing here.