To make our game a little more functionally intuitive and game-like, we're going to create a custom interface, and make use of macros for keyboard controls.
If you haven't already read Tutorial #8, you should check it out first. Or, start at the beginning, if you're new to the series!

Creating an Interface
To start off, we're going to create the actual interface file (.dmf), I just named mine Interface. NewInterface.png
You should now be looking at a screen with 3 sections, one for Marcos, one for Menus, and one for Windows.

Creating Macros
The interface file we just created will handle how our game's windows look and function, it also handles the macros (keyboard controls).

Step 1.1 First, we'll edit our macros. Double click the macro line at the top, and then delete out the unnecessary controls, leaving only the ones for cardinal movement. You can delete a specific key's macro by right clicking on it and selecting delete, or by highlighting it and then pressing the delete key. EditingMacros.png

Step 1.2 Now, we'll create our own controls. Click the [New macro...] button, then select a Key to use, and set the Command to Attack. NewMacro.png
Using the [Find Key...] button is usually easiest, and the Command represents which verb you want to use. In our case, this will call the Attack() verb that we created a few Tutorials back.
With this new macro added, we can now attack by pressing the F key, instead of having to click a text command in a stat panel/info control.
The various check-boxes here can be used to get different input responses. ALT CTRL and SHIFT will make it so those keys must also be held down for the macro to trigger. Repeat will cause the macro to automatically repeat every tick for as long as the key is held down. 'When key is released' will activate when the key is released... instead of when it is initially pressed down. Repeat and Release cannot be selected at the same time.

The Main Game Window
Now that we have a custom interface, our game won't have a map, or stat panels, or an output, or anything else. We'll need to add these onto the default Window.

Step 2.1 Double Click the default Window to bring it up for editing. EditingDefaultWindow.png

Step 2.2 First, we should make some basic changes to the window itself. You can do this by double clicking anywhere on it, or by clicking the [Edit...] button on the window in the upper left. EditingMainWindow.png
Here, I've set the window name/ID to MainWindow, this can be used later to reference the window from the code.

Step 2.3 Switching over to the Options tab, we have a few more things to change EditingMainWindowOptions.png
The Title of the window will be displayed at the top, and if its the main window, also in the taskbar.
We turn the Statusbar off because its just a waste of space, it displays an /atoms name on MouseOver, but not much else.
The icon for your interface can be set to display on both the Titlebar, and on the taskbar entry, same as the Title. If you set the icon on the window marked as default, it will automatically apply to all other windows. Here, I've just set it to the Player icon, for demonstrative purposes.

Step 2.4 The last tab is the Skin options. These let you set background color/images, and an overall transparency for the window. I won't be using any of these for now, but you can mess with them if you'd like.

A Main Map Control
Our window is currently blank, we won't be able to see the actual game, or any of the stat panel info we've previously setup. To add various controls to our window, use the button from the window in the top left.

Step 3.1 First, we'll add a map control. Click the [Map] button, and then click anywhere on our window to place it. NewMapControl.png

Step 3.2 Now drag that map control so it is aligned with the top left of the window, just below the File Menu. MapAlignment.png

Step 3.3 By using the blue boxes on the sides of a control, you can re-size it. Use the bottom right box, and make the map cover the entire window. SizingMapControl.png

Step 3.4 Now double click the map, or use the [Edit...] button, like we did before with the main window, to bring up this map's editing window.

Step 3.5 In the General tab, set the map name/ID to MainMap and make sure the default check-box is checked.

Step 3.6 In the Anchors tab, set the anchors to 0,0 over 100,100 MapAnchors.png

Step 3.7 Use the OK/Done buttons to close those windows back down to the base DM layout, then press ctrl+R to run your game. It should ask if you want to compile (because you've made changes to the interface), say yes.
There is now nothing but a map, with icons that will scale to fit the window, and you can attack by pressing the F key. Our output is missing though, so we won't get a report about damage!

Adding Output & Info Controls
Finally, we'll add controls so we can see our stats and damage outputs again.

Step 4.1 First, re-size the map so that it isn't taking up the entire window. Once you have room, add an output control, and set it up on the opposite side of the map. AddingOutput.png

Step 4.2 Select both the map and the output control, by holding ctrl and clicking both of them. Re-size one of the controls over the other. Then use the [Distribute width evenly] tool from the menu bar. DistrubuteWidthEvenly.png
This will evenly size them, so each one takes up half the window.

Step 4.3 With the controls still selected, click the [Auto-anchor controls] tool. AutoAnchorControls.png
This will make sure the controls resize properly if the window changes size. It doesn't always give the best results, so make sure you check.
You want 0,0 over 50,100 on the map, and 50,0 over 100,100 on the output. The 50s are here because each one is using 50% of the space. If you had 3 controls, you would want something like 33 to 66 to 99, and the 99% should be rounded up to 100, so no blank space is exposed.

Step 4.4 Double click your output control to edit it. Change its name/ID to MainOutput, make sure the default check-box is checked, and set the border style to sunken. OutputGeneralSettings.png
You can use the Appearance tab to change the default font face and colors for your output, but I won't be bothering with mine.

Step 4.5 To add an info control, follow the same basic steps we did for the output. Except, this time, place it above the output, instead of beside the map. AddingInfo.png
The edited settings for the info control should be about the same as the output's as well. InfoGeneralSettings.png
When you use the auto-anchor tool this time, make sure you have all 3 controls (map, info, output) selected.

Managing the Interface with Code
Step 5.1 winset() content by popular demand! Now then, we'll setup the default state of our main interface window with a new line of code in /mob/Login()
world<<"[src] has Returned"
world<<"[src] has Logged In"
spawn(-1) winset(src,"default","size=640x480; pos=100,100; is-maximized=true")
//The above winset() line is new
winset() is used to change interface settings. You give it a player (src, in this example), the window or control to be changed ("default" in this example. If we wanted to change some settings on our interface's map, we could send it "default.MainMap"), and finally, the settings we want to change. As you can see here, we are using a single winset() to change multiple parameters (the size, position, and maximized state of the window), you do this by separating the parameters with their values by a ; (as seen in the example above)
Sending multiple parameters at once is beneficial as it cuts down on network traffic and processing. We also spawn() this code off to prevent any possible network delays from effecting our overall project. Such network delays when working with the interface are more of a concern with winget(), which I won't be going into for now.
A full list of interface settings can be found here:

After writing this tutorial, I've realized what a ridiculous amount of work it is just to get your interface halfway back to default, just so you can implement custom macros...

* Tutorial 10 will be about on-screen damage, and hiding our Attack() verb from the Commands tab.
I would really be interested in seeing a tutorial made by you about how to use an interface with character creation.

For instance.

1 main menu window for loading a character making a new character, and quitting.

1 window that shows different character saves to choose from (could also be used to delete saves as well.

1 window that leads to character creation with basic character settings like the characters name, height, weight, eye color, hair color, skin color. Maybe the ability to set how the players icon would look.

I have been looking for a good tutorial on this but have not been able to find one as of yet.

Anyway, if it is at all possible I would be very thankful. :P Plus I think it would be an interesting thing to add to this tutorial series.

(I have made a interface if you are interested in making this tutorial, it is already set up with all of the needed windows and labeling. If you are interested just let me know and I will send it to you.)
Thanks that would be wonderful. =]
I love you.
I love you too. (No homo)
Falacy wrote:
I'll try posting one of these every Friday from now on.

Nice, I enjoy your articles. Looking forward to them, thanks Falacy.
Shouldn't you have explained winset(), winget(), etc too?
Kenny84 wrote:
Shouldn't you have explained winset(), winget(), etc too?

When we actually use them. There's no need with whats being done here. winget() should be used scarcely, it takes forever to run, and you can usually get the info some other way. M: undefined type: M M: undefined type: M M: undefined type: M M: undefined type: M Locate: undefined proc M: undefined type: M M.Level: undefined type: M.Level M: undefined type: M M: variable defined but not used M: variable defined but not used

(how can i fix this issue?)
So, when is tutorial 10 coming out and what will be included in it? (If it hasn't changed from what is shown at the end of this tutorial.)
Falacy I would like to request a tutorial on HUD's because the other tutorials fail and i want to have a hp bar and like hotkeys etc ;D. don't matter when you do it, it would be nice tho if you do make the tut :)
Falacy hey man Nice tutorials i really learned alot but there is one thing standing in my way...

Can u make a tutorial on menus in the .dmf file and how to code them and to make a button to disable and enable it. Thnx in advance :)
Thanks man
Thanks Alot Falacy! :D

Your Tutorials actually got me way further than just iconning and mapping. Now I can actually make decent looking games. Your set of tutorials kick the official byond ones and other ones too :P Can't Wait For Part 10!
where part 10 man
This only shows how to use the interface editor.
I don't see this much more then a "introduction to the interface and macro editor".

it explains things good, but i don't see it as a complete tutorial. winset(), winget(), winclone(), winshow() is something you really should bring into a tutorial about interfaces. Make buttons that creates/shows other windows, exiting other windows, creating panes/childs etc. also, something that i havent seen been brought up in any tutorials, creating new menu's during runtime. as you said above, that the window procs was process-consuming. I don't think so...

i don't think that the window procs are so processconsuming that u wouldnt use it. Every computer today shouldn't have any problem running it. If you are meaning it would be bad programming to use it, i would prove you wrong.
In response to Tafe
Tafe wrote:
it explains things good, but i don't see it as a complete tutorial. winset(), winget(), winclone(), winshow() is something you really should bring into a tutorial about interfaces. [interface features]
I don't support the use of interfaces, aside from the basic usage of a map and output control. Everything else should be handled in-game on the map/screen. Especially if this flash client ever gets released, since that's all they're really going to support with it.

i don't think that the window procs are so processconsuming that u wouldnt use it.
If you're referring to my winget() comments, the problem I mentioned isn't that it is processor consuming, it is about the network lag. Winget() takes at least 1, if not 2 ticks to send and then receive the information. Majority of the time, such information can be stored in a variable for instant access.

Also, this tutorial isn't really designed to cover the entirety of interface usage, it is simply the interface portion of the tutorial for the process of creating this tutorial game as a whole.
Corax Software wrote:
Inefficacy is hardly an excuse for not including them.
Again, its not really about efficiency, but reliability. Waiting 2 ticks for a response, that 90% of the time you can get instantly through a variable, is not only a poor design decision, but can often lead to bugs.

The only time you should really need winset() is to setup the window at Login(), which I suppose I could include. In general, however, and as I already stated, I do not support the use of interfaces beyond the necessary map control, and an output control for simplicity. Everything else should be handled in-game on the map like a proper game.

This tutorial doesn't cover a lot about interfaces. Child controls, buttons, labels, inputs, etc. It covers the very basics that you need to get the game up and running. This tutorial is only part of a series that covers the process of creating an entire game, not the end all be all interface tutorial. The general point of this tutorial was just to rebuild the default BYOND interface so that custom macros could be implemented.
In response to Falacy
Why did you never continue these?
Page: 1 2 3