From db435f4f05bd5315f0cc0d0d1adc14e3f039d8d1 Mon Sep 17 00:00:00 2001 From: Terry Hearst Date: Sat, 11 Feb 2023 01:28:49 -0500 Subject: [PATCH] Add basic gamepad support --- src/CameraController.hx | 21 ++++------ src/Gamepad.hx | 92 +++++++++++++++++++++++++++++++++++++++++ src/Main.hx | 2 + src/Marble.hx | 11 ++++- src/MarbleGame.hx | 4 +- src/MarbleWorld.hx | 14 +++++-- src/Settings.hx | 32 ++++++++++++++ 7 files changed, 158 insertions(+), 18 deletions(-) create mode 100644 src/Gamepad.hx diff --git a/src/CameraController.hx b/src/CameraController.hx index cfcfaa39..8ecf8cb4 100644 --- a/src/CameraController.hx +++ b/src/CameraController.hx @@ -26,6 +26,7 @@ import h3d.Camera; import h3d.Vector; import hxsl.Types.Matrix; import h3d.scene.Scene; +import src.Gamepad; enum CameraMode { FreeOrbit; @@ -160,18 +161,14 @@ class CameraController extends Object { var lerpt = hxd.Math.min(1, 1 - Math.pow(0.6, dt * 600)); - if (Key.isDown(Settings.controlsSettings.camForward)) { - nextCameraPitch += 0.75 * 5 * dt; - } - if (Key.isDown(Settings.controlsSettings.camBackward)) { - nextCameraPitch -= 0.75 * 5 * dt; - } - if (Key.isDown(Settings.controlsSettings.camLeft)) { - nextCameraYaw -= 0.75 * 5 * dt; - } - if (Key.isDown(Settings.controlsSettings.camRight)) { - nextCameraYaw += 0.75 * 5 * dt; - } + var cameraPitchDelta = (Key.isDown(Settings.controlsSettings.camBackward) ? 1 : 0) + - (Key.isDown(Settings.controlsSettings.camForward) ? 1 : 0) + - Gamepad.getAxis(Settings.gamepadSettings.cameraYAxis); + nextCameraPitch += 0.75 * 5 * cameraPitchDelta * dt; + var cameraYawDelta = (Key.isDown(Settings.controlsSettings.camRight) ? 1 : 0) + - (Key.isDown(Settings.controlsSettings.camLeft) ? 1 : 0) + + Gamepad.getAxis(Settings.gamepadSettings.cameraXAxis); + nextCameraYaw += 0.75 * 5 * cameraYawDelta * dt; nextCameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, nextCameraPitch)); diff --git a/src/Gamepad.hx b/src/Gamepad.hx new file mode 100644 index 00000000..88661a72 --- /dev/null +++ b/src/Gamepad.hx @@ -0,0 +1,92 @@ +package src; + +import hxd.Pad; + +class Gamepad { + public static var gamepad:Pad = Pad.createDummy(); + + public static function init() { + Pad.wait(onPad); + } + + public static function onPad(pad:Pad) { + gamepad = pad; + pad.onDisconnect = function() { + gamepad = Pad.createDummy(); + } + } + + public static function getId(name:String) { + switch (name) { + case "start": + return gamepad.config.start; + case "ranalogY": + return gamepad.config.ranalogY; + case "ranalogX": + return gamepad.config.ranalogX; + case "ranalogClick": + return gamepad.config.ranalogClick; + case "dpadUp": + return gamepad.config.dpadUp; + case "dpadRight": + return gamepad.config.dpadRight; + case "dpadLeft": + return gamepad.config.dpadLeft; + case "dpadDown": + return gamepad.config.dpadDown; + case "back": + return gamepad.config.back; + case "analogY": + return gamepad.config.analogY; + case "analogX": + return gamepad.config.analogX; + case "analogClick": + return gamepad.config.analogClick; + case "Y": + return gamepad.config.Y; + case "X": + return gamepad.config.X; + case "RT": + return gamepad.config.RT; + case "RB": + return gamepad.config.RB; + case "LT": + return gamepad.config.LT; + case "LB": + return gamepad.config.LB; + case "B": + return gamepad.config.B; + case "A": + return gamepad.config.A; + } + return -1; + } + + public static function isDown(buttons:Array) { + for (button in buttons) { + if (gamepad.isDown(getId(button))) + return true; + } + return false; + } + + public static function isPressed(buttons:Array) { + for (button in buttons) { + if (gamepad.isPressed(getId(button))) + return true; + } + return false; + } + + public static function isReleased(buttons:Array) { + for (button in buttons) { + if (gamepad.isReleased(getId(button))) + return true; + } + return false; + } + + public static function getAxis(axis:String) { + return gamepad.values[getId(axis)]; + } +} \ No newline at end of file diff --git a/src/Main.hx b/src/Main.hx index 9ea4e95f..ca62dbc7 100644 --- a/src/Main.hx +++ b/src/Main.hx @@ -18,6 +18,7 @@ import hxd.res.DefaultFont; import h2d.Text; import h3d.Vector; import src.ProfilerUI; +import src.Gamepad; class Main extends hxd.App { var marbleGame:MarbleGame; @@ -67,6 +68,7 @@ class Main extends hxd.App { try { Settings.init(); + Gamepad.init(); ResourceLoader.init(s2d, () -> { AudioManager.init(); AudioManager.playShell(); diff --git a/src/Marble.hx b/src/Marble.hx index 6141779d..06e722f8 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -61,6 +61,7 @@ import collision.CCDCollision.TraceInfo; import src.ResourceLoaderWorker; import src.InteriorObject; import src.Console; +import src.Gamepad; class Move { public var d:Vector; @@ -1686,6 +1687,8 @@ class Marble extends GameObject { var move = new Move(); move.d = new Vector(); if (this.controllable && this.mode != Finish && !MarbleGame.instance.paused && !this.level.isWatching) { + move.d.x = -Gamepad.getAxis(Settings.gamepadSettings.moveYAxis); + move.d.y = -Gamepad.getAxis(Settings.gamepadSettings.moveXAxis); if (Key.isDown(Settings.controlsSettings.forward)) { move.d.x -= 1; } @@ -1698,10 +1701,14 @@ class Marble extends GameObject { if (Key.isDown(Settings.controlsSettings.right)) { move.d.y -= 1; } - if (Key.isDown(Settings.controlsSettings.jump) || MarbleGame.instance.touchInput.jumpButton.pressed) { + if (Key.isDown(Settings.controlsSettings.jump) + || MarbleGame.instance.touchInput.jumpButton.pressed + || Gamepad.isDown(Settings.gamepadSettings.jump)) { move.jump = true; } - if (Util.isTouchDevice() ? MarbleGame.instance.touchInput.powerupButton.pressed : Key.isDown(Settings.controlsSettings.powerup)) { + if (Key.isDown(Settings.controlsSettings.powerup) + || (Util.isTouchDevice() && MarbleGame.instance.touchInput.powerupButton.pressed) + || Gamepad.isDown(Settings.gamepadSettings.powerup)) { move.powerup = true; } if (MarbleGame.instance.touchInput.movementInput.pressed) { diff --git a/src/MarbleGame.hx b/src/MarbleGame.hx index 15d118f8..fb10e067 100644 --- a/src/MarbleGame.hx +++ b/src/MarbleGame.hx @@ -25,6 +25,7 @@ import src.ProfilerUI; import src.Settings; import src.Console; import src.Debug; +import src.Gamepad; @:publicFields class MarbleGame { @@ -182,7 +183,8 @@ class MarbleGame { if (!paused) { world.update(dt * Debug.timeScale); } - if (Key.isPressed(Key.ESCAPE) && world.finishTime == null && world._ready) { + if ((Key.isPressed(Key.ESCAPE) || Gamepad.isPressed(["start"])) + && world.finishTime == null && world._ready) { #if hl paused = !paused; handlePauseGame(); diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 2ef1b552..ffc469e6 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -94,6 +94,7 @@ import src.ProfilerUI; import src.ResourceLoaderWorker; import haxe.io.Path; import src.Console; +import src.Gamepad; class MarbleWorld extends Scheduler { public var collisionWorld:CollisionWorld; @@ -1183,12 +1184,15 @@ class MarbleWorld extends Scheduler { ProfilerUI.measure("updateTimer"); this.updateTimer(dt); - if ((Key.isPressed(Settings.controlsSettings.respawn)) && this.finishTime == null) { + if ((Key.isPressed(Settings.controlsSettings.respawn) || Gamepad.isPressed(Settings.gamepadSettings.respawn)) + && this.finishTime == null) { performRestart(); return; } - if ((Key.isDown(Settings.controlsSettings.respawn) || MarbleGame.instance.touchInput.restartButton.pressed) + if ((Key.isDown(Settings.controlsSettings.respawn) + || MarbleGame.instance.touchInput.restartButton.pressed + || Gamepad.isDown(Settings.gamepadSettings.respawn)) && !this.isWatching && this.finishTime == null) { if (timeState.timeSinceLoad - this.respawnPressedTime > 1.5) { @@ -1202,6 +1206,7 @@ class MarbleWorld extends Scheduler { if (Key.isPressed(Settings.controlsSettings.blast) || (MarbleGame.instance.touchInput.blastbutton.pressed) + || Gamepad.isPressed(Settings.gamepadSettings.blast) && !this.isWatching && this.game == "ultra") { this.marble.useBlast(); @@ -1245,7 +1250,10 @@ class MarbleWorld extends Scheduler { ProfilerUI.measure("updateAudio"); AudioManager.update(this.scene); - if (this.outOfBounds && this.finishTime == null && Key.isDown(Settings.controlsSettings.powerup) && !this.isWatching) { + if (this.outOfBounds + && this.finishTime == null + && (Key.isDown(Settings.controlsSettings.powerup) || Gamepad.isDown(Settings.gamepadSettings.powerup)) + && !this.isWatching) { this.restart(); return; } diff --git a/src/Settings.hx b/src/Settings.hx index 4e68c950..70022eab 100644 --- a/src/Settings.hx +++ b/src/Settings.hx @@ -75,6 +75,20 @@ typedef TouchSettings = { var buttonJoystickMultiplier:Float; } +typedef GamepadSettings = { + var moveXAxis:String; + var moveYAxis:String; + var cameraXAxis:String; + var cameraYAxis:String; + var jump:Array; + var powerup:Array; + var cameraSensitivity:Float; + var invertXAxis:Bool; + var invertYAxis:Bool; + var respawn:Array; + var blast:Array; +} + typedef PlayStatistics = { var oobs:Int; var respawns:Int; @@ -141,6 +155,20 @@ class Settings { buttonJoystickMultiplier: 2.5 } + public static var gamepadSettings:GamepadSettings = { + moveXAxis: "analogX", + moveYAxis: "analogY", + cameraXAxis: "ranalogX", + cameraYAxis: "ranalogY", + jump: ["A", "LT"], + powerup: ["B", "RT"], + cameraSensitivity: 0.6, + invertXAxis: false, + invertYAxis: false, + respawn: ["back"], + blast: ["X", "LB", "RB"] + } + public static var playStatistics:PlayStatistics = { oobs: 0, respawns: 0, @@ -200,6 +228,7 @@ class Settings { options: optionsSettings, controls: controlsSettings, touch: touchSettings, + gamepad: gamepadSettings, stats: playStatistics, highscoreName: highscoreName, marbleIndex: optionsSettings.marbleIndex, @@ -310,6 +339,9 @@ class Settings { touchSettings.blastButtonPos = [300, 240]; touchSettings.blastButtonSize = 60; } + if (json.gamepad != null) { + gamepadSettings = json.gamepad; + } if (json.stats != null) { playStatistics = json.stats; }