I'm about to commence my first GUI, I was wondering if anyone has any times on how I should structure the data and classes? Something that might help me with future issues.
Jump to content
Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.
Posted 12 April 2014 - 08:47 AM
You could do something like this: make your own GameButton class and have new buttons you create inherit from the GameButton class.
To think data structure is to think of object oriented composition. Each button should have some notion of representing itself (i.e: an image, position(x and y coordinate), have a mouse listener(so the buttons can listen for mouse events). Add these buttons object to the canvas so the buttons can listen the mouse events from the canvas.
Edited by warnexus, 12 April 2014 - 08:48 AM.
Posted 12 April 2014 - 08:59 AM
When I started using GUI toolkits, I couldn't figure out why they were written for a single thread, but the keyboard and mouse events come in on other threads. Even Java uses a single threaded event thread concept and none of the GUI components are thread safe. Because the UI lives in two worlds, waiting for user input while the high level software is running, but responding to low level keyboard and mouse events, as well as operating systems messages such as focus gained/lost, it is very difficult to get right.
Long story short (too late) don't build your own GUI toolkit unless you really need to. Find an API or toolkit and use that.
Edited by Glass_Knife, 13 April 2014 - 08:50 AM.
I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming
My Twitter: https://twitter.com/indieprogram
My Book: http://amzn.com/1305076532
Posted 12 April 2014 - 06:09 PM
Just a word of warning for you--unless you have something very simple in mind, this can easily snowball into taking up a massive amount of your time (especially if you've never done anything similar before). You may find yourself, 10-15 years later, working full time as some sort of UI specialist. lol (Ok, that's not such a bad thing.) I'm sure personality has much to do with this, but based on what you're asking, you could fall into that trap.
If you don't like that fate, my advice would be to either find an existing library or to define your requirements accurately and very simple. Many people seem to think that UI development doesn't seem so hard, but believe me, it gets extremely challenging fast (especially with the high expectations people have now).
Just my opinion--could turn out wrong...
Unfortunately, many (most? all?) UI libraries have their own learning curve, but you should get up and running faster if you're not too much of a picky perfectionist.
Posted 12 April 2014 - 06:56 PM
I've made a few GUIs before. It can get tricky and time consuming. Break down the GUI into the simplest components you need to accommodate your program.
These are the basic ones I use. I also have "menu groups" which are like their own window and contain the menu items listed above (as needed). Each of these items you need to be able to reference in your program so that they can "do something".
If it's at all possible, you should try to find a third party GUI. If you are set on doing it yourself, I can help you if you want.
Posted 12 April 2014 - 08:58 PM
Posted 13 April 2014 - 02:49 AM
The key to a good GUI is your event handling system.
When someone clicks on a button, how do you link that to code?
There are plenty of techniques depending on programming language, but they basically come down to two core technologies.
Callbacks and messages.
Callbacks are simple and direct, you link the button to a subroutine which does the real work.
Messages are a little more complex, you click on the button. It adds a message to the list. At some point in your code you parse any pending messages and clear the list.
I prefer callbacks. They can be called events, signals, callbacks, all sorts of things, but they all work the same way.
The only other thing I would advise is that you don't use scaling. I hate the look of scaled graphics. So to draw a button you draw the four corners, draw the sides, then fill the middle instead of just drawing a scaled version of the button.
Other than that, have fun. I love writing GUI's, I particularly like making strange effects like circular folding menus, animated buttons, animated transitions.
Posted 13 April 2014 - 03:47 AM
The implementation of a GUI system has aspects of input processing, graphical representation, and effect.
1.) Clarify whether immediate mode or retained mode GUI is what you prefer.
2.) Define how input is handled (fetched, collected, prepared) before it is provided to consumers.
3.) Define whether provided input is pushed to consumers or pulled by consumers. E.g. when running down an iteration of the game loop, the various sub-systems are called anyway and hence may investigate provided input whenever they are updated. This is an alternative to the push model which is known from application programs.
4.) GUI elements compete with other GUI elements and with game controller objects. Define how routing of input to the various possible consumers is to be done. Is the gameplay view just another widget?
5.) Define how the effects of action widgets (e.g. when pushing a button) is processed. E.g. does it invoke a callback, sends a message, or sends a command object?
6.) Define how the effects of value widgets (e.g. when dragging a slider knob) is processed. E.g. alter a local value, use a callback, send a message, send a command object, or change the target value in-place (the latter is fine for tweaking).
7.) Depending on the targeted platform: Make the graphical rendering resolution (DPI) independent by using scalable graphics / multi-resolution graphics.
8.) Even more important (IMO): Make the placement independent on the aspect ratio by using various anchors (horizontally left / center / right, vertically top / center / bottom) and a resolution independent length (e.g. normalized with the display height).
Hopefully you don't need things like table or outline views and drag & drop, because they make things really complicated.
Posted 13 April 2014 - 01:32 PM
Hello there, Gamedev forums! : )
I feel like it is appropriate for me to make my first post in this thread, as thinking about UI/GUI implementations have took up a lot of my free time in the past months, or even a year. (HTML5 indie, refusing to use CSS for "proper" buttons, since I plan on going to mobile as well, and I do not want to be dependant of DOM/CSS in any way whatsoever).
So, I have arrived at a point where my implementations was this:
a. You have a class named uiNode, which has an attached onExecute() function, and has a -initially empty- uiNodes array as well.
b. Upon updating your game/scene, you see if you have clicked on one of your nodes. You can do this via just getting the mouseclick and compare it to a list of your nodes (so the click has to be within the boundraries of your virtual button/menu item).
c. Each uiNode of yours can contain more uiNodes (they always automaticallly have an empty uiNodes array), and it is possible to have an onExecute() that does nothing else but "opens up" a set of buttons, that were otherwise invisible/inactive before.
So you have basic elements that are either visible or not, clickable or not (these things are different for a reason - you might have invisible buttons that are tied to pictures, or visible, but not yet clickable buttons that become active when something changes them), and due to the recursive nature of this.uiNodes[n].uiNodes[m].uiNodes[l]...., you can have submenus naturally. Your onExecute either leads to new menu points, or executes the code linked to clicking that particular button.
I found out that while this approach works, sometimes, for easier scenes (and even for something like an inventory screen), it was less of a hassle to just create my click logic independent of this structure. But when real menus are needed, this helped me.
A few pitfalls to avoid, regardless of what language you are aiming for:
- Have a way to dynamically change size/positions - you are not always in this with the same resolutions, after all
- Do not check each button's click state every frame, that can get demanding fast in main menus. Instead, just make a list of your active nodes and cycle through their positions whenever a click occurs. That way, you do not have scenarios where overlapping buttons/texts activate at the same time. You can even define rules like nest levels, click hierarchy, etc.
- What others posted here: define your needs, and do not go overboard with it. I spent way too much time on this, time that should have gone towards the implementations of the game rules, not arbitrary ui structure building. I do not regret it, but it might not be your favorite time spender.
Edited by Sawamara, 13 April 2014 - 01:33 PM.
Posted 13 April 2014 - 09:43 PM
Posted 14 April 2014 - 01:21 AM
While it's good to figure out class hierarchies and what features you need, don't lose sight of the purpose of the GUI - to allow the user to EASILY input whatever information the program you're writing needs. This is one of those things that some would dismiss as 'the easy part', but it's not (see: KDE vs Gnome). Incidentally, documentation is another thing that falls into this category - even Eric Raymond once wrote in an 'open letter' to open source developers saying, in effect, "We've done the hard part, now just do the easy stuff and write the manual." Sorry Eric, writing isn't easy - it's a craft that takes years of hard work, training, critques, and more practice to learn. Design is much the same: it's a separate skillset from what you use when you code the GUI elements.
IOW, your GUI code could be the most beautiful, elegant code ever seen, but your GUI could still suck bollocks from the user standpoint.
For inspiration, I'll refer you to what may be the most widely used and easily understood GUI ever created: The Denny's Menu.
Edited by Mouser9169, 14 April 2014 - 01:23 AM.
"The multitudes see death as tragic. If this were true, so then would be birth"
- Pisha, Vampire the Maquerade: Bloodlines
Posted 14 April 2014 - 04:55 AM
I'm on my 3rd or 4th UI now. Like HawkBlood said, edit boxes list boxes imageboxes, text, dropdowns and contain them all in a dialogbox type class, this is like your window.
Use a 3d model app to create and place buttons then export to your format and load it up.
some thing like this
then create a menu say for load screen
class MenuLoadScreen :BaseMenu
basemenu *base = new MenuLoadScreen();
then you can have a list of them
and define input elements for the location of the menu
#define LOADMENU_ID 0
or use a CurrentMenuID to change menues.
Posted 28 April 2014 - 09:29 PM
One note unless GUIWindow is this I recommend a UIPanel class. This is pretty much just a group of components that has a size and can organize children relative to its position. It lets you anchor points and you will need a margin / anchor property to make sure everything lines up unless you are only wanting to support 1 resolution. Another convenient figure is if you allow it to clip children. Then you can create scroll views. Most gui utilities support panels, grids, and other organizational items but you can get by with just a panel to be honest. Also by supporting children to organizational objects you can build together different parts to make more complicated components. Also when you create your event system you can search through your items in a tree structure rather then a linear list. Also you NEED events / callbacks. If you are in c++ use FastDelegate as a base for your delegate system and build an event class. Most other languages have some sort of support for that otherwise.
Common components I use.
2. Texture Button
4. Progress Bar / Slider (these components internally will be very similar)
Posted 29 April 2014 - 03:08 AM
That is what the window is, although the idea with the window is to have a border (like a popup) but a Panel could be used as a border less window to go inside of a window.
The generated diagrams don't really show it, but they are working like a tree, also not really shown are the events, if something happens the entity will return a Event which contains a pointer to the entity, event type and the entity type.
GameDev.net™, the GameDev.net logo, and GDNet™ are trademarks of GameDev.net, LLC.