Click here to Skip to main content
Email Password   helpLost your password?

Screenshot - OdysseyUI.jpg

Introduction

I am developing a 4X Space Opera game called Star Odyssey, in the tradition of the Master of Orion series. Every game needs a User Interface and mine is no exception. The DirectX SDK provides a sample UI that looks very cool, but it is very difficult to extrapolate from the project and it relies on textured GUI elements. Since I am not very good at drawing GUI elements, it would have taken ages for me to go that way. Instead, I took the ''programmer art'' way: to create controls and other GUI elements in a dynamic way, trying my best to make it look cool at the same time. The result is presented here. Readers should be somewhat experienced in DirectX terminology. Since the game doesn't need absolute FPS responsiveness, simple Windows messages are used to handle input. Please note that in order to run the sample, you need the DirectX SDK installed. In case you have problems, try using the DirectX web installer.

Using the code

The controls provided in this project are designed to work just like Windows Forms controls. So, people that already have experience in developing Forms application will find these renderable controls very easy to use. In the demo archive, you'll find the Odyssey UI.dll. It can be referenced from any C# MDX project and it is the easiest way to use this library. Otherwise, you can compile the source code. To use the library in your code, you have to follow these easy steps:

  1. Reference the AvengersUTD.Odyssey.UserInterface namespace.
  2. You have to let Odyssey UI manage Windows Forms events. For your convenience, you can call the supplied method UI.SetupHooks(form);).
  3. Assign to UI.Device your DirectX device object. Throughout the code, there are several ''device'' calls, so this avoids you having to pass the device reference every call.
  4. Create a HUD object. The HUD is the on-screen overlay of the User Interface.
  5. Tell the HUD that you're starting to design the UI, hud.BeginDesign();.
  6. Create the controls as you would do when coding Windows Forms applications.
  7. Add the controls to the HUD container, hud.Add(control);. Note that the top level children of the HUD are to be understood as if they were on the desktop. So it is your responsibility to avoid making them overlap. If you want multiple windows, add the control inside a window and then add the window to the HUD instead.
  8. Assign events, if necessary.
  9. When you are done creating the UI, use hud.EndDesign();.
  10. Assign the HUD object created this way to be the CurrentHUD of the User Interface, UI.CurrentHUD = hud;. This allows you to specify different HUDs and change HUD with ease.
  11. Finally, in your render loop you just have to call hud.Render();.

The following is the sample code to render the interface you see in the image:

// Add these lines where appropriate in your code:

// (provided that you did all the above steps also)


UI.Device = yourDirectXDevice;
UI.SetupHooks(form);

// Create a new hud object. The string parameter

// is its ID: it will be used in the future

// when the library will allow users

// to "skin" via xml the user interface.

// ScreenSize refers to a size variable that represents

// your current resolution. The HUD should always be set

// to be as big as it can be.


HUD hud = new HUD("TestHud", Settings.ScreenSize);

private void TestUI()
{
    // Start designing the UI

    hud.BeginDesign();

    // Create a panel control;

    Panel panelTest = new Panel("UI Test Panel", 
        new Vector2(25, 150), new Size(520, 400));

    // Create two labels. The Vector2 parameter

    // refers to its position in the parent control.

    // Since the labels are going to be

    // added to the previous panel, the

    // absolute position of the first

    // one will then be: (X: 25 + 20, Y: 250 + 20).

    // The alignment parameters are used

    // to specify how you want to draw the text.

    // The first label can be highlighted, hence the 

    // extra color value in the constructor.

    
    Label lTest = new Label("LabelTestPanel", 
                  "The blue window is a Panel" + 
                  " Control and this is a Label",
                  Alignment.Left, Alignment.Top, 
                  new Vector2(10, 10), Color.White, Color.Red);

    Label lTb = new Label("LabelTrackBar", "This TrackBar control " + 
                "goes from 0 to 10 with a\n'TickFrequency' value of 2",
                Alignment.Left, Alignment.Top, 
                new Vector2(20, 40), Color.LightGreen);

    // This is a button. We have attached a delegate

    // to its "MouseClick" event: it will be fired

    // when the user clicks on the button.

    
    Button example = new Button("ButtonExample", "This is a button", 
        new Vector2(20, 320), new Size(200, 50));
    example.MouseClick += delegate(BaseControl sender, 
        System.Windows.Forms.MouseEventArgs e)
    {
        example.Label = "Yep you clicked me";
    };
    
    // This button opens a modal dialog box.

    // In windows forms the MessageBox.Show method is "blocking"

    // it means that the program does not continue to the 

    // "next line" until the user presses one of the dialog's buttons.

    // Since simulating that behavior would have taken too much time

    // for the time being you have pass a delegate method as a parameter

    // that tells what you want to do. Just pass null if you simply

    // want the window to close.

    
    Button dialogTest = new Button("DialogTest", "Show me a dialog", 
        new Vector2(300,320), new Size(200,50) );
    dialogTest.MouseClick += 
        delegate(BaseControl sender, 
        System.Windows.Forms.MouseEventArgs e)
    {
        DialogBox.Show("Test", 
            "Do you like this User Interface?\n\nBy the way, " + 
            "this dialog is modal!",
            DialogBoxButtons.YesNo,
            delegate(BaseControl ctl, DialogResult dialogResult)
        {
            if (dialogResult == DialogResult.No)
                DialogBox.Show("Really?", 
                "Sigh.... :(", DialogBoxButtons.Ok, null);
            else
                DialogBox.Show("Thanks", 
                "I'm glad that you liked it!\n\nIf you have any " + 
                "feedback drop me a line at avengerdragon at gmail.com " + 
                "or visit my forum at " + 
                "[hover=\"Aquamarine\"]http://starodyssey.avengersutd.com[/]",
                DialogBoxButtons.Ok, null);
        });
    };

    // This is a trackbar control. You have to set

    // the trackbar minim value, tick Frequency

    // and maximum values with the SetValues method.

    // You can also attach a delegate method for

    // its "ValueChanged" event.

    
    TrackBar slider = new TrackBar("TrackBar", 
        new Vector2(20, 100), new Size(200, 30));
    slider.SetValues(0, 2, 10);
    slider.ValueChanged += delegate(BaseControl ctl) {
        lTb.Text = "The trackbar value is now: " + slider.Value;
    };

    // This is a textbox. When you click on it, you can start typing.

    
    TextBox tb = new TextBox("TextBox",
        new Vector2(20, 140), new Size(200, 30), 24);
    tb.Text = "This is a textbox";

    // This is a groupbox control: a simple panel

    // with a flat border and a caption.

    
    GroupBox gb = new GroupBox("GroupBox", "This is a groupbox", 
        new Vector2(20, 200), new Size(200, 100),
        Color.White, BorderStyle.Flat);

    // This is an OptionGroup control: a collection of radio buttons.

    // The string array passed as a parameter

    // will be used to dynamically create an option button

    // for each of the strings. You can also attach

    // a delegate too its "SelectedIndexChanged" event

    
    OptionGroup og = new OptionGroup("OptionGroup", new string[] {
        "This is", "the OptionGroup", "control"}, 
        new Vector2(5, 10), new Size(100, 30));
    og.SelectedIndexChanged += delegate(BaseControl ctl)
    {
        gb.Caption = "You clicked the OptionButton number: " + 
            og.SelectedIndex;
    };
    
    // This is the CheckBox Control. You can access its 

    // selected value through its .IsSelected property.

    
    CheckBox cb = new CheckBox("CB1", "Checkbox", 
            new Vector2(300, 300), new Size(100,30));

    // This is the DropDownList control also known as

    // a combobox.

    
    DropDownList ddl = new DropDownList("DDL",
        new string[] { "This", "is the", "DropDownList", "control" },
        new Vector2(300, 100), new Size(150, 30));    

    // Next, we'll  create three windows.

    // We'll then create three controls to go inside those 

    // windows: a RichTextArea, a Table and a TabPanel

    
    Window win1 = new Window("win1", 
        "Test Window #1", new Vector2(500, 100), new Size(640, 480));
    Window win2 = new Window("win2", 
        "Test Window #2", new Vector2(550, 110), new Size(640, 480));
    Window win3 = new Window("win3", 
        "Test Window #3", new Vector2(600, 120), new Size(640, 480));
    
    // This is the RichTextArea control. It is a panel that 

    // automatically formats input depending on BBCode like

    // string. We simply pass the string to be formatted and the

    // style to use as default (if the default one is Arial 20pt 

    // for example, the bold command will apply the bold effect

    // on the Arial 20pt font)

    // Accepted commands are b,i,s for bold, italic and shadowd

    // respectively and c or color for the standard color and

    // h or hover for the color to use when the mouse pointer

    // is over the label. Nested markup is not supported at

    // the moment.

    // We pass an empty vector because we want it to cover

    // the whole internal area of the window. We manually

    // compute its size because there's no "autosize" feature yet.

    
    RichTextArea rta = new RichTextArea("RTA", 
        Vector2.Empty, new Size(632, 300), rtext, TextStyle.Default);
        
    // This is the TabPanel control. A Panel that has some

    // buttons on the top that allow the user to access different

    // pages in it. Each page in this example has a label control.

    // You can switch page by clicking the top buttons.

    
    TabPanel tabPanel = new TabPanel("Tab", 
        new Vector2(30, 50), new Size(310, 200));
    tabPanel.AddTab("Page 1");
    tabPanel.AddControlInTab(new Label("pag1", 
        "Page 1", Alignment.Left, Alignment.Top,
        new Vector2(100, 20), Color.LightGreen), 0);
    tabPanel.AddTab("Page 2");
    tabPanel.AddControlInTab(new Label("pag2", 
        "Page 2", Alignment.Left, Alignment.Top,
        new Vector2(100, 20), Color.LightGreen), 1);
    tabPanel.AddTab("Page 3");
    tabPanel.AddControlInTab(new Label("pag3", 
        "Page 3", Alignment.Left, Alignment.Top,
        new Vector2(100, 20), Color.LightGreen), 2);    
        
    // This is the table control. You can esaily format by choosing

    // different TableStyle parameters

    
    Table table = new Table("Table", 3, 2, new Vector2(15, 15));
    table[0, 0].Text = "This";
    table[0, 1].Text = "is the";
    table[1, 0].Text = "Table";
    table[1, 1].Text = "control!";
    table.Format(new TableStyle(150, 30, 1, 1, Border.All));
            
    // Finally we add each control to its parent container.

    
    gb.Add(og);
    panelTest.Add(lTest);
    panelTest.Add(lTb);
    panelTest.Add(slider);
    panelTest.Add(tb);
    panelTest.Add(gb);
    panelTest.Add(ddl)
    panelTest.Add(example);
    panelTest.Add(dialogTest);
    
    win1.Add(rta);
    win2.Add(tabPanel)
    win3.Add(table);
    
    hud.Add(panelTest);
    hud.Add(win1);
    hud.Add(win2);
    hud.Add(win3);
    
    // Signal the hud object that we're doing creating controls

    
    hud.EndDesign();
}

// After having called the TestUI method

// somewhere in yor app before rendering,

// in your render loop you have to place

// the following line:


public void Render()
{
    hud.Render();
}

Points of interest

I tried to mimic the Windows Forms event style and the result looks very similar to it. In the development of my game, it showed to be very helpful because once the needed controls are implemented and fully working, you can concentrate on the game itself, speeding things along. These are the main features of the UI:

The following controls are included:

It should be noted that by deriving or improving the PictureBox control you can theoretically develop a whole new set of textured controls, in addition to the renderable ones. You could even combine them to achieve new effects. There are several possibilities. More controls are on the way. To stay updated on the development of this library, refer to the project page at the Star Odyssey website. Please post any bugs you find and requests on the forums.

The Odyssey UI is released under the Creative Commons Attribution NonCommercial license. This source code can be modified as you wish and if you do decide to use it in your project, please contact me telling me about it so we can share links if you'd like. Thanks for reading!

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralColors
lordofthedoom
9:30 28 Dec '09  
Hi, can you tell me how can i change background color from that blue to for example green or else ? or how can i load another texture on background ?? thanks a lot...
GeneralSource?
justchat
15:05 15 Jul '09  
The website seems to be down...where can we get the latest version of the source? Specifically the version that doesn't require shader 2.0
Generalhow display image?
Member 2074002
19:03 18 Nov '08  
I use picturebox from this library, but my panel is hidden back behind of Picturebox, what is your idea?
GeneralRe: how display image?
AvengerDr
22:45 18 Nov '08  
Mmm are you talking about a windows.forms panel or a panel from my library?
Could you mail me a screenshot? Email is on my website (avengerdragon /at/ gmail.com)
GeneralRun time error
Member 2074002
19:14 17 Nov '08  
hi, when I call Render() Function after testUI() I get this error:
"Error in Application" .Now I have some questions:
1- what is form in UI.setHooks(form)? Is it a Win Form?
2- where should I call Render?
please Help me and tell me a correct solution
Thanks very much !
email : mehrdadsilver@yahoo.com Smile
GeneralRe: Run time error
AvengerDr
22:41 18 Nov '08  
Are you using the last version? If not, please download it from my website at www.avengersutd.com

1) Yes usually it is a form. It can also be a generic control.. It's the area where you should capture mouse and keyboard input from. So it can also be a panel but I've not tried that.
2) In your render loop.. It has to be called each frame.

If you are still getting errors, be sure to debug it and tell me the line that is causing problems (if you are also compiling my source code).
GeneralSolution Code Please
Madmaximus
5:25 21 Aug '08  
When I run the demo I get this error:
Source : Microsoft.DirectX.Direct3D
Method : .ctor
Date : 10:13:18 AM
Time : 8/21/2008
Computer :
Error : Error in the application.
Stack Trace : at Microsoft.DirectX.Direct3D.Device..ctor(Int32 adapter, DeviceType deviceType, Control renderWindow, CreateFlags behaviorFlags, PresentParameters[] presentationParameters)
at AvengersUTD.StarOdyssey.StarOdysseyEngine.CreateDevice()
at AvengersUTD.StarOdyssey.StarOdysseyEngine..ctor()
at AvengersUTD.Start.Main()
^^-------------------------------------------------------------------^^

Can you please provide solution code, this will help with the setup of the project too.

Thanks,
Ken
GeneralRe: Solution Code Please
AvengerDr
5:47 21 Aug '08  
From the stack trace it looks like your device may not support some of the presentation parameters that I'm initing the device with. Most likely it's either hardware vertex processing or multisampling. I suggest you disable those.

Anyway you may want to look at the website, here- where I posted a new version that now supports SlimDX too.
Generalplease make in C++ code
hardcorelife
22:43 9 Jul '08  
Good job, wonderful but i don't know C#..
GeneralWhy do I need DirectX SDK installed?
triplebit
21:56 30 Jun '08  
Here is a quot from the article-
"Please note that in order to run the sample, you need the DirectX SDK installed"

Is it neede also when using the release version?

Regards

mandy
GeneralUsing in a standard winform application
triplebit
10:45 1 Jun '08  
Can I use it in a none directx application(and how)?
Regards
Izack
Generalcorrupt files
petr12345
0:17 20 Nov '07  
Hi! All your RAR files seem to be corrupt. I have downloaded form every possible source and it seems there is some problem with the RAR software you used. Please update your files and/or use the .zip format.


Petr12345
GeneralRe: corrupt files
AvengerDr
13:46 24 Nov '07  
I just tried to download it from my web page and it works. Please check again and let me know!
GeneralC++
ortsa
5:54 17 Nov '07  
Possible c++ port/version?
GeneralRe: C++
AvengerDr
13:47 24 Nov '07  
Unfortunately I'm not quite up to the task for a C++ port.. I do not have much experience in C++ coding.. but if someone would like to port it I'd be sure to offer any assistance.
GeneralCorrupt files
isthereaproblem
20:48 15 Oct '07  
Hi! All your RAR files seem to be corrupt. I have downloaded form every possible source and it seems there is some problem with the RAR software you used. Please update your files.
GeneralWebsite
SatelliteCoder
10:08 11 Oct '07  
Hi,
I really love your engine! Smile It rocks! But I really like to use your v0.3.4 version, but when I try to download it from your website, the file seems to be corrupted. Could you send me a new version or update your website, so I could play with your updated version? Thanks a lot!
GeneralDoesn't work when window is resized
-masterchief-
23:32 30 Jul '07  
When I resize then window everything is scaled properly, but if I try to use a control it doesn't work.
Besides this bug excellent work.

GeneralRe: Doesn't work when window is resized
AvengerDr
9:40 31 Jul '07  
Thanks! That is probably happening because there is not (yet) a "OnResize" event of some sort, so when that happens the HUD still "thinks" that it has the original resolution. It will be addressed in a future release. If you found more bugs please submit them or (better) on my forums so I can keep track of them!

Adal
GeneralReally neat!
J. Dunlap
9:32 28 Jul '07  
Great job! Big Grin

But given that this is an article on a coding site, wouldn't it be good to include some details in the article about how you went about rendering the controls, dealing with events, etc?


GeneralRe: Really neat!
AvengerDr
12:16 28 Jul '07  
Thanks for the feedback Smile
Yes you're right, in the next update I'll try to share some of knowledge I gained during the development of this library. I'd do it right away but I'm in the process of adding yet more features. So you'll have to wait for a bit Smile But if anyone needs to ask some questions, you can either post here or in the forums.

Thanks again for the interest,


Adal
GeneralUpdated demo with no shader request
AvengerDr
0:31 26 Jul '07  
Hi there, I uploaded an updated version of the demo that does not require shaders. I had the check in it because my game uses SM2.0 but the Odyssey UI can do without it.
GeneralVery nice
Quartz.
6:12 15 Jun '07  
i was looking for this , 5 stars Smile from me



Omit Needless Words - Strunk, William, Jr.

Vista? Photoshop Preview Handler

GeneralAwesome
merlin981
4:13 15 Jun '07  
I've had this idea for a long time, but never had a chance to work on it. Thank you for posting this, I can't wait to use it.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I theme/skin my controls and apps with Themer
I get my developer tools from Merlin A.I. Soft
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

NewsUpdated version
AvengerDr
16:24 14 Jun '07  
Hello there,
I updated a new version that includes new controls and new feature. Please let me know if anything is wrong in this article page. To stay updated, please check our forums often!
Thanks!


Last Updated 24 Jul 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010