GM8.1: Pause/unpause with joystick-It's Adequate!

S

ScaryPotato

Guest
Hey guys, nice to see a new/active forum after so long!

I've been working on trying to include gamepade functionality to my pause code, but nothing seems to work. The code below works fine for the keyboard, and will let me pause with the gamepad (but it doesn't unpause using the gamepad).

I tried to include some commands to simulate keyboard buttons being pressed/released (the cancelled-out NEW STUFF), but when that is activated, it starts affecting how the keyboard functions work (it initiates the pause command each time you press 'P' without unpausing)

Any suggestions or ideas on how to get this working would be awesome as I'm not sure what else I could try!


Code:
if joystick_check_button(1,8) and pause=0//the Start Button on the XBox controller
{
    keyboard_key_press(ord('P'));//simulates the 'P' key being pressed
    pause=1;
}



if (keyboard_check_pressed(ord('P'))) //if key is currently pressed   
{       
    io_clear();//clears keyboard and mouse states       
    pause=1; //variable to control actions when game is paused         
    sound_loop(PauseLoop); //Pause BGM loop
    instance_create(view_xview,view_yview,PauseScreenObj); //image that covers the viewport
    instance_create(view_xview,view_yview,PauseTextObj);//'Paused' text that goes ontop of PauseScreenObj
             
    with PauseScreenObj
    {image_alpha=0.5;}//makes it so you can see the state of the game when you paused it
           
    while (pause==1)   
    {           
            screen_redraw(); //if there are any Draw Events, this should keep them on-screen         
            io_handle();//updates keyboard and mouse states
           
            //NEW STUFF
            //if joystick_exists(1)//to make sure the following commands only take place if the gamepad is used
            //{
               //if !joystick_check_button(1,8) and pause=1//if the gamepad button isn't pressed and 'pause' is a certail value
                //{
                    //keyboard_key_release(ord('P'));//simulates the 'P' key being released
                    //pause=2;
                   
                    //if joystick_check_button(1,8) and pause=2//changing the 'pause' variable to allow the command to stop
                    //{pause=3;}   
                //}
            //}
            //END OF NEW STUFF
           
            //if pause>0         
            //{                   
                    if keyboard_check_pressed(ord('P'))||pause=3//if key is pressed OR if 'pause' variable is the right value         
                    {
                        sound_stop(PauseLoop);//stop the Pause BGM
                        ss=SoundObj;//variable for Game BGM
                        if (ss != noone)//check that there is a song to play
                        {sound_loop(ss.Song);}//loops the song
                                     
                        pause=0;                               
                        with (PauseScreenObj) instance_destroy();//get rid of blackened screen   
                        with (PauseTextObj) instance_destroy(); //get rif of 'Paused' text         
                    }                   
            //}
    }
}
 
R

rui.rosario

Guest
I haven't used GM 8.1 in a looong time, and I never used it with joysticks, but I think I can give my 2 cents.

First, what I would suggest was to abstract away the actual keys pressed (both keyboard and joystick), to something like
Code:
/// key_pause script
return (keyboard_check_pressed(ord('P')) || joystick_check_button(1,8))
This would allow you to simplify the code that used this, like
Code:
/* instead of all this
if joystick_check_button(1,8) and pause=0//the Start Button on the XBox controller
{
    keyboard_key_press(ord('P'));//simulates the 'P' key being pressed
    pause=1;
}



if (keyboard_check_pressed(ord('P'))) //if key is currently pressed   
{   
*/
if (key_pause() && pause == 0) {
Also, I would avoid using the io_clear() with the while loop and the screen_redraw.
I would instead store the currently draw screen in a surface, drawing that as a background and deactivating all objects except newly created pause menu ones. This would correctly process input every time since you wouldn't need to explicitly call io_clear (which I would bet is the culprit, or at least it is the function I would blame first) and screen_redraw. Other than that, I really can't say anything else since I don't remember GM 8.1 that well.
 
S

Snail Man

Guest
Not confirmed as I don't have GM8.1 on hand, but I suspect that io_handle might not work with joystick input. I'd investigate this if I were you. What I've done for pause screens in the past is make a separate room, then when you press pause, set room_persistant to true, effectively saving the state of the current room, and also set an alarm for one step, then go to the pause room. When you return from the pause room, the alarm event will trigger, setting room_persistant to false. I like this method because it avoids loops, and works in GM:STUDIO as well
 
S

ScaryPotato

Guest
Hey guys, thanks a lot for the replies! I was kind of suspect about the whole io_clear() and io_handle() stuff, when I was trying out different things with that bit of code, so you're probably both right that the issue is coming from them for the joystick stuff (the info form the documentation says it applies to keyboard and mouse, but apparently the joystick is altogether separate)

I'm pretty sure I've got a pause system similar to what rui.rasario mentioned in a GM:S project somewhere, so I'll dig that up and see if I can make it work with GM8.1. Will post and update when I'm home from work with any progress or colossal failures ;)
 
S

ScaryPotato

Guest
So, after some digging around, I found this code, and all the commands work in GM8.1. It was an example that I found a long time ago, and I can't remember who to credit the work to

objNewPause Create Event:
/// Create surface, draw everything to it, deactivate all other instances

surf = surface_create( room_width, room_height );
// Unfortunately, for this method to work, the surface has to be the size of the entire room and not just the size of the view.
// So, if you have a very large room size, this method may not work well for you... :(

surface_set_target(surf);
draw_clear_alpha(c_black, 0); // Clears surface.
with(all) { if (visible == true) { event_perform(ev_draw,0); } } // Draws every visible instance to surface.
surface_reset_target();

instance_deactivate_all(true);
visible = true;

image_index=0;
image_speed=0;
pause = 0;

objNewPause Alarm[0]:
// This alarm should ONLY be used when the surface is lost.
// The following is the same that happens in the create event. It is just redrawing all the instances to the surface.

surface_set_target(surf);
draw_clear_alpha(c_black, 0);
with(all) { if (visible == true) { event_perform(ev_draw,0); } }
surface_reset_target();

instance_deactivate_all(true);

objNewPause Step Event:
/// Unpause, clear surface, re-activate all objects.

//for keyboard
if keyboard_check_released(ord('P'))
{
global.PauseController=0;
surface_free(surf);
instance_activate_all();
instance_destroy();
}

//for gamepad (aka joystick)
global.JoystickPressRate -= 1;//counter for then the player can pause with the gamepad


objNewPause End Step:
//for joystick
if joystick_check_button(1,8) and global.JoystickPressRate<1
{
global.PauseController=0;
global.JoystickPressRate = 30;//this causes a delay before you can re-pause the game
surface_free(surf);
instance_activate_all();
instance_destroy();
}


objNewPause Room End:
/// Clear surface

surface_free(surf); // It's good practice to always clear the surface on room end, in case the room changes while the pause object is still hanging out.

objNewPause Draw Event:
/// Draw the surface to the screen

if (surface_exists(surf)){ // Make sure surface exists - if game loses focus, the surface can sometimes be lost.
draw_surface(surf, 0, 0);
// This needs to be in the DRAW event and not the DRAW GUI event because the surface is covering the entire room.
}
else
{
// If the surface gets lost, the following recreates it and redraws all the instances.
instance_activate_all(); // Activate all the instances again just for 1 step so they can be redrawn to the surface.
surf = surface_create( room_width, room_height );
alarm[0] = 1; // The instances must appear to the screen for 1 step to be redrawn.
}


/// [OPTIONAL] Draws a partially transparent rectangle over everything.
draw_set_color(c_black);
draw_set_alpha(0.5);
draw_rectangle(0,0,room_width,room_height,0);
draw_set_alpha(1);


//drawing the menu options
draw_self();

objPlayer Create Event:
global.JoystickPressRate=0;//Value for joystick button pressing with Pausing
global.JoystickPressRateMax=60;//Value for joystick button pressing with Pausing
global.PauseController=0;//This will control whether or not you can pause the game

objPlayer Step Event:
//Continued in the End Step Event


//for keyboard
if keyboard_check_released(ord('P'))
{global.PauseController=1;}


//for joystick
if joystick_check_button(1,8)
{
if (global.JoystickPressRate > 0)
{global.JoystickPressRate -= 1;}
else
{
global.JoystickPressRate = 30; //this causes a delay before the player can unpause the game
global.PauseController=1;
}
}
else
{global.JoystickPressRate = 0;}



objPlayer End Step Event:
//Continued from the stuff in the Step Event
if global.PauseController=1
{instance_create(x,y,objNewPause);}

So, all of this works like a charm in GM:S, and almost works in GM8.1. With this code, I am able to pause and unpause with the joystick/gamepad, but it only seems to happen sporadically (as if the timing needs to be precise for anything to happen), and all pause functionality seems to be lost with the keyboard (or maybe the timing isn't as precise as the gamepad?) At any rate, I've tried removing the joystick_check_button(id,numb) portion and had no luck pausing with the keyboard. I'm really at a loss at this point, since everything looks like it should work normally to my newb eyes. Does anyone have any suggestions how to get this working?

On a side note, I can't wait to get back to working with GM:S again!
 
Last edited by a moderator:
R

renex

Guest
You might want to use a SDL wrapper for joystick support... you get endless joysticks and better functionality than the pitiful joystick function set.

And you can poll them on your infinite loop.

This is a good one that I have been using for a long time now - even after Studio.
 
S

ScaryPotato

Guest
Hey renex, thanks for the tip about that file. It's something that I'll definitely look into using for other things I work on!
As limited as GM8.1 is with joystick functions though, everything works smoothly for me, apart from this stupid pause/unpause system. I managed to get things working a little better just now, by placing parts of code in the Step Event, and other parts in the End Step Event. That gave me keyboard functionality back, and it works right now on the Xbox gamepad, although it is finnicky.
I'll tweak things a little bit when I'm home tonight, but it's at about 95% right now, which is a huge relief! (Will post the code once I get it working at 100%)
 
S

ScaryPotato

Guest
Okay! So, after a bunch of messing around with variables, I think I've managed to come up with something usable. After picking apart the code I wrote, it seems like the joystick_check_button(id,numb) checks if the button is pressed at every step, so it needed some variables to prevent it from cycling through the commands constantly. I'll update the post with all the spoilers to include these latest changes. Maybe it'll come in handy for someone down the road, who knows. For now, I'm going to consider this solved.

Thanks to all you guys for the suggestions and info to help me through this!:D
 
Top