Making a text / keyboard menu

 

This tutorial allows you to create a text / keyboard menu.  This is the technique used in swords and sorcery to have the user select options using the keyboard.

 

I didn’t want players to use the mouse in that game to add to the « oldie » effect.

 

  1. Drawing text on the screen.

 

GM requires that you draw text and images on the screen using the draw event.  That means all scripts that post text or images on the screen have to be called by an object’s draw event.

 

Object Properties

In the example, the script write_monsters draws the text in the combat menu.

 

The combat feature being text driven, when combat starts the player is directed to a new room dedicated to fighting.  This way everything in the room originates from the controler object (read more about those in the founding principles tutorial).

 

This is important because text is only drawn for one step, so there are only two ways to make text stay on the screen as long as you like :

 

  1. Preventing the step from finishing by interrupting it (more on specific commands below).

  2. Having the text re-drawn at each step, for as long as you want it there.  Associating it to a controler object’s draw event works for that because those are redrawn at each step.  Then all you need is a variable to determine whether or not that same text is to be written again or not.


 

 

 

Commands for drawing text and images are the following :

-         draw_text (x position, y position, ‘your text here’)

-         draw_sprite (x position, y position, sprite_name)

o       The sprite has to be uploaded in the sprite folder.Add Sprite

 

Making the text stay on the screen.

 

As mentionned above, one of the ways to prevent your text from disappearing as the game moves on to the next step is to prevent it from doing that.  Use the following command :

 

 keyboard_wait()

This freezes the game until the player strikes a key. 

 

But that’s not enough.  For it to make sense, your game has to react different ways according to what key is pressed.  That means first recording what key the player did press.

 

keyboard_lastkey() returns exactly that.

 

Using an if statement and variables you can determine what happens next, depending on what key was pressed.


 

 

Here is an extract from the weapons store script in Swords and Sorcery :

 

// buying weapons

        if (global.buying =11)

            {

            draw_text (350,400,’(1)’);

            draw_text (350,435,’(2)’);

            draw_text (350,470,’(3)’);

            draw_text (350,505,’(4)’);

            draw_text (350,540,’(5)’);

           

            draw_text (400,400,global.itemname[1]);

            draw_text (400,435,global.itemname[2]);

            draw_text (400,470,global.itemname[3]);

            draw_text (400,505,global.itemname[4]);

            draw_text (400,540,global.itemname[5]);

           

            draw_text (600,400,global.itembuyfor[1]);

            draw_text (600,435,global.itembuyfor[2]);

            draw_text (600,470,global.itembuyfor[3]);

            draw_text (600,505,global.itembuyfor[4]);

            draw_text (600,540,global.itembuyfor[5]);

            

            draw_text (700,400,’gold’);

            draw_text (700,435,’gold’);

            draw_text (700,470,’gold’);

            draw_text (700,505,’gold’);

            draw_text (700,540,’gold’);

           

            draw_text (100,710,’Available gold:’);

            draw_text (300,710,global.gold);

           

            draw_text (100,745,’(X)Back.’);

           

            io_clear ();

            screen_refresh();

            keyboard_wait();

            if (keyboard_lastkey = ord (’1′)) global.itembought = 1 else

            if (keyboard_lastkey = ord (’2′)) global.itembought = 2 else

            if (keyboard_lastkey = ord (’3′)) global.itembought = 3 else

            if (keyboard_lastkey = ord (’4′)) global.itembought = 4 else

            if (keyboard_lastkey = ord (’5′)) global.itembought = 5 else

            if (keyboard_lastkey = ord (’6′)) global.itembought = 12 else

           

            if (keyboard_lastkey = vk_numpad1) global.itembought = 1 else

            if (keyboard_lastkey = vk_numpad2) global.itembought = 2 else

            if (keyboard_lastkey = vk_numpad3) global.itembought = 3 else

            if (keyboard_lastkey = vk_numpad4) global.itembought = 4 else

            if (keyboard_lastkey = vk_numpad5) global.itembought = 5 else

            if (keyboard_lastkey = vk_numpad6) global.itembought = 12 else

           

            if (keyboard_lastkey = ord (’X'))

                {

                global.buying = 1;

                exit;

                }


 

There are several variables involved here. 

-         global.buying determines what the player is currently doing in the store, which depends on previously picked options.  In this case the choice he made previously led him to the buying weapons menu which lists the items available, their price (global.intembuyfor[item id), and how much gold the player has (global.available gold).

-         global.itembought  records what item the player bought according to the choice he made.  If player hit ‘3’ when asked what he wishes to buy, then he has chosen item 3, which corresponds to a large club according to the item list script.

o       He is then asked to confirm and if he does, the item is added to his inventory by calling a script dedicated to doing that (add_to_inv()).  The price is subtracted from his available gold.

 

Here is the end of that script’s section for information :

 

            if (global.itembought = 0) exit;

            if (global.itembought >0 && global.gold >= global.itembuyfor[global.itembought])

                {   

                draw_text (350,635,’Confirm y/n’);

                io_clear ();

                screen_refresh();

                keyboard_wait();

                if (keyboard_lastkey = ord (’Y'))

                    {

                    global.newitem = global.itembought;

                    add_to_inv();

                    if global.packfull = 0

                        {

                        draw_text (350,670,’OK’);

                        global.gold -= global.itembuyfor [global.itembought];

                        global.newitempacked=0;

                        } else

                        {   

                        draw_text (350,670,’No space left to pack!’);

                        global.packfull=0;

                        }

                    screen_refresh();

                    sleep (1000);

                    exit;  

                   } else exit;

                } else

                    {

                    if (global.itembought =0) exit;

                    if (global.gold < global.itembuyfor [global.itembought])

                        draw_text (350,670,’Cant afford it!’);

                        screen_refresh ();

                        sleep (1000);

                        exit;

                    }

            }

 

If the player hits the wrong key, then itembought is still at 0.  That causes nothing, the step finishes, and all text would disappear if it weren’t for the following way to keep text on the screen from one step to the next.

 

NOTE :  screen_refresh is necessary each time new text is to be added to the screen (like « can’t afford it ! » or the menu items written at the beginning.)

 

Using controller objects to keep text on the screen.

 

When a step ends, the room starts over, and objects that were added to the room are drawn again.

 

Using a controler object that doesn’t show on the screen because it has no sprite associated to it ensures that your store script is read again at the next step, during the controler’s draw event.

 

If the player hits the wrong key, then the variables haven’t changed and your store text is re-drawn just like during the previous step.

 

To make this easier, my store and combat screens are in separate rooms.  When the player enters a store or is engaged in combat, I use room_goto (room #) to transfer to a different room.

 

This isn’t necessary for in-game options such as « There is a cave opening.  Enter ? ».  Those are triggered by the player being in a specific place so it will appear again if the player returns to that specific place.

 

Those are done by creating instances when the conditions for the question appearing are met.

 

Example :

 

if (global.posx=7 && global.posy=15) instance_create(100,100,inn_obj);

If the player is at the coordinates (7,15) on the map then the inn_obj is created.  That launches a new draw event, to which I will have associated a script asking if the player wants to enter the inn  (the sript works for all stores and special events so it checks the coordinates again to act accordingly).

 

From there if he says yes, he is sent to the adequate room.

 

I systematically destroy objects I no longer need to prevent objects to pile on each other, severely slowing down the game, using the position_destroy (i,j)command.  All script generating objects are created at the same place to make it simple. 

 

This should enable you to add text menus to your games, even if they are nothing like swords and sorcery.

 

Don’t hesitate to join the forum to ask questions whenever needed !

<