NaN:NaN
NaN:NaN

Scale and position your image


3p0ch
Drop file(s), or click here to upload.
    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,760 / 1,880
    Exp Rank:
    38,573
    Vote Power:
    5.52 votes
    Audio Scouts
    1
    Rank:
    Portal Security
    Global Rank:
    23,339
    Blams:
    50
    Saves:
    381
    B/P Bonus:
    8%
    Whistle:
    Normal
    Medals:
    5,082
    Supporter:
    4y 6m 10d

    Tutorial on using the Gamepad mapper with JavaScript

    Posted by 3p0ch - March 5th, 2022


    Here's the source code for the tutorial on using the Gamepad mapper in a pure JavaScript game. Some general-use functions that you can copy/paste into your game are included in the beginning, the rest shows how to implement them in practice.

    <!DOCTYPE html>
    <html>
      <body bgcolor="white">
        <button id="button"></button>
        <p id="para"></p>
        <script>
          
          // **** Here are some generally useful functions ****
          
          // This function attempts to read the gamepad configuration from localStorage
          // It will either return an object with the configuration data,
          //   or null if no gamepad configuration has been saved yet.
          // In your game, you can test whether or not it's null and give the player a
          //   visual cue of whether a gamepad config has been successfully loaded
          //   (like show "Configue gamepad" if not, or "Re-configure gamepad" if so)
          function read_gamepad_config() {
            const gamepad_key = "gamepad_configuration";
            
            return JSON.parse(localStorage.getItem(gamepad_key));
          }
          
          // Open the page on NewGrounds to configure the gamepad
          // The page to configure the gamepad will automatically close itself when it's done
          // So you can listen for when your game's window is focused again and then
          //   attempt to read the gamepad configuration that was just set
          function run_config() {
            const gamepad_mapper_url = "https://www.newgrounds.com/portal/view/project/1765261";
            
            window.open(gamepad_mapper_url);
            window.addEventListener("focus", function(){
              read_gamepad_config();
            }, {"once": true});
          }
          
          // Return true if a gamepad button is pressed
          // If you make your gamepad object and your gamepad configuration global
          //   then you could set up your function to just take button_name
          function is_button_pressed(button_name, gamepad, config) {
            // Make sure button_name exists in config (check for typos of button_name)
            if (button_name in config) {
              if (config[button_name] !== null) {
                return gamepad.buttons[config[button_name]].pressed;
              }
            } else {
              console.log ("Attempted to read button named " + button_name +
                  " but that button name is not configured");
            }
            return false;
          }
          
          // Return the value of an axis
          // If you make your gamepad object and your gamepad configuration global
          //   then you could set up your function to just take axis_name
          // If you want to set dead-zones to zero within in this function, feel free
          function axis_value(axis_name, gamepad, config) {
            // Make sure axis_name exists in config (check for typos of button_name)
            if (axis_name in config) {
              if (config[axis_name] !== null) {
                return gamepad.axes[config[axis_name]] * config[axis_name + "_direction"];
              }
            } else {
              console.log ("Attempted to read axis named " + axis_name +
                  " but that axis name is not configured");
            }
          }
          
          
          // **** End of generally useful functions ****
          // The rest is demonstration of using them in practice
          
          let html_button = document.getElementById("button");
          let html_para = document.getElementById("para");
          let gamepad_index;
          let gamepad_config;
          let gamepad_object;
          
          let button_names = ["ButtonUp", "ButtonDown", "ButtonLeft", "ButtonRight",
                "DUp", "DDown", "DLeft", "DRight", "L1", "L2", "R1", "R2", "Start", "Select",
                "LStickPress", "RStickPress"];
          let axis_names = ["LStickUp", "LStickDown", "LStickLeft", "LStickRight",
                "RStickUp", "RStickDown", "RStickLeft", "RStickRight"];
          
          // Show this until a gamepad is detected
          html_button.innerHTML = "No gamepad detected, try plugging in and interacting with it";
          
          // Listen for gamepad connection
          window.addEventListener("gamepadconnected", function(event) {
            gamepad_index = event.gamepad.index;
            // Read the config data if it's present
            // Show either "Configure" or "Re-configure" depending on if data has been saved
            if (gamepad_config = read_gamepad_config()) {
              html_button.innerHTML = "Re-configure gamepad";
            } else {
              html_button.innerHTML = "Configure gamepad";
            }
            
            // Add an event listener to configure the gamepad if the HTML button is pressed
            html_button.addEventListener("click", run_config);
            // Enter the main loop
            show_gamepad_status();
          });
          
          // Main loop showing the current buttons pressed and axis values
          function show_gamepad_status() {
            // Only do this if the gamepad is configured
            if (gamepad_config) {
              html_para.innerHTML = "";
              // Get the current gamepad state
              gamepad_object = navigator.getGamepads()[gamepad_index];
              // Show axis status
              for (let axis_name of axis_names) {
                html_para.innerHTML += `${axis_name} ${axis_value(axis_name, gamepad_object, gamepad_config)}<br>`;
              }
              // Show button status
              html_para.innerHTML += "<br>Pressed buttons<br>";
              for (let button_name of button_names) {
                if (is_button_pressed(button_name, gamepad_object, gamepad_config)) {
                  html_para.innerHTML += `${button_name}<br>`;
                }
              }
            }
            requestAnimationFrame(show_gamepad_status);
          }
        </script>
      </body>
    </html>
    

    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 from file:// to test it 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:

    Comments

    For me this solution doesn't work when testing the game locally. On Firefox, I get an "Uncaught TypeError: event.gamepad is undefined" log. I'm not sure what's different about the NG HTML environment that makes it work. I'm also unsure how I would implement this in Phaser 3; Could I use this configuration with Phaser's gamepad API?