GameMaker Gamepad assignments[HELP]

JDizzle383

Member
How would I go about assigning a gamepad to a specific player as follows without saying gamepad_get_device(0):

Gamepad 0 = Xinput
Gamepad 1 = Xinput
Gamepad 2 = no more Xinput connected, search for DirectInput and assign it to the empty player slot
Gamepad 3 = Xinput connected after the DirectInput was, so give this player an Xinput, and then search for more
Gamepad 4 = connected another DirectInput, so assign it to this player slot
Gamepad 5 = fourth Xinput is connected, assign it to the player 5 slot
Gamepad 6 = DirectInput
Gamepad 7 = DirectInput
Gamepad 8 = DirectInput
Gamepad 9 = DirectInput
Gamepad 10 = DirectInput
Gamepad 11 = DirectInput

To be clear I don't want to assign the numbers to the pads until they are connected, and the first one to be connected shows up as P1, the second as P2, third as P3 and so on regardless of the type of controller assigned to that specific slot. I tried assigning P1 to Gamepad 0 but then if I got to assign a direct input it gives me an error that slot 4 has not been declared due to it looking for a 5th player instead of the "next player in the connected controllers queue."
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Can't you just loop through all the connected controllers and assign them as they show up?
Code:
var _player_num = 0;
for (var i = 0; i < 12; i++;)
    {
    if gamepad_is_connected(i)
        {
        global.gp[_player_num] = true;
        ++_player_num;
        }
    }
 

JDizzle383

Member
Would that code go in the System Event? I am trying to use that event so that I don't have to constantly check for the gamepads.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Yes, you could indeed put it into the system event, and simply run it each time a gamepad is detected. The downside would be that it might rearrange the gamepad "slots" so a player that was previously using gamepad 2 would suddenly be using gamepad 3! Might be better doing something like this (This is actual code from my game Skein and works perfectly):


Code:
how_debug_message("Event = " + async_load[? "event_type"]);        // Debug cocde so you can see which event has been
show_debug_message("Pad = " + string(async_load[? "pad_index"]));   // triggered and the pad associated with it.

switch(async_load[? "event_type"])             // Parse the async_load map to see which event has been triggered
{
case "gamepad discovered":                     // A game pad has been discovered
    var pad = async_load[? "pad_index"];       // Get the pad index value from the async_load map
    gamepad_set_axis_deadzone(pad, 0.6);       // Set the "deadzone" for the axis
    gamepad_set_button_threshold(pad, 0.1);    // Set the "threshold" for the triggers
    if gamepad_get_device_count() > 1
        {
        if global.PadIndex[p1] == -4
            {
            global.PadIndex[p1] = pad;
            show_debug_message("Pad assigned to Player1: " + string(global.PadIndex[p1]));
            }
        else if global.PadIndex[p2] == -4
            {
            global.PadIndex[p2] = pad;
            show_debug_message("Pad assigned to Player2: " + string(global.PadIndex[p2]));
            }
        }
    else
        {
        if global.PadIndex[p1] == -4
            {
            global.PadIndex[p1] = pad;
            show_debug_message("Pad assigned to Player1: " + string(global.PadIndex[p1]));
            }
        }
    break;
case "gamepad lost":                           // Gamepad has been removed or otherwise disabled
    var pad = async_load[? "pad_index"];       // Get the pad index
    if pad == global.PadIndex[p1]
        {
        global.PadIndex[p1] = -4;
        }
    else if pad == global.PadIndex[p2]
        {
        global.PadIndex[p2] = -4;
        }
    break;
}

// Note: "p1" and "p2" are simply macros that map to 0 and 1 - it makes reading the array much easier :)
In this code I simply assign whichever pad is detected first to player 1, then the next to player 2. You could easily expand this to cover 4 or more pads though...
 

JDizzle383

Member
So I am a bit confused about the == -4 part of the code you have...

What is that there for if you only need 2 players?
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
-4 is simply the number I use to set the global array for player pad indexes when there is no gamepad assigned. That way I can do a check for "global.PadIndex[player] > -4" to see if that player has a gamepad assigned or not.
 

JDizzle383

Member
so theoretically that can be negative anything since a gamepad can't be a negative number. makes sense.

Also, which event do you have that code in?
 
Last edited:

JDizzle383

Member
I keep getting this error, and I have no idea why...

FATAL ERROR in
action number 1
of Async Event: System Event
for object obj_controller:


Variable obj_controller.p1(100024, -2147483648) not set before reading it.
at gml_Object_obj_controller_1_Other_75 (line 10) - if (global.PadIndex[p1] == -4)

I know It says I haven't "set" p1, but I copied the code you used so I don't know where to start fixing it if you said it works...
 

JDizzle383

Member
I put the macros in the default script called "macros" in GMS2. does it need to be called as a script at the beginning of the create event then for it to recognize the macros? I was under the impression that the macros script was just there to define the macros and was run without the need to call it over and over...

that didn't fix it when I called the macros script in the create event either. Either I am calling macros incorrectly, or assigning them incorrectly assuming that the code you provided is not the issue I set p1[0] and p2[1], but it did nothing for me. I also tried setting p1 = 0 and p2 = 1, but was given an improper syntax error upon trying to run the code the best thing I can come up with is I don't understand how macros are used...
 

JDizzle383

Member
so I tried using a switch statement coupled with the following in EVERY case, just to see if it would work.

Code:
case 0:
            if (!instance_exists(obj_hand))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand);
            }
            else if (instance_exists(obj_hand) && !instance_exists(obj_hand1))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand1);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && !instance_exists(obj_hand2))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand2);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && instance_exists(obj_hand2) && !instance_exists(obj_hand3))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand3);
            }
            break;
            case 1:
            if (!instance_exists(obj_hand))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand);
            }
            else if (instance_exists(obj_hand) && !instance_exists(obj_hand1))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand1);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && !instance_exists(obj_hand2))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand2);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && instance_exists(obj_hand2) && !instance_exists(obj_hand3))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand3);
            }
            break;
            case 2:
            if (!instance_exists(obj_hand))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand);
            }
            else if (instance_exists(obj_hand) && !instance_exists(obj_hand1))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand1);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && !instance_exists(obj_hand2))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand2);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && instance_exists(obj_hand2) && !instance_exists(obj_hand3))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand3);
            }
            break;
            case 3:
            if (!instance_exists(obj_hand))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand);
            }
            else if (instance_exists(obj_hand) && !instance_exists(obj_hand1))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand1);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && !instance_exists(obj_hand2))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand2);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && instance_exists(obj_hand2) && !instance_exists(obj_hand3))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand3);
            }
            break;
            case 4:
            if (!instance_exists(obj_hand))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand);
            }
            else if (instance_exists(obj_hand) && !instance_exists(obj_hand1))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand1);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && !instance_exists(obj_hand2))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand2);
            }
            else if (instance_exists(obj_hand) && instance_exists(obj_hand1) && instance_exists(obj_hand2) && !instance_exists(obj_hand3))
            {
                instance_create_depth(room_width/2,440,-2,obj_hand3);
            }
// stopped here to see if the DirectInput(case 4) would respond the way I needed it to before writing out the other DirectInputs
            break;
            default:
            break;
It seemed to create the objects just fine and assign the players correctly, but then it looks at the obj_hand and so on to assign the gamepad number to move it, so if it is created as Gamepad 0-3 it will look for the gamepad that the specific object is assigned to. to put it another way, there is a scr_move(device,deadzone) which assigns the pads based on 0 to 11(in order and only Xinput for the first four, then DirectInput for the last 8) rather than which one was plugged in first. as far as I can tell unplugging them causes no issue as it still searches for the one that was previously connected. scr_move is below for clarity:

Code:
///scr_move(device,deadzone);
dvc = argument0;
dzn = argument1;

move_up = keyboard_check(vk_up);
move_down = keyboard_check(vk_down);
move_left =keyboard_check(vk_left);
move_right =keyboard_check(vk_right);

xx = move_right-move_left;
yy = move_down-move_up;

if (gamepad_is_connected(dvc)){
gamepad_set_axis_deadzone(dvc,dzn)
xx=gamepad_axis_value(dvc,gp_axislh);
yy=gamepad_axis_value(dvc,gp_axislv);
}
These two scripts contradict each other, but I have not figured out how to use the "gamepad discovered" to look for them in the order they connect AND assign controls without saying the device == 0 or device == 4...

I feel like an idiot and the answer is probably staring me in the face, but I don't know what I need to do at this point since puting controls in the async system event is a bad idea....
 

JDizzle383

Member
the manual only shows example Drag and Drop code for the "Gamepad Get Connected" stuff in GMS2. I am trying to figure out the code to do so while assigning objects to the pad numbers, creating the objects as the pads connect, and destroying the object as it disconnects

This is as far as I got rewriting the code. I am unsure of how to say "if it doesn't exist anymore, disconnect the pad" though. ALSO, when assigning the pad, I want a player to appear, but all this does is assign a pad to a slot, right?
Code:
{
    for(i = 0; i < 12; i += 1) {
    var connected = gamepad_is_connected(i);
    if(connected == true)
    {
            global.gamepad_id = i;
            break;
    }
}
}
 
Last edited:

JDizzle383

Member
I have read that tech blog a number of times and can't quite wrap my head around how to make it assign OTHER OBJECTS to represent the player. I don't want a sub-image, I want a player object which changes based on which gamepad number it is. that means that the player objects ALL need a common variable that assigns the player's slot rather than saying "instance_create_depth(x,144,-2,obj_player)" since the obj_player would at that point be assigned to EVERYONE. I want the variable to assign the pad to an instance of the previously mentioned obj_hand ONLY if it were the first pad plugged in, then the second object, obj_hand1 should be assigned to the second gamepad. in the tech blog it assigns the SAME player object to EVERY PLAYER I plug in, which I am trying to avoid as I have 6 objects, all needing separate pads plugged in in order. the code in that tutorial text also creates the sprite at random positions, when I want it to create the sprite at room_width/4 but at a different 4th of the room and at room_height of 144 for each player aka above the selection portraits
 
Top