From 85e9ff0c0c762ada2e0c9f568c512d33a4b0b80b Mon Sep 17 00:00:00 2001 From: Terry Hearst Date: Mon, 13 Feb 2023 20:30:45 -0500 Subject: [PATCH 1/2] Cherry-pick gamepad support to MBG branch --- src/CameraController.hx | 25 ++++---- src/Gamepad.hx | 113 ++++++++++++++++++++++++++++++++++ src/Main.hx | 2 + src/Marble.hx | 11 +++- src/MarbleGame.hx | 12 +--- src/MarbleWorld.hx | 5 +- src/Settings.hx | 31 ++++++++++ src/gui/EndGameGui.hx | 2 + src/gui/EnterNameDlg.hx | 1 + src/gui/ExitGameDlg.hx | 3 + src/gui/GuiButton.hx | 18 +++++- src/gui/HelpCreditsGui.hx | 1 + src/gui/MainMenuGui.hx | 1 + src/gui/MessageBoxOkDlg.hx | 1 + src/gui/MessageBoxYesNoDlg.hx | 2 + src/gui/PlayMissionGui.hx | 4 ++ 16 files changed, 205 insertions(+), 27 deletions(-) create mode 100644 src/Gamepad.hx diff --git a/src/CameraController.hx b/src/CameraController.hx index cfcfaa39..7d6d3030 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,18 @@ 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); + if (Settings.gamepadSettings.invertYAxis) + cameraPitchDelta = -cameraPitchDelta; + nextCameraPitch += 0.75 * 5 * cameraPitchDelta * dt * Settings.gamepadSettings.cameraSensitivity; + var cameraYawDelta = (Key.isDown(Settings.controlsSettings.camRight) ? 1 : 0) + - (Key.isDown(Settings.controlsSettings.camLeft) ? 1 : 0) + + Gamepad.getAxis(Settings.gamepadSettings.cameraXAxis); + if (Settings.gamepadSettings.invertXAxis) + cameraYawDelta = -cameraYawDelta; + nextCameraYaw += 0.75 * 5 * cameraYawDelta * dt * Settings.gamepadSettings.cameraSensitivity; 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..42a9589d --- /dev/null +++ b/src/Gamepad.hx @@ -0,0 +1,113 @@ +package src; + +import hxd.Pad; +import src.Settings; + +class Gamepad { + public static var gamepad:Pad = Pad.createDummy(); + + public static function init() { + Pad.wait(onPad); + } + + public static function onPad(pad:Pad) { + pad.axisDeadZone = Settings.gamepadSettings.axisDeadzone; + pad.onDisconnect = function() { + gamepad = Pad.createDummy(); + } + gamepad = pad; + } + + 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) { + var buttonId = getId(button); + if (buttonId < 0 || buttonId > gamepad.buttons.length) + continue; + if (gamepad.isDown(buttonId)) + return true; + } + return false; + } + + public static function isPressed(buttons:Array) { + for (button in buttons) { + var buttonId = getId(button); + if (buttonId < 0 || buttonId > gamepad.buttons.length) + continue; + if (gamepad.isPressed(buttonId)) + return true; + } + return false; + } + + public static function isReleased(buttons:Array) { + for (button in buttons) { + var buttonId = getId(button); + if (buttonId < 0 || buttonId > gamepad.buttons.length) + continue; + if (gamepad.isReleased(buttonId)) + return true; + } + return false; + } + + public static function getAxis(axis:String) { + switch (axis) { + case "analogX": + return gamepad.xAxis; + case "analogY": + return gamepad.yAxis; + case "ranalogX": + return gamepad.rxAxis; + case "ranalogY": + return gamepad.ryAxis; + } + return 0.0; + } +} diff --git a/src/Main.hx b/src/Main.hx index 00be103b..2d548997 100644 --- a/src/Main.hx +++ b/src/Main.hx @@ -17,6 +17,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; @@ -58,6 +59,7 @@ class Main extends hxd.App { ResourceLoader.init(s2d, () -> { Settings.init(); + Gamepad.init(); AudioManager.init(); AudioManager.playShell(); marbleGame = new MarbleGame(s2d, s3d); diff --git a/src/Marble.hx b/src/Marble.hx index 5fbbfc1e..8c659410 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -51,6 +51,7 @@ import h3d.mat.Texture; import collision.CCDCollision.TraceInfo; import src.ResourceLoaderWorker; import src.InteriorObject; +import src.Gamepad; class Move { public var d:Vector; @@ -1428,6 +1429,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; } @@ -1440,10 +1443,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 881ecd2a..f6bea66c 100644 --- a/src/MarbleGame.hx +++ b/src/MarbleGame.hx @@ -16,6 +16,7 @@ import src.JSPlatform; import gui.Canvas; import src.Util; import src.ProfilerUI; +import src.Gamepad; @:publicFields class MarbleGame { @@ -161,17 +162,10 @@ class MarbleGame { if (!paused) { world.update(dt); } - if (Key.isPressed(Key.ESCAPE) && world.finishTime == null && world._ready) { - #if hl + if (((Key.isPressed(Key.ESCAPE) #if js && paused #end) || Gamepad.isPressed(["start"])) + && world.finishTime == null && world._ready) { paused = !paused; handlePauseGame(); - #end - #if js - if (paused) { - paused = false; - } - handlePauseGame(); - #end } } if (canvas != null) { diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 740a3779..3a3b900b 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -75,6 +75,7 @@ import src.Marble; import src.Resource; import src.ProfilerUI; import src.ResourceLoaderWorker; +import src.Gamepad; class MarbleWorld extends Scheduler { public var collisionWorld:CollisionWorld; @@ -910,7 +911,9 @@ class MarbleWorld extends Scheduler { } } - if (this.outOfBounds && this.finishTime == null && Key.isDown(Settings.controlsSettings.powerup)) { + if (this.outOfBounds + && this.finishTime == null + && (Key.isDown(Settings.controlsSettings.powerup) || Gamepad.isDown(Settings.gamepadSettings.powerup))) { this.clearSchedule(); this.restart(); return; diff --git a/src/Settings.hx b/src/Settings.hx index 7636fafb..2f3044ec 100644 --- a/src/Settings.hx +++ b/src/Settings.hx @@ -62,6 +62,19 @@ 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 axisDeadzone:Float; +} + class Settings { public static var highScores:Map> = []; @@ -107,6 +120,20 @@ class Settings { powerupButtonSize: 60, buttonJoystickMultiplier: 2.5 } + + public static var gamepadSettings:GamepadSettings = { + moveXAxis: "analogX", + moveYAxis: "analogY", + cameraXAxis: "ranalogX", + cameraYAxis: "ranalogY", + jump: ["A", "LT"], + powerup: ["B", "RT"], + cameraSensitivity: 1.0, + invertXAxis: false, + invertYAxis: false, + axisDeadzone: 0.15 + } + public static var progression = [24, 24, 52]; public static var highscoreName = ""; @@ -158,6 +185,7 @@ class Settings { options: optionsSettings, controls: controlsSettings, touch: touchSettings, + gamepad: gamepadSettings, progression: progression, highscoreName: highscoreName }; @@ -223,6 +251,9 @@ class Settings { if (json.touch != null) { touchSettings = json.touch; } + if (json.gamepad != null) { + gamepadSettings = json.gamepad; + } progression = json.progression; highscoreName = json.highscoreName; } else { diff --git a/src/gui/EndGameGui.hx b/src/gui/EndGameGui.hx index a11bbd47..0edff5dc 100644 --- a/src/gui/EndGameGui.hx +++ b/src/gui/EndGameGui.hx @@ -43,6 +43,7 @@ class EndGameGui extends GuiControl { continueButton.position = new Vector(333, 386); continueButton.extent = new Vector(113, 47); continueButton.accelerator = hxd.Key.ENTER; + continueButton.gamepadAccelerator = ["A"]; continueButton.pressedAction = continueFunc; var restartButton = new GuiButton(loadButtonImages("data/ui/endgame/replay")); @@ -50,6 +51,7 @@ class EndGameGui extends GuiControl { restartButton.vertSizing = Bottom; restartButton.position = new Vector(51, 388); restartButton.extent = new Vector(104, 48); + restartButton.gamepadAccelerator = ["B"]; restartButton.pressedAction = restartFunc; function setButtonStates(enabled:Bool) { diff --git a/src/gui/EnterNameDlg.hx b/src/gui/EnterNameDlg.hx index a38f9ac0..e66d4746 100644 --- a/src/gui/EnterNameDlg.hx +++ b/src/gui/EnterNameDlg.hx @@ -72,6 +72,7 @@ class EnterNameDlg extends GuiControl { okbutton.position = new Vector(163, 182); okbutton.extent = new Vector(78, 59); okbutton.accelerator = hxd.Key.ENTER; + okbutton.gamepadAccelerator = ["A"]; okbutton.pressedAction = (sender) -> { MarbleGame.canvas.popDialog(this); Settings.highscoreName = enterNameEdit.text.text; diff --git a/src/gui/ExitGameDlg.hx b/src/gui/ExitGameDlg.hx index 37f6448f..ae42e32f 100644 --- a/src/gui/ExitGameDlg.hx +++ b/src/gui/ExitGameDlg.hx @@ -48,6 +48,7 @@ class ExitGameDlg extends GuiControl { yesButton.horizSizing = Right; yesButton.pressedAction = yesFunc; yesButton.accelerator = hxd.Key.ENTER; + yesButton.gamepadAccelerator = ["A"]; var noButton = new GuiButton(loadButtonImages("data/ui/common/no")); noButton.position = new Vector(151, 107); @@ -55,6 +56,7 @@ class ExitGameDlg extends GuiControl { noButton.vertSizing = Bottom; noButton.horizSizing = Right; noButton.pressedAction = noFunc; + noButton.gamepadAccelerator = ["B"]; var restartButton = new GuiButton(loadButtonImages("data/ui/common/restart")); restartButton.position = new Vector(249, 107); @@ -62,6 +64,7 @@ class ExitGameDlg extends GuiControl { restartButton.vertSizing = Bottom; restartButton.horizSizing = Right; restartButton.pressedAction = restartFunc; + restartButton.gamepadAccelerator = ["X"]; dialogImg.addChild(exitGameText); dialogImg.addChild(yesButton); diff --git a/src/gui/GuiButton.hx b/src/gui/GuiButton.hx index 00669fe6..7bfe3b82 100644 --- a/src/gui/GuiButton.hx +++ b/src/gui/GuiButton.hx @@ -6,6 +6,7 @@ import gui.GuiControl.MouseState; import hxd.Window; import h2d.Tile; import src.ResourceLoader; +import src.Gamepad; enum ButtonType { Normal; @@ -28,6 +29,8 @@ class GuiButton extends GuiAnim { public var buttonSounds:Bool = true; public var accelerator:Int = 0; + public var gamepadAccelerator:Array = []; + public var acceleratorWasPressed = false; public function new(anim:Array) { super(anim); @@ -69,11 +72,20 @@ class GuiButton extends GuiAnim { } } } - if (!disabled && accelerator != 0 && hxd.Key.isReleased(accelerator)) { - if (this.pressedAction != null) { - this.pressedAction(this); + if (!disabled) { + if (acceleratorWasPressed && + (accelerator != 0 && hxd.Key.isReleased(accelerator)) || Gamepad.isReleased(gamepadAccelerator)) { + if (this.pressedAction != null) { + this.pressedAction(this); + } + } else if ((accelerator != 0 && hxd.Key.isPressed(accelerator)) || Gamepad.isPressed(gamepadAccelerator)) { + acceleratorWasPressed = true; } } + if (acceleratorWasPressed) { + if ((accelerator != 0 && hxd.Key.isReleased(accelerator)) || Gamepad.isReleased(gamepadAccelerator)) + acceleratorWasPressed = false; + } super.update(dt, mouseState); } diff --git a/src/gui/HelpCreditsGui.hx b/src/gui/HelpCreditsGui.hx index a408f252..f17a4847 100644 --- a/src/gui/HelpCreditsGui.hx +++ b/src/gui/HelpCreditsGui.hx @@ -71,6 +71,7 @@ class HelpCreditsGui extends GuiImage { homeButton.position = new Vector(278, 378); homeButton.extent = new Vector(79, 61); homeButton.accelerator = hxd.Key.ESCAPE; + homeButton.gamepadAccelerator = ["B"]; homeButton.pressedAction = (sender) -> { MarbleGame.canvas.setContent(new MainMenuGui()); } diff --git a/src/gui/MainMenuGui.hx b/src/gui/MainMenuGui.hx index d5335812..0cc14d98 100644 --- a/src/gui/MainMenuGui.hx +++ b/src/gui/MainMenuGui.hx @@ -47,6 +47,7 @@ class MainMenuGui extends GuiImage { var playButton = new GuiButton(loadButtonImages("data/ui/home/play")); playButton.position = new Vector(50, 113); playButton.extent = new Vector(270, 95); + playButton.gamepadAccelerator = ["A"]; playButton.pressedAction = (sender) -> { cast(this.parent, Canvas).setContent(new PlayMissionGui()); } diff --git a/src/gui/MessageBoxOkDlg.hx b/src/gui/MessageBoxOkDlg.hx index 37164050..01e20cc3 100644 --- a/src/gui/MessageBoxOkDlg.hx +++ b/src/gui/MessageBoxOkDlg.hx @@ -47,6 +47,7 @@ class MessageBoxOkDlg extends GuiControl { okButton.extent = new Vector(78, 59); okButton.vertSizing = Top; okButton.accelerator = hxd.Key.ENTER; + okButton.gamepadAccelerator = ["A"]; okButton.pressedAction = (sender) -> { MarbleGame.canvas.popDialog(this); } diff --git a/src/gui/MessageBoxYesNoDlg.hx b/src/gui/MessageBoxYesNoDlg.hx index d5a19e84..3f05edfe 100644 --- a/src/gui/MessageBoxYesNoDlg.hx +++ b/src/gui/MessageBoxYesNoDlg.hx @@ -47,6 +47,7 @@ class MessageBoxYesNoDlg extends GuiControl { yesButton.extent = new Vector(82, 47); yesButton.vertSizing = Top; yesButton.accelerator = hxd.Key.ENTER; + yesButton.gamepadAccelerator = ["A"]; yesButton.pressedAction = (sender) -> { MarbleGame.canvas.popDialog(this); yesFunc(); @@ -58,6 +59,7 @@ class MessageBoxYesNoDlg extends GuiControl { noButton.extent = new Vector(75, 47); noButton.vertSizing = Top; noButton.accelerator = hxd.Key.ESCAPE; + noButton.gamepadAccelerator = ["B"]; noButton.pressedAction = (sender) -> { MarbleGame.canvas.popDialog(this); noFunc(); diff --git a/src/gui/PlayMissionGui.hx b/src/gui/PlayMissionGui.hx index cb538fca..20d0120a 100644 --- a/src/gui/PlayMissionGui.hx +++ b/src/gui/PlayMissionGui.hx @@ -222,6 +222,7 @@ class PlayMissionGui extends GuiImage { var pmPlay = new GuiButton(loadButtonImages("data/ui/play/play")); pmPlay.position = new Vector(391, 257); pmPlay.extent = new Vector(121, 62); + pmPlay.gamepadAccelerator = ["A"]; pmPlay.pressedAction = (sender) -> { // Wacky hacks currentList[currentSelection].index = currentSelection; @@ -235,6 +236,7 @@ class PlayMissionGui extends GuiImage { var pmPrev = new GuiButton(loadButtonImages("data/ui/play/prev")); pmPrev.position = new Vector(321, 260); pmPrev.extent = new Vector(77, 58); + pmPrev.gamepadAccelerator = ["dpadLeft"]; pmPrev.pressedAction = (sender) -> { setSelectedFunc(currentSelection - 1); } @@ -243,6 +245,7 @@ class PlayMissionGui extends GuiImage { var pmNext = new GuiButton(loadButtonImages("data/ui/play/next")); pmNext.position = new Vector(507, 262); pmNext.extent = new Vector(75, 60); + pmNext.gamepadAccelerator = ["dpadRight"]; pmNext.pressedAction = (sender) -> { setSelectedFunc(currentSelection + 1); } @@ -280,6 +283,7 @@ class PlayMissionGui extends GuiImage { var pmBack = new GuiButton(loadButtonImages("data/ui/play/back")); pmBack.position = new Vector(102, 260); pmBack.extent = new Vector(79, 61); + pmBack.gamepadAccelerator = ["B"]; pmBack.pressedAction = (sender) -> { cast(this.parent, Canvas).setContent(new MainMenuGui()); }; From c9a1843edd9ccf24824a633e6cc53f51a5d79006 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:47:06 +0530 Subject: [PATCH 2/2] fix marble bounces --- src/Marble.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Marble.hx b/src/Marble.hx index 8c659410..179e33e9 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -137,6 +137,7 @@ class Marble extends GameObject { var _airAccel:Float = 5; var _maxDotSlide = 0.5; var _minBounceVel:Float = 0.1; + var _minBounceSpeed:Float = 3; var _minTrailVel:Float = 10; var _bounceKineticFriction = 0.2; var minVelocityBounceSoft = 2.5; @@ -636,7 +637,7 @@ class Marble extends GameObject { } function bounceEmitter(speed:Float, normal:Vector) { - if (this.bounceEmitDelay == 0 && this._minBounceVel <= speed) { + if (this.bounceEmitDelay == 0 && this._minBounceSpeed <= speed) { this.level.particleManager.createEmitter(bounceParticleOptions, this.bounceEmitterData, this.getAbsPos().getPosition()); this.bounceEmitDelay = 0.3; }