Backgrounds, Graphics, Text and Models Examples

The visual part of a menu requires you to add a background and place some decorative graphics, text or models on it. We will look at some examples of how to accomplish that here.

We will start off with our minimal script file and build from there :

    #include "ui/menudef.h" 
    {
      assetGlobalDef
      {
        smallFont "fonts/smallfont" 12
        font "fonts/font" 16
        bigFont "fonts/bigfont" 20
        cursor "menu/art/3_cursor3.tga"
        itemFocusSound "sound/misc/menu2.wav"
        fadeClamp 1.0
        fadeCycle 1
        fadeAmount 0.1
      } 

      menuDef
      {
        name "main"
        fullScreen MENU_TRUE
      }
    }  

This is our main menu at its simplest. We will expand on it by adding a background and some graphical items. It will be assumed that all graphics for the menu are stored in the ui/assets directory.

FAKK 2

Our first example will be recreating the look of the FAKK 2 main menu. The following graphic is the background used by FAKK2 for it's menus.

This will used in the menuDef section as the background graphic. We'll setup the menuDef with a window style of WINDOW_STYLE_SHADER in order to display this graphic correctly. We'll also add the focus color and the onOpen and onESC commands to complete the overall information section.

      menuDef
      {
        name "main"
        fullScreen MENU_TRUE
        background "ui/assets/fakkback.tga"
        style WINDOW_STYLE_SHADER
        focusColor 1 .75 0 1

        onOpen { playlooped "music/sonic1.wav" }
        onESC { uiScript "quit" }
      }        

With this menuDef we have a background graphic and some music playing. We also can quit by pressing the ESC key. Next, we need to add some graphical items to expand the look of the menu.

One of the neat things about FAKK2 menus is the smoke that blows across the background, yet remains behind all of the other menu items. We'll see how to add that smoke here.

First, we need a shader that will create smoke that moves. Since you will probably be using other shaders in the menus it would be best to create a new shader file just for the menu. Place this shader in it.

    ui/assets/smoke
    {
	    {
       blendFunc GL_SRC_ALPHA GL_ONE
       map ui/assets/smoke.tga
       tcmod scroll .1 0.1
       rgbgen identity
     }
    }

The graphic used for this shader is :

Now let's create the smoke item. This should be the first item placed in the menuDef so it will be drawn on top of the menuDef background but underneath everything else. This is a simple decorative item that just displays the above shader. It will be visible when the menu opens.

    menuDef
    {
      name "main"
      fullScreen MENU_TRUE
      background "ui/assets/fakkback.tga"
      style WINDOW_STYLE_SHADER
      focusColor 0 .75 0 1

      onOpen { playlooped "music/sonic1.wav" }

      itemDef
      {
name menusmoke
style WINDOW_STYLE_SHADER
rect 0 0 640 480
background "ui/assets/smoke"
visible MENU_TRUE
decoration
} }

Since we want the smoke to cover the entire screen we set the window size to 640x480, origined at (0,0). The window style is WINDOW_STYLE_SHADER so the item will draw our smoke shader in the window.

The last thing to go onto the menu is the graphic of the main character, Julie. This is drawn on top of the smoke so we will define these items after the menusmoke item. Julie is made up of three graphics, so we will need three items to draw them. The graphics used are :

 

Once again, these items are visible, decorative and displaying a graphic.

    menuDef
    {
      name "main"
      fullScreen MENU_TRUE
      background "ui/assets/fakkback.tga"
      style WINDOW_STYLE_SHADER
      focusColor 0 .75 0 1

      onOpen { playlooped "music/sonic1.wav" }

      itemDef
      {
name menusmoke
style WINDOW_STYLE_SHADER
rect 0 0 640 480
background "ui/assets/smoke"
visible MENU_TRUE
decoration
} itemDef {
name julie1
style WINDOW_STYLE_SHADER
rect 54 0 256 256
background "ui/assets/julie_1.tga"
visible MENU_TRUE
decoration
}
itemDef {
name julie2
style WINDOW_STYLE_SHADER
rect 0 256 256 256
background "ui/assets/julie_2.tga"
visible MENU_TRUE
decoration
}
itemDef {
name julie3
style WINDOW_STYLE_SHADER
rect 256 256 128 256
background "ui/assets/julie_3.tga"
visible MENU_TRUE
decoration
}
}

Each item has a window area the same size as the graphic it displays and origined so they line up correctly on the screen.

To show how to put decorative text in a menu we'll add something not in the FAKK 2 menu, a copyright notice at the bottom of the screen. To have the text display over top of all the preceding graphics we'll define the text item last. Also we'll look at different ways of displaying the text by using backgrounds.

The first display method will be just the text with no background of any kind. This will use the default window style, be visible and decorative.

      itemDef 
      {
name copyright
style WINDOW_STYLE_EMPTY
rect 0 420 640 30
text "Copyright by Reaction Factory 2005" forecolor 0 0 1 1 textstyle ITEM_TEXTSTYLE_SHADOWED textalign ITEM_ALIGN_CENTER textalignx 320 textaligny 24 textscale 0.4
visible MENU_TRUE
decoration
}

The area we wish to display our text in is at the bottom of the screen, origin (0,420), and extends across the entire menu. The text color is set to blue by the forecolor command and the text style is shadowed. We want the text centered on the screen so we set the horizontal alignment point to the center of the text string and offset this point to the center of the screen (320 pixels from the left). The vertical alignment sets the bottom of the text 6 pixels above the bottom of the window area (30-24=6). Lastly the size of the text is set to 19 pts (48x0.4).

This is pretty simple text and has many uses in menus. The next display method will place the text over top of a solidly filled red box. This requires a few changes to the previous item definition.

      itemDef 
      {
name copyright
style WINDOW_STYLE_FILLED
rect 100 420 440 30
text "Copyright by Reaction Factory 2005" forecolor 0 0 1 1 backcolor 0.5 0 0 1 textstyle ITEM_TEXTSTYLE_SHADOWED textalign ITEM_ALIGN_CENTER textalignx 220 textaligny 24 textscale 0.4
visible MENU_TRUE
decoration
}

The first thing you'll notice is the change to the window style. To put color into the window the style must be WINDOW_STYLE_FILLED. The background color of the window is determined by the backcolor command, which in this case is red. Since we didn't want the box going the full width of the screen, we changed the origin and size so it is smaller but still centered horizontally. Since the box is smaller in width, we had to change the horizontal offset so the text would still be centered in the box.

This is a pretty bland looking box, being just a solid color, so we probably will want to spice it up a little. One thing that can be done is to add some borders to the box. A black border all the way around should look nice.

      itemDef 
      {
name copyright
style WINDOW_STYLE_FILLED
rect 100 420 440 30
text "Copyright by Reaction Factory 2005" forecolor 0 0 1 1 backcolor 0.5 0 0 1 textstyle ITEM_TEXTSTYLE_SHADOWED textalign ITEM_ALIGN_CENTER textalignx 220 textaligny 20 textscale 0.4 border WINDOW_BORDER_FULL bordersize 4 bordercolor 0 0 0 1
visible MENU_TRUE
decoration
}

This adds a 4 pixel wide black border all the way around the window area. You'll notice that we had to change the vertical alignment from 24 to 20 to allow for the border.

One last modification we can make to the box is to change the window style from WINDOW_STYLE_FILLED to WINDOW_STYLE_GRADIENT. This will make a red gradient background, for a somewhat different look.

      itemDef 
      {
name copyright
style WINDOW_STYLE_GRADIENT
rect 100 420 440 30
text "Copyright by Reaction Factory 2005" forecolor 0 0 1 1 backcolor 0.5 0 0 1 textstyle ITEM_TEXTSTYLE_SHADOWED textalign ITEM_ALIGN_CENTER textalignx 220 textaligny 20 textscale 0.4 border WINDOW_BORDER_FULL bordersize 4 bordercolor 0 0 0 1
visible MENU_TRUE
decoration
}

Jedi Knight II

The next example we will examine is the main menu of Jedi Knight II. This menu is put together a little differently than the FAKK 2 menu in that it doesn't use a background in the menuDef. We will start off then with this menuDef :

      menuDef
      {
        name "main"
        fullScreen MENU_TRUE
        focusColor 1 .75 0 1

        onOpen { playlooped "music/sonic1.wav" }
        onESC { uiScript "quit" }
      } 

Since we still need some kind of background we'll use an item to display it. The graphic used by Jedi Knight II is this :

We'll use a decorative, visible, graphic item covering the entire screen to display the background. This item must be the first item defined so everything else is drawn on top of it.

      menuDef
      {
        name "main"
        fullScreen MENU_TRUE
        focusColor 1 .75 0 1

        onOpen { playlooped "music/sonic1.wav" }
        onESC { uiScript "quit" }

        itemDef
        {
name frame_pic
style WINDOW_STYLE_SHADER
rect 0 0 640 480
background "ui/assets/menu1.jpg"
visible MENU_TRUE
decoration
} }

Next comes the light saber glow and halo on the left side of the screen. This is done using two items, one for the glow and one for the halo. Both of these use shaders to create the required effect so we'll add those to our shader file now.

    ui/assets/menu3
{
nopicmip nomipmaps
{
map ui/assets/menu3.jpg
blendFunc GL_ONE GL_ONE
}
{
map ui/assets/menu3.jpg
blendFunc GL_ONE_MINUS_DST_COLOR GL_ONE
rgbGen wave sawtooth 0.15 0.2 0 123
tcMod stretch sawtooth 1 0.1 0 179
}
}
ui/assets/menu2
{
nopicmip
nomipmaps
{
map ui/assets/menu2b.jpg
blendFunc GL_ONE GL_ONE
rgbGen vertex
alphaGen wave sin 0 1 0 1
tcMod rotate 10
}
{
map ui/assets/menu2b.jpg
blendFunc GL_ONE GL_ONE
detail
rgbGen vertex
tcMod rotate -5
tcMod scale -1 1
}
}

With the shaders done we can create the items. These are just simple decorative, visible items displaying a graphic.

    itemDef 
{
name saberglow
style WINDOW_STYLE_SHADER
rect 30 0 90 480
background "ui/assets/menu3"
visible MENU_TRUE
decoration
}
itemDef
{
name saberhalo
style WINDOW_STYLE_SHADER
rect -425 -185 1000 1000
background "ui/assets/menu2"
forecolor 0.7 0.7 0.7 1
visible MENU_TRUE
decoration
}

The saberhalo item has a couple of interesting features. First, you'll notice that a foreground color has been defined. This color is used (by the window style WINDOW_STYLE_SHADER) to tint the graphic being displayed. Without this color tint you'd find the halo is so bright that much of the detail is lost. By tinting it with a grey color the brightness is reduced and detail is restored. Second is the window area. Since they wanted the halo to be large the window area was made large, 1000x1000. Any of the halo that is outside the screen area of 640x480 is not drawn so a large window is acceptable to the program. Also, since they wanted the halo to be over to the left side, they set the window origin to negative values, effectively moving the halo to the left and up on the screen. Origins off the screen are allowed but, again, any part of the item not on the screen is not drawn.

Lastly comes the title graphic. Again, it uses a shader to generate some effects on the graphic so we'll add that to our shader file.

    ui/assets/menu4
    {
      nopicmip
      nomipmaps
      {
        map ui/assets/menu4.tga
        blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
      }
      {
        map ui/assets/menu5.jpg
        blendFunc GL_ONE_MINUS_DST_ALPHA GL_ONE
        tcMod scale 0.5 1
        tcMod scroll -0.15 0
        detail
     }
   }

The item is, once again, visible, decorative and graphic displaying.

    itemDef 
    {
      name starwars
      style WINDOW_STYLE_SHADER
      rect 143 12 470 93
      background "ui/assets/menu4"
      visible MENU_TRUE
      decoration
    }

The Jedi Knight II menu has one more feature to make it stand out - a rotating model of a light saber. We'll see how to add a model to a menu and how to make it rotate.

To add a model to the menu we must create an item to display the model. The item to display the Jedi Knight II light sabers model would be as follows :

    itemDef
{
name logomodel
type ITEM_TYPE_MODEL
rect -123 48 400 400 asset_model "models/map_objects/bespin/jk2logo.md3"
model_angle 90
model_rotation 3.5
model_fovx 40
model_fovy 40
visible MENU_TRUE
decoration
}

By setting the item type to ITEM_TYPE_MODEL the item will display the model we define using the asset_model command, which in this case is the JKII logo model. The item window area is set to 400x400 and the model will always be centered in this area. The window origin set to an off screen point (-123,48) so the model will be located at the center of the halo.

We must specify the model's FOV for both X and Y directions in order to set the displayed size of the model. If model_fovx and model_fovy are set to 90 the model will be displayed in its actual size. In this case it is much too small so we must reduce the FOVs to make the model display larger. An FOV of 40 is about right. To avoid distorting the model when it is displayed make both the X and Y FOVs the same.

Lastly, we want the model to rotate. The model_angle command sets the starting angle of the model and the model_rotation command sets the speed of the rotation (1 degree in 3.5 milliseconds).

Quake 3 Arena

One last example will be the Quake 3 Arena main menu. This is a fairly simple menu but it does demonstrate the use of models and text. The menu has a background graphic (the Quake 3 symbol) so we'll start with that. It will be the background for the menuDef, although we could use an item to display it, ala Jedi Knight II.

      menuDef
      {
        name "main"
        fullScreen MENU_TRUE
        focusColor 1 .75 0 1
        background "textures/sfx/logo512.tga"

        onOpen { playlooped "music/sonic1.wav" }
        onESC { uiScript "quit" }
      }   

The flaming Quake III symbol at the top of the menu screen is actually a model that we will now add to the definition.

    itemDef
{
name logomodel
type ITEM_TYPE_MODEL
rect 0 -15 640 150 asset_model "models/mapobjects/banner/banner5.md3"
model_angle 180
model_fovx 75
model_fovy 30
visible MENU_TRUE
decoration
}

Since the model will be centered in the item window area we can make it the window the full width of the screen (640 wide). The window height must be enough to display the entire model at the size we set. A height of 150 seems to work okay. Since the model is also centered vertically we have to move the Y origin to off the screen to remove any blank space above the model. The model_angle value of 180 means we will view the model head on from the front. The actual model size is too small to fill the window properly so we have to decrease the FOVs from the normal 90 to make the model display larger. The actual FOV values were found by trial and error so the model fit the area correctly and wasn't distorted.

In Quake 3 the logo model moves back and forth across the screen by modifying the viewing angle (set by model_angle). Unfortunately, we can't duplicate that movement in our script as the commands are not avalible.

The last part of the menu is the copyright text at the bottom of the screen. We'll use a normal text item to display this.

      itemDef 
      {
name copyright
style WINDOW_STYLE_EMPTY
rect 0 450 640 30
text "Quake III Arena(c) 1999-2000, Id Software, Inc. All Rights Reserved" forecolor 0.5 0 0 1 textstyle ITEM_TEXTSTYLE_NORMAL textalign ITEM_ALIGN_CENTER textalignx 320 textaligny 24 textscale 0.33
visible MENU_TRUE
decoration
}

The text size is 16 pt (48x0.33) and is colored a light red. It is centered on the screen very near the bottom (the text bottom is at 450+24 = 474).

 

Return to Home Page