Support for multiple gamepads

This commit is contained in:
Matt Thorson 2020-05-07 13:48:03 -07:00
parent da320af175
commit 33e2c241a3
3 changed files with 57 additions and 28 deletions

View File

@ -30,10 +30,10 @@ namespace Strawberry
private SDL.Window* window; private SDL.Window* window;
private SDL.Surface* screen; private SDL.Surface* screen;
private bool* keyboardState; private bool* keyboardState;
private SDL.SDL_GameController* gamepad; private SDL.SDL_GameController*[] gamepads;
private int32 updateCounter; private int32 updateCounter;
public this(String windowTitle, int32 width, int32 height) public this(String windowTitle, int32 width, int32 height, int gamepadLimit = 1)
: base() : base()
{ {
Game = this; Game = this;
@ -51,7 +51,10 @@ namespace Strawberry
Path.GetDirectoryPath(exePath, exeDir); Path.GetDirectoryPath(exePath, exeDir);
Directory.SetCurrentDirectory(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(.JoyAxisMotion, .Disable);
SDL.EventState(.JoyBallMotion, .Disable); SDL.EventState(.JoyBallMotion, .Disable);
SDL.EventState(.JoyHatMotion, .Disable); SDL.EventState(.JoyHatMotion, .Disable);
@ -68,7 +71,9 @@ namespace Strawberry
SDLTTF.Init(); 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() public ~this()
@ -79,8 +84,16 @@ namespace Strawberry
if (switchToScene != scene && switchToScene != null) if (switchToScene != scene && switchToScene != null)
delete switchToScene; delete switchToScene;
delete VirtualInputs; {
let list = scope List<VirtualInput>();
for (var i in VirtualInputs)
list.Add(i);
for (var i in list)
delete i;
delete VirtualInputs;
}
delete gamepads;
Game = null; Game = null;
} }
@ -94,7 +107,9 @@ namespace Strawberry
{ {
SDL.Event event; SDL.Event event;
if (SDL.PollEvent(out event) != 0 && event.type == .Quit) if (SDL.PollEvent(out event) != 0 && event.type == .Quit)
{
return; return;
}
// Fixed 60 Hz update // Fixed 60 Hz update
double msPerTick = 1000 / 60.0; double msPerTick = 1000 / 60.0;
@ -189,19 +204,19 @@ namespace Strawberry
return keyboardState[(int)key]; 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 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; return 0;
let val = SDL.GameControllerGetAxis(gamepad, axis); let val = SDL.GameControllerGetAxis(gamepads[gamepadID], axis);
if (val == 0) if (val == 0)
return 0; return 0;
else if (val > 0) else if (val > 0)

View File

@ -95,15 +95,15 @@ namespace Strawberry
return this; 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; 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; return this;
} }
@ -204,6 +204,7 @@ namespace Strawberry
private class GamepadButtons : Node private class GamepadButtons : Node
{ {
public int GamepadID;
public OverlapBehaviors OverlapBehavior; public OverlapBehaviors OverlapBehavior;
public SDL.SDL_GameControllerButton NegativeButton; public SDL.SDL_GameControllerButton NegativeButton;
public SDL.SDL_GameControllerButton PositiveButton; public SDL.SDL_GameControllerButton PositiveButton;
@ -211,8 +212,9 @@ namespace Strawberry
private float value; private float value;
private bool turned; 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; NegativeButton = negativeButton;
PositiveButton = positiveButton; PositiveButton = positiveButton;
OverlapBehavior = overlapBehavior; OverlapBehavior = overlapBehavior;
@ -220,9 +222,9 @@ namespace Strawberry
public override void Update() public override void Update()
{ {
if (Game.GamepadButtonCheck(PositiveButton)) if (Game.GamepadButtonCheck(GamepadID, PositiveButton))
{ {
if (Game.GamepadButtonCheck(NegativeButton)) if (Game.GamepadButtonCheck(GamepadID, NegativeButton))
{ {
switch (OverlapBehavior) switch (OverlapBehavior)
{ {
@ -249,7 +251,7 @@ namespace Strawberry
value = 1; value = 1;
} }
} }
else if (Game.GamepadButtonCheck(NegativeButton)) else if (Game.GamepadButtonCheck(GamepadID, NegativeButton))
{ {
turned = false; turned = false;
value = -1; value = -1;
@ -272,11 +274,13 @@ namespace Strawberry
private class GamepadAxis : Node private class GamepadAxis : Node
{ {
public int GamepadID;
public SDL.SDL_GameControllerAxis Axis; public SDL.SDL_GameControllerAxis Axis;
public float Deadzone; 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; Axis = axis;
Deadzone = deadzone; Deadzone = deadzone;
} }
@ -285,7 +289,7 @@ namespace Strawberry
{ {
get get
{ {
let val = Game.GamepadAxisCheck(Axis); let val = Game.GamepadAxisCheck(GamepadID, Axis);
if (Math.Abs(val) < Deadzone) if (Math.Abs(val) < Deadzone)
return 0; return 0;
else else

View File

@ -91,9 +91,15 @@ namespace Strawberry
return this; 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; return this;
} }
@ -143,10 +149,12 @@ namespace Strawberry
private class GamepadButton : Node private class GamepadButton : Node
{ {
public int GamepadID;
public SDL.SDL_GameControllerButton Button; public SDL.SDL_GameControllerButton Button;
public this(SDL.SDL_GameControllerButton button) public this(int gamepadID, SDL.SDL_GameControllerButton button)
{ {
GamepadID = gamepadID;
Button = button; Button = button;
} }
@ -154,19 +162,21 @@ namespace Strawberry
{ {
get get
{ {
return Game.GamepadButtonCheck(Button); return Game.GamepadButtonCheck(GamepadID, Button);
} }
} }
} }
private class GamepadAxis : Node private class GamepadAxis : Node
{ {
public int GamepadID;
public SDL.SDL_GameControllerAxis Axis; public SDL.SDL_GameControllerAxis Axis;
public float Threshold; public float Threshold;
public ThresholdConditions Condition; 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; Axis = axis;
Threshold = threshold; Threshold = threshold;
Condition = condition; Condition = condition;
@ -177,9 +187,9 @@ namespace Strawberry
get get
{ {
if (Condition == .GreaterThan) if (Condition == .GreaterThan)
return Game.GamepadAxisCheck(Axis) >= Threshold; return Game.GamepadAxisCheck(GamepadID, Axis) >= Threshold;
else else
return Game.GamepadAxisCheck(Axis) <= Threshold; return Game.GamepadAxisCheck(GamepadID, Axis) <= Threshold;
} }
} }
} }