From 33e2c241a379cac013fccc2f2ec258ff7ac5fb9b Mon Sep 17 00:00:00 2001 From: Matt Thorson Date: Thu, 7 May 2020 13:48:03 -0700 Subject: [PATCH] Support for multiple gamepads --- src/Game.bf | 37 ++++++++++++++++++++++++++----------- src/Input/VirtualAxis.bf | 24 ++++++++++++++---------- src/Input/VirtualButton.bf | 24 +++++++++++++++++------- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/Game.bf b/src/Game.bf index 2978107..7689698 100644 --- a/src/Game.bf +++ b/src/Game.bf @@ -30,10 +30,10 @@ namespace Strawberry private SDL.Window* window; private SDL.Surface* screen; private bool* keyboardState; - private SDL.SDL_GameController* gamepad; + private SDL.SDL_GameController*[] gamepads; private int32 updateCounter; - public this(String windowTitle, int32 width, int32 height) + public this(String windowTitle, int32 width, int32 height, int gamepadLimit = 1) : base() { Game = this; @@ -51,7 +51,10 @@ namespace Strawberry Path.GetDirectoryPath(exePath, exeDir); Directory.SetCurrentDirectory(exeDir); - SDL.Init(.Video | .Events | .Audio | .GameController); + SDL.InitFlag init = .Video | .Events | .Audio; + if (gamepadLimit > 0) + init |= .GameController; + SDL.Init(init); SDL.EventState(.JoyAxisMotion, .Disable); SDL.EventState(.JoyBallMotion, .Disable); SDL.EventState(.JoyHatMotion, .Disable); @@ -68,7 +71,9 @@ namespace Strawberry SDLTTF.Init(); - gamepad = SDL.GameControllerOpen(0); + this.gamepads = new SDL.SDL_GameController*[gamepadLimit]; + for (let i < this.gamepads.Count) + this.gamepads[i] = SDL.GameControllerOpen((int32)i); } public ~this() @@ -79,8 +84,16 @@ namespace Strawberry if (switchToScene != scene && switchToScene != null) delete switchToScene; - delete VirtualInputs; + { + let list = scope List(); + for (var i in VirtualInputs) + list.Add(i); + for (var i in list) + delete i; + delete VirtualInputs; + } + delete gamepads; Game = null; } @@ -94,7 +107,9 @@ namespace Strawberry { SDL.Event event; if (SDL.PollEvent(out event) != 0 && event.type == .Quit) + { return; + } // Fixed 60 Hz update double msPerTick = 1000 / 60.0; @@ -189,19 +204,19 @@ namespace Strawberry return keyboardState[(int)key]; } - public bool GamepadButtonCheck(SDL.SDL_GameControllerButton button) + public bool GamepadButtonCheck(int gamepadID, SDL.SDL_GameControllerButton button) { - if (gamepad == null) + if (gamepads == null) return false; - return SDL.GameControllerGetButton(gamepad, button) == 1; + return SDL.GameControllerGetButton(gamepads[gamepadID], button) == 1; } - public float GamepadAxisCheck(SDL.SDL_GameControllerAxis axis) + public float GamepadAxisCheck(int gamepadID, SDL.SDL_GameControllerAxis axis) { - if (gamepad == null) + if (gamepads == null) return 0; - let val = SDL.GameControllerGetAxis(gamepad, axis); + let val = SDL.GameControllerGetAxis(gamepads[gamepadID], axis); if (val == 0) return 0; else if (val > 0) diff --git a/src/Input/VirtualAxis.bf b/src/Input/VirtualAxis.bf index 657681c..591fe0d 100644 --- a/src/Input/VirtualAxis.bf +++ b/src/Input/VirtualAxis.bf @@ -95,15 +95,15 @@ namespace Strawberry return this; } - public VirtualAxis AddButtons(SDL.SDL_GameControllerButton negativeButton, SDL.SDL_GameControllerButton positiveButton, OverlapBehaviors overlapBehavior = .TakeNewer) + public VirtualAxis AddButtons(int gamepadID, SDL.SDL_GameControllerButton negativeButton, SDL.SDL_GameControllerButton positiveButton, OverlapBehaviors overlapBehavior = .TakeNewer) { - nodes.Add(new GamepadButtons(negativeButton, positiveButton, overlapBehavior)); + nodes.Add(new GamepadButtons(gamepadID, negativeButton, positiveButton, overlapBehavior)); return this; } - public VirtualAxis AddAxis(SDL.SDL_GameControllerAxis axis, float deadzone) + public VirtualAxis AddAxis(int gamepadID, SDL.SDL_GameControllerAxis axis, float deadzone) { - nodes.Add(new GamepadAxis(axis, deadzone)); + nodes.Add(new GamepadAxis(gamepadID, axis, deadzone)); return this; } @@ -204,6 +204,7 @@ namespace Strawberry private class GamepadButtons : Node { + public int GamepadID; public OverlapBehaviors OverlapBehavior; public SDL.SDL_GameControllerButton NegativeButton; public SDL.SDL_GameControllerButton PositiveButton; @@ -211,8 +212,9 @@ namespace Strawberry private float value; private bool turned; - public this(SDL.SDL_GameControllerButton negativeButton, SDL.SDL_GameControllerButton positiveButton, OverlapBehaviors overlapBehavior = .TakeNewer) + public this(int gamepadID, SDL.SDL_GameControllerButton negativeButton, SDL.SDL_GameControllerButton positiveButton, OverlapBehaviors overlapBehavior = .TakeNewer) { + GamepadID = gamepadID; NegativeButton = negativeButton; PositiveButton = positiveButton; OverlapBehavior = overlapBehavior; @@ -220,9 +222,9 @@ namespace Strawberry public override void Update() { - if (Game.GamepadButtonCheck(PositiveButton)) + if (Game.GamepadButtonCheck(GamepadID, PositiveButton)) { - if (Game.GamepadButtonCheck(NegativeButton)) + if (Game.GamepadButtonCheck(GamepadID, NegativeButton)) { switch (OverlapBehavior) { @@ -249,7 +251,7 @@ namespace Strawberry value = 1; } } - else if (Game.GamepadButtonCheck(NegativeButton)) + else if (Game.GamepadButtonCheck(GamepadID, NegativeButton)) { turned = false; value = -1; @@ -272,11 +274,13 @@ namespace Strawberry private class GamepadAxis : Node { + public int GamepadID; public SDL.SDL_GameControllerAxis Axis; public float Deadzone; - public this(SDL.SDL_GameControllerAxis axis, float deadzone) + public this(int gamepadID, SDL.SDL_GameControllerAxis axis, float deadzone) { + GamepadID = gamepadID; Axis = axis; Deadzone = deadzone; } @@ -285,7 +289,7 @@ namespace Strawberry { get { - let val = Game.GamepadAxisCheck(Axis); + let val = Game.GamepadAxisCheck(GamepadID, Axis); if (Math.Abs(val) < Deadzone) return 0; else diff --git a/src/Input/VirtualButton.bf b/src/Input/VirtualButton.bf index f598829..a1bbe40 100644 --- a/src/Input/VirtualButton.bf +++ b/src/Input/VirtualButton.bf @@ -91,9 +91,15 @@ namespace Strawberry return this; } - public VirtualButton AddButton(SDL.SDL_GameControllerButton button) + public VirtualButton AddButton(int gamepadID, SDL.SDL_GameControllerButton button) { - nodes.Add(new GamepadButton(button)); + nodes.Add(new GamepadButton(gamepadID, button)); + return this; + } + + public VirtualButton AddAxis(int gamepadID, SDL.SDL_GameControllerAxis axis, float threshold, ThresholdConditions condition = .GreaterThan) + { + nodes.Add(new GamepadAxis(gamepadID, axis, threshold, condition)); return this; } @@ -143,10 +149,12 @@ namespace Strawberry private class GamepadButton : Node { + public int GamepadID; public SDL.SDL_GameControllerButton Button; - public this(SDL.SDL_GameControllerButton button) + public this(int gamepadID, SDL.SDL_GameControllerButton button) { + GamepadID = gamepadID; Button = button; } @@ -154,19 +162,21 @@ namespace Strawberry { get { - return Game.GamepadButtonCheck(Button); + return Game.GamepadButtonCheck(GamepadID, Button); } } } private class GamepadAxis : Node { + public int GamepadID; public SDL.SDL_GameControllerAxis Axis; public float Threshold; public ThresholdConditions Condition; - public this(SDL.SDL_GameControllerAxis axis, float threshold, ThresholdConditions condition = .GreaterThan) + public this(int gamepadID, SDL.SDL_GameControllerAxis axis, float threshold, ThresholdConditions condition = .GreaterThan) { + GamepadID = gamepadID; Axis = axis; Threshold = threshold; Condition = condition; @@ -177,9 +187,9 @@ namespace Strawberry get { if (Condition == .GreaterThan) - return Game.GamepadAxisCheck(Axis) >= Threshold; + return Game.GamepadAxisCheck(GamepadID, Axis) >= Threshold; else - return Game.GamepadAxisCheck(Axis) <= Threshold; + return Game.GamepadAxisCheck(GamepadID, Axis) <= Threshold; } } }