Hello Guest, please login or register.
Did you miss your activation email?
Login with username, password and session length.

Pages: [1]   Go Down

Author Topic: Menu System with the Controller object.  (Read 4564 times)

0 Members and 1 Guest are viewing this topic.
Menu System with the Controller object.
« on: May 03, 2010, 12:57:55 pm »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
It is a new month and I thought why not show everyone what I have been working on for the Community Project. This topic is about the Menu System I build for the CP Minish Engine. To test and illustrate the system I implemented some of the menu screens found in the Minish Cap. First I'll give a brief overview of what to expect. Then I'll explain some more the implementation details and all the relevant scripts. After that I'll follow with some questions that are still bugging me. And I'll close with some other systems that semi tie in with the menu system, but are not developed yet.

Brief overview:
I have implemented a Menu System. The menu system is completely build of scripts and is a state of objController. To demonstrate it I have implemented the item and status menus with the save and Kinstone submenus. By pressing START (Enter) you can enter and exit the menu. With the L (A) and R (S) you can shift from the item menu to the status menu and back again.

To move the cursor use the arrow keys. No! You can't navigate the cursor on the L and R buttons or use it to go to the next menu screen, because Minish Cap doesn't do that either. That was done in OOT and MM, but not in the Minish Cap. Use the A (X) and B (Z) for entering and exiting the submenus. In the submenus the L and R buttons do not work.

With the item and status menu the cursor position of the last visited index is stored, just as which of the two menus you visited the last. I haven't implemented the graphical effects of dropping HUD's, Title and sliding L & R buttons.

Have fun playing. The demo is attached to this post.


Implementation details:
No about some implementation details. First of the Menu System is not a separate "Room" nor a separate "Object". The Menu is actually a state of objController, realised by a number of Menu specific variables and a bunch of scripts. But later about that.

Pausing the game
There are two viable options. Option 1 is deactivating and activating all objects except objController itself. Second is to have a global variable pause or something and then each object at the beginning of each event (except the create event) should have if(global.pause) exit;. I have chosen for the former, because this engine should be usable by every one. And they should be able to add objects to the engine if they want to. Then option 1 is the easiest and best choice.

However this resulted in that a number of variables of objects (especially Link) are also needed by the menu. And when objLink is deactivated this becomes a problem. The variables that are definitely required are the keys and the scripts belonging to the keys. These were made 'global'. To keep it all ordered and such I declared all the global variables in the script "InitializeGlobals" that is called at the beginning of the creation event of the Controller. This also resulted in the alterations of those variables in the code and scripts of objLink.

The variables of the menu system
As mentioned above a number of variables were made global. But a number of variables specific to the menu system were defined in the create event of objController. The common variables are used by many states of objController, while the menu specific..., well you can guess.

Common:
  • state - the state of the Controller object, game, menu, titlescreen.
  • substate - this can be almost anything and the values depend on the state. With the menu it can mean the submenus.
  • timer - a counter that can be used by the state.
  • use_A/use_B/use_L/use_R/use_START/use_SELECT - boolean values that tell whether a key press should be processed (true) or ignored (false) by the controller.

Menu state specific:
  • menu_i - pointer to the current main menu screen. It holds an index value to menu[i,j] and thus designates the current active menu screen.
  • menu_m - the maximum number of main menu screens used in the game and all of them are put in menu[i,j].
  • narrow - it is a blinking value for the cursor and other blinking stuff. In MC the menu cursor widens and narrows after a number of frames.
  • menu[i,j] - holds all the menu data of the main menus.
    • j = 0 : holds the Menu scripts of the main menus.
    • j = 1 : holds the last selected cursor index of the main menu.
    • j = 2 : Another variable which can be used for anything.

As you can guess menu[,] and menu_i are the most important parts for the menu system. menu[,] is a matrix that holds all the data of a main menu screen. Each row is a menu screen. First is the script that holds all the code of a menu. Second is the last selected position of the cursor for the menu screen. In MC the cursor of each screen is stored. Last is a position for extra data that might be useful. Because there are only 3 menu screens in MC I could have done it with 3 sets of variables, but doing it in a matrix structure allows for scripts that are more plug and play. With menu[menu_i,1] = you could change a cursor position, no matter where in the matrix it is added.

The variables use_A, use_B, use_L, use_R, use_START and use_SELECT are boolean values that represent whether the press of the respective keys are propagated to the state. It is usefull when you don't want the menu to end, thus preventing the START press to exit the Menu state.

The scripts of the menu system
The basic script that also represents the state for the menu is 'ControlMenu'. On its own this script does very little. The state accepts 4 events which are propagated to the script of the menu that is currently active. In the STEP event this script does nothing but propagate it to the menu script. In the DRAW event the background is drawn to the buffer, after which the menu script can draw its parts. In the KEY PRESS event the base script does the most. An START key exits the Menu state no matter what the active menu script is doing. The L and R keys will go to the previous and the next menu, when the substate has the value 0 or lower, otherwise the keys are given to the menu script. All the other keys are propagated to the menu script. The fourth event is the CREATE event, which initializes the Menu System and the active menu.

The other menu scripts are created to demonstrate as examples for the Menu System, but also to look at how to realize or functions (later about that). 'MenuItem' and 'MenuStatus' are the base menus that are added. Like the name says 'MenuItem' is the menu that allows you to assign weapons to item keys, by pressing the respective key. If the item already had been assigned to the other item key, the weapons will be swapped. The MenuItem also has the save screen as a submenu. Submenus are substates in which L and R should not do their usual action. There are a couple of ways to realize the submenus. In MenuItem this is done by assigning the value 1 to the substate. The script 'MenuItem' also contains all the code for the save menu.

The other base menu is the Quest Status Menu, which is coded in the script 'MenuStatus'. This screen actually only shows the games current status. This menu also has a number of submenus, accessible by selecting them and pressing the A (X). The only two submenus currently implemented are the Save menu and the Kinstone collection menu. Unlike the Item Menu this menu does not assign numbers to the substate. Instead the script of the submenu is assigned to substate and when a submenu is activated the events are passed to the script of the submenu.

In short...
The script ControlMenu is the basis of the menu system, but it can not work without actual menu scripts. The data of the menus are stored in menu[,] and menu_i indicates which menu is active. Submenus are dealt with by the menu scripts, the code can be put together in a single script like in MenuItem or it can be divided over a number of scripts like in MenuStatus.


Bugging questions:
Okay having explained how the menu system works I still have a few things bothering me. Which I could not find a proper solution for.

Direction keys
Currently when processing key presses the controller only looks at the keys representing the buttons of the GBA. The d-pad is hardcoded as the arrow keys and dealt with in the step event. Just like in objLink. But because the controller only deals with key presses in the states for the controller that I currently can imagine, such as the HUD, Menu, Teleport and File Select. It only needs to deal with presses and not holds and releases.

My idea was that I would add the directional keys to the KEY PRESS events as well. Which would leave the step event near empty (note not completely empty, but near empty). This is a small feat to do accomplish, but my trail of thought did not end there.

I was thinking about making the directional keys the same as the buttons. Assign the values to global variables. And then when in the code the directional keys are used, accessing the global variable instead of using 'vk_up' or 'vk_left'. There are mainly two reasons for this. First it would allow the engine to be easier configurable to the developers preference. Probably even make a key configuration feature, that would allow the player to customize his own buttons. The second reason is that it makes added features more plug and playable. When a developer chooses to use other keys (such as WASD) for the directions, then those developers would not need to look through every bit of code of the features they are adding just to change the direction keys used.

I know it probably would not be as efficient as using 'vk_up' and 'vk_left', but there is something to be said about plug and playability.

Information bar
As you look closely a small text bar appears at the bottom of the screen, when the cursor is on something that had already been obtained. This text bar provides the name of that something (weapon, key items, trophies) centered in the middle. Now I was wondering how to do that the best way possible. I thought up two options:

First is to have each name as a sprite and then store those sprites, like I did with the Save menu example. The only thing that needs to be done is to draw the sprite on the text bar in the middle. This does mean that the file size increases a lot.

The second option is to store the info as a string and then draw the string to the text bar. This would require that a text engine would be implemented, which is a complete separate feature for the engine. It also gives an added requirement for the text feature that it can center text as its alignment.

I would prefer to use the second option, but that does mean that I cannot complete this part until I know the details of the text feature.


Other systems:
While I was making the example menus for the menu system, I could not help but think about some other minor features which aren't directly connected to the menu. Most of them are about storing data. Some of these features are partially implemented and some of them are not.

weapon matrix
First thing I thought about was how to store data of the weapons/items that Link uses by pressing the A and the B. I was thinking about making a matrix "global.weapon[,]" where each row is the data for a single weapon. What I currently have stored is the following:

weapon[x,0] - the strength/level of the obtained weapon, where 0 is that the weapon has not been obtained yet. For the bottles this value could represent the current content, with 1 being empty.
weapon[x,1] - the script that is associated with the weapon. The script that is executed when the respective buttons were to be pressed. And the script that is the state for that action.

At the moment I don't know what more I would need to store, but that could always be added. In some scripts the level of the weapon is required to be known and would thus need to access the matrix. To facilitate plug and play scripts again, one could assign the index of the row in the matrix to the buttons instead of the scripts themselves. And those index numbers would be easy accessible to the script.

I can still see some problematic points with those index numbers though and I have not really thought about a simple solution yet. Or whether that is the best way to store the data.

Boolean variables & flag lists
Well I probably am saying something wrong with the title, but what it comes down to is how to store game progress data. I thought about having some numerical values and the higher they are the further the progress, but this would result in very linear progress. Another option was to have a great deal of numbers that act as booleans because they only have the values 1 (true) or 0 (false), for example has_Opened_Area_X_Chest_Y.

The best option to me is to use a combination. I use the true/false values of option 2 because it allows for a more nonlinear gameplay and I use option 1's numerical values because it allows more data to be stored in a single variable, without get swamped in a landslide of variables.

This would come to the following. By using bitwise operators I would use a numerical variable as an array with boolean values. The 52 (+ 1 hidden) significand bits of GM's number data type are then the elements/indexes of the array. Storing a total of 53 variables in 1 variable. I have implemented the scripts setFlag, unsetFlag and queryFlag to deal with the bitwise operators and to somewhat make it dummy proof.

With the globals I have the variable status to deal with the stuff of the status screen and I was thinking about making once more a matrix to store data of every dungeon. Thus you could give a index value to each chest in the dungeon and then with common dungeon data representing the right flaglist, you could query, set and unset the right value.

Saving and loading data
I have implemented the save menu as an example for the menu system. Every functionality is implemented except for actually saving data. I thought to do this in script that would just be called and not a separate thread. This would mean that the game would just freeze and not show any animation while saving. This is not something I have thought long and hard about.

Dungeon vs overworld
Also not yet implemented, but it is something that would be required for the map screen and maybe the flaglists. Data that indicates which area the player is in. And if this is an overworld or a dungeon area. In addition which overworld or dungeon area. For the dungeon I was also thinking about how store the number of keys the player has in its possesion.

I thought about doing this in variables with the controller object or maybe make a special object associated with the room or something. Well I'm not to sure about this.
« Last Edit: May 03, 2010, 01:06:26 pm by Niek »
Logged
Re: Menu System with the Controller object.
« Reply #1 on: May 03, 2010, 01:07:12 pm »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
My apologies for the ridiculously long post, but I needed it get everything of my chest.
Logged
Re: Menu System with the Controller object.
« Reply #2 on: May 03, 2010, 01:51:03 pm »
  • *
  • Reputation: +4/-0
  • Offline Offline
  • Gender: Male
  • Posts: 207
Awesome work as usual Niek. Real nice addition to the engine. I havent read your first post yet but I will after I write this...although it will probably be like reading Chinese lol as I only know the very basics OF GML atm. But yeah, its great that youre putting in so much work on this engine. I really wish I had as much programming skill as you cuz id be helping as much as I could :(

Edit:

I found this "glitch" ages ago before I got a new laptop



Its when you push the block next to the cliff, and then jump down the cliff onto the block.
(Link gets stuck in front of the block)
I know this can probably be avoided by level design but I can remember a part in one of ALTTPs dungeons where this happens, except that if you move in any direction while "stuck" in the block, Link gets released from the block and is no longer stuck.
OK, it was a bit different in ALTTP as you actually get stuck "in" the block, not "in front" of the block as shown in the pic above. And also, it was from falling from a higher level onto the block at a lower level...not from jumping down a cliff type object.
« Last Edit: May 03, 2010, 02:24:50 pm by Skeme KOS »
Logged
Re: Menu System with the Controller object.
« Reply #3 on: May 03, 2010, 02:48:12 pm »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
But yeah, its great that youre putting in so much work on this engine. I really wish I had as much programming skill as you cuz id be helping as much as I could :(
Thanks for the compliment, but don't sell yourself short. Like I said before, practice makes perfect. Start out with something simple such as Link drinking a red potion to replenish hearts. Or when Link collects ruppees, arrows or hearts. Show the code and then we can give you advice on how to improve it or where there are glitches.

I don't know if you have access to the Minish Cap game. I could give you the homework assignment to implement a bottle action :P. But that you are testing it all helps a lot as well.

I found this "glitch" ages ago before I got a new laptop



Its when you push the block next to the cliff, and then jump down the cliff onto the block.
(Link gets stuck in front of the block)
Hmm, that seems to be a problem with pushing and ledge jumping. Well you are right that it is partially a problem for level design, but it couldn't hurt to look at it to see if it can be prevented.
Logged

Mamoruanime

@Mamoruanime
Re: Menu System with the Controller object.
« Reply #4 on: May 03, 2010, 07:26:06 pm »
  • ^Not actually me.
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 9786
Very nice. Only glitches I could find are ones that under normal circumstances couldn't be replicated in an actual game setting.
Logged
Re: Menu System with the Controller object.
« Reply #5 on: May 03, 2010, 09:34:54 pm »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
Now I'm curious about what you tried to do  :P
Logged

Mamoruanime

@Mamoruanime
Re: Menu System with the Controller object.
« Reply #6 on: May 03, 2010, 09:52:02 pm »
  • ^Not actually me.
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 9786
Now I'm curious about what you tried to do  :P

Lol well nothing that broke the menu in particular. That's actually pretty solid, and I'm fairly impressed by it's design :P
Logged
Re: Menu System with the Controller object.
« Reply #7 on: May 16, 2010, 07:10:20 am »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
A bit late, but still thanks. I am still wondering about what to do with the direction keys and the information bar.

Bugging questions:
Okay having explained how the menu system works I still have a few things bothering me. Which I could not find a proper solution for.

Direction keys
Currently when processing key presses the controller only looks at the keys representing the buttons of the GBA. The d-pad is hardcoded as the arrow keys and dealt with in the step event. Just like in objLink. But because the controller only deals with key presses in the states for the controller that I currently can imagine, such as the HUD, Menu, Teleport and File Select. It only needs to deal with presses and not holds and releases.

My idea was that I would add the directional keys to the KEY PRESS events as well. Which would leave the step event near empty (note not completely empty, but near empty). This is a small feat to do accomplish, but my trail of thought did not end there.

I was thinking about making the directional keys the same as the buttons. Assign the values to global variables. And then when in the code the directional keys are used, accessing the global variable instead of using 'vk_up' or 'vk_left'. There are mainly two reasons for this. First it would allow the engine to be easier configurable to the developers preference. Probably even make a key configuration feature, that would allow the player to customize his own buttons. The second reason is that it makes added features more plug and playable. When a developer chooses to use other keys (such as WASD) for the directions, then those developers would not need to look through every bit of code of the features they are adding just to change the direction keys used.

I know it probably would not be as efficient as using 'vk_up' and 'vk_left', but there is something to be said about plug and playability.

Information bar
As you look closely a small text bar appears at the bottom of the screen, when the cursor is on something that had already been obtained. This text bar provides the name of that something (weapon, key items, trophies) centered in the middle. Now I was wondering how to do that the best way possible. I thought up two options:

First is to have each name as a sprite and then store those sprites, like I did with the Save menu example. The only thing that needs to be done is to draw the sprite on the text bar in the middle. This does mean that the file size increases a lot.

The second option is to store the info as a string and then draw the string to the text bar. This would require that a text engine would be implemented, which is a complete separate feature for the engine. It also gives an added requirement for the text feature that it can center text as its alignment.

I would prefer to use the second option, but that does mean that I cannot complete this part until I know the details of the text feature.


Oh yeah I still have been working further on this and decided that the A (X) and B (Z) buttons no longer contain the script id as value, but an index of the row where the script id can be found and of course other data. And this index is passed as the last parameter to the events this would make things considerably easier for the bottles.

I had also been thinking about how to do a color change of the tunics, but that involved swapping the sprite resources. And swapping resources is a Pro feature  :-X. So that is on hold.

Well what I am now working on is stripping that what has been created already to the bare minimum. And have almost every action as a PnP add-on.
Logged
Re: Menu System with the Controller object.
« Reply #8 on: May 24, 2010, 12:29:31 pm »
  • *
  • Reputation: +16/-0
  • Offline Offline
  • Gender: Male
  • Posts: 1633
Never mind :)
Logged

Brutus

Kirby Master
Re: Menu System with the Controller object.
« Reply #9 on: November 14, 2010, 08:29:58 pm »
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 134
Someone might have already mentioned this, but when you charge an arrow, after that the only arrows you shoot are charged ones :P
Logged
if place_free(x,y,z) {wrong number of arguments to function or script}
Pages: [1]   Go Up

 


Contact Us | Legal | Advertise Here
2013 © ZFGC, All Rights Reserved



Page created in 0.025 seconds with 57 queries.

anything