Game Development Community

dev|Pro Game Development Curriculum

2D Tuesday: Fancy Hud

by Michael Perry · 06/26/2012 (2:42 pm) · 27 comments

2D Tuesdays: Fancy HUD


static.garagegames.com/static/pg/blogs/michael-perry/TorqueLogoSmall.png

Kickoff

Greetings everyone. It's 2D Tuesday! Each week someone on the 2D team will post a blog or resource related to Torque 2D and/or iTorque 2D. The majority of the posts will come from myself, but don't be shocked if someone else takes over for me from time to time.

Last week, I wrapped up the Box2D discussion. I had originally planned to write a lengthy blog about behaviors, but there was a snag. As I stated in my previous posts, I'm going to be pulling a lot of stuff from archived e-mails and internal discussions/wikis. This allows me to post without eating up significant development time. Unfortunately, the past week has been very crazy for the development team. I stand by priorities, which means this week's post is going to be very lean. Actual development on the 2D engines is what everyone wants, but I don't want to break my streak of 2D blogs.

First, here's the "let's cover our bacon section":


static.garagegames.com/static/pg/blogs/michael-perry/TorqueLogoSmall.png

FULL DISLOSURE

Do not take the content from these blogs as law. I'm never going to say "this will be in x.x version" or "this is ready to be used right now". There's going to be a lot of R&D discussion. I might even post a discussion I had with Melv that ended up being scrapped. It might be useful for you to understand how we communicate internally, or amusing to see the mad scientists we really are. I will not post timelines. I will not post release dates. I will not commit the team to something we cannot deliver on.


static.torquepowered.com/static/pg/blogs/michael-perry/separatorz.jpg

static.garagegames.com/static/pg/blogs/michael-perry/TorqueLogoSmall.png

Sprite-based HUD

The process for using a second level as your interface is really simple. I have attached three screenshots to illustrate the setup.

Game Level
static.garagegames.com/static/upload/emp-44571/GameLevel.png
This was a simple game level I set up, called "level.t2d". This where I create my game objects, like a player, tiles, etc. It has a space ship that constantly flies to the right.

HUD Level
static.garagegames.com/static/upload/emp-44571/HudLevel.png
This is a completely new level I created to contain my HUD, called "hud.t2d". This contains my player health sprite, power-up sprite and a particle effect that connects the two.

Final Result
static.garagegames.com/static/upload/emp-44571/HudFinalResult.png
This is the game running outside of the editor. As you can see, it contains both levels. Additionally, the HUD level is on top (which is what you want for an interface)

Here are the steps to reproduce my example:

1. Create your game level (which you have already done)
2. Create your HUD level (contains your interface)
3. Open game/gui/mainScreen.gui and look for this code:

new t2dSceneWindow(sceneWindow2D)
{
   canSaveDynamicFields = "0";
   isContainer = "0";
   Profile = "GuiContentProfile";
   HorizSizing = "width";
   VertSizing = "height";
   Position = "0 0";
   Extent = "1024 768";
   MinExtent = "8 8";
   canSave = "1";
   Visible = "1";
   hovertime = "1000";
   lockMouse = "0";
   useWindowMouseEvents = "1";
   useObjectMouseEvents = "1";
};

4. Add the following code immediately after that block:

new t2dSceneWindow(hudWindow)
{
   canSaveDynamicFields = "0";
   isContainer = "0";
   Profile = "GuiContentProfile";
   HorizSizing = "width";
   VertSizing = "height";
   Position = "0 0";
   Extent = "1024 768";
   MinExtent = "8 8";
   canSave = "1";
   Visible = "1";
   hovertime = "1000";
   lockMouse = "0";
   useWindowMouseEvents = "1";
   useObjectMouseEvents = "1";
};

5. Locate your load level code.

Torque 2D: Open game/gameScripts/game.cs and look for this code:

sceneWindow2D.loadLevel(%level);

iTorque 2D: Open projectFiles/scripts/game.cs, look for the above code.

6. Change that line of code to explicitly load your game level:

sceneWindow2D.loadLevel("game/data/levels/level.t2d");

7. Directly beneath that code, add the following:

hudWindow.loadLevel("game/data/levels/hud.t2d");

Now for the explanation of what's going on. A t2dSceneWindow is a GUI that remains static to your game window. It also contains a camera and various other functions. A t2dSceneWindow is responsible for loading your levels. In a stock T2D project, you only get one t2dSceneWindow which loads a level at the start. That is the sceneWindow2D.loadLevel() call in startGame.

Because you want to load two separate levels and show them at the same time, you need a second t2dSceneWindow. That is where the hudWindow comes into play. You have to create a new one (which is added to mainScreen.gui), which will be responsible for loading your interface (hudWindow.loadLevel("game/data/levels/hud.t2d") ).

The reason I said you should explicitly change the sceneWindow2D.loadLevel(%level), is because that %level variable is set by the game editor to whatever level you were last working on. This can be bad, since you want to load and render two separate levels in a specific order.

That's about it. If you have any specific questions about this example, I'm more than happy to answer them.


static.garagegames.com/static/pg/blogs/michael-perry/TorqueLogoSmall.png

Next Time

That's it for this week folks. Sorry I couldn't deliver on an epic discussion of behaviors, but hopefully the fact that we are working feverishly on the tech and still willing to post at least something will satisfy everyone. Behaviors next week. Oh! Also, iTorque 2D 1.5.1 Preview is going out tomorrow. It's not an Earth shattering release, but it should help a few of you wrap up your existing games and support newer iOS devices.

VOTE TIME!

You get to decide the content of next week's blog by picking one of the following choices:

1. Why behaviors rock and how they are going to become more epic!
2. How we were able to remove 45 kilograms of dirt and cobwebs from the editor system!

Post a reply with your vote.
Page «Previous 1 2
#1
06/26/2012 (3:26 pm)
I vote for '1. Why behaviors rock and how they are going to become more epic!'
#2
06/26/2012 (3:33 pm)
A little off subject:

Some of the best features of iTorque are the auto datablock management system and the gui system. Why is GG trying to get rid of these features. I think GG should be improving them and encouraging users to use them.

I hope the new iTorque improves on the two features listed above.

BTW behaviors is another great feature and I'm glad you're not trying to get rid of that one :)
#3
06/26/2012 (3:38 pm)
Awesome post for having little time.

I'd like to add to this that when implementing this in my game I had come up with a simple modification of an existing bit of code from levelSelect.cs from one of the demos.

I established the basic notion of having Pre/PostLoad and End events for levels.

$levelLoading = false;


function startLevel(%level)
{
	if(strpos($SelectedLevel, "battle.t2d") >= 0){
		BattleEnd();
	}
	echo("starting level" SPC %level);
	$SelectedLevel = %level;
   if(!$levelLoading)
   {
      $levelLoading = true;
      schedule(100, 0, transitionLevel);
   }
}

function transitionlevel()
{
	sceneWindow2D.endLevel();
	sceneUIWindow2D.endLevel();
	schedule(100, 0, loadLevel);
}

function loadLevel()
{
	
	preLevelLoad();
	if(strpos($SelectedLevel, "data/levels/") < 0){
		$SelectedLevel = "data/levels/" @ $SelectedLevel;
	}
   // Load the .t2d file for this game
   sceneWindow2D.loadLevel($SelectedLevel);
	postLevelLoad();
   $levelLoading = false;
}

function preLevelLoad(){
	if(strpos($SelectedLevel, "battle.t2d") >= 0){
		BattlePreLoad();
	}
}


function postLevelLoad(){
	if(strpos($SelectedLevel, "battle.t2d") >= 0){
		BattlePostLoad();
	}
}

I'm using the "FancyHud" for my battle menu, so I detect that I'm loading the battle level and kick of it's methods.

In BattlePostLoad I handle my FanceHud code:
function BattlePostLoad(){
	
	sceneUIWindow2D.loadLevel("data/levels/battleUI.t2d");
	sceneUIWIndow2D.setCurrentCameraZoom(4);

	sceneUIWindow2D.Visible = true;
	sceneUIWindow2D.setCameraInterpolationMode("LINEAR");
	sceneUIWindow2D.setTargetCameraZoom(1); 
	sceneUIWindow2D.startCameraMove($battleUIZoomTime); 
	schedule($battleUIZoomTime*1000, 0, BattlePostUIZoom);
}

I removed most of the other BattlePostLoad code to focus on what I did for my FanceHud. You can even see here that I've thrown in a little zoom embellishment where I zoom out to reveal the HUD which has the effect of it zooming into place.

This is all kicked off by replacing the above mentioned line in game.cs
sceneWindow2D.loadLevel(%level);

$SelectedLevel = %level;
loadLevel();

Hope this helps out anyone looking to implement this along with any level switching functionality.
#4
06/26/2012 (3:41 pm)
Good post Johnny. Someone in IRC made the same comments (maybe that was you). The datablock management system is not going away. It's actually going to improve dramatically. Same with the built-in GUI system. The content of this blog has been requested several times in various posts and e-mails, so I thought I'd just post what I've written in the past.

I really like using scenes and sprites for HUDs, but I know not everyone wants that.
#5
06/26/2012 (3:42 pm)
Very nice David! Thanks for sharing.
#6
06/26/2012 (4:59 pm)
@Michael -Thanks for clearing that up.

And your tutorial above is great. It's a great technique for UI/HUD. I used it alot in Are You Quick Enough games. Scenes are awesome.
#7
06/26/2012 (6:38 pm)
Well I hadn't thought of this. :) I guess I assumed multiple &quot;scenes&quot; would be too heavy, but it makes perfect sense. It should cost almost no more than just having the HUD elements in the main scene. I had considered adding GUI layers, but never scene layers. Neat!

I bet I'll be using this soon. It seems possible to adjust the cameras independently and usually leaving the "HUD camera" alone. Cool!

P.S. What I'm currently doing for HUD is using regular scene objects as HUD pieces but adding a behavior to each that auto sizes/positions it every time the camera moves. haha! It's kinda cool, but much less intuitive that your method.
#8
06/26/2012 (6:57 pm)
@Charlie - Glad you like it. I use this method for my own game and I have no problems with performance. It's all very light.

Also, do you and David have a vote for next week's content?
#9
06/26/2012 (7:20 pm)
I vote for the behavior system blog.
#10
06/26/2012 (10:29 pm)
Oh, I'm actually super interested in both. But since I'm super into object oriented programming and polymorphism, bring on the behaviors.
#11
06/26/2012 (11:38 pm)
I have seen this mentioned somewhere before while reading the forums, but you explained it much better. I'm playing with the GUI system at the moment, but I will definitely have to play with this as well :)

I vote for behaviors, I was going to start with them next, what great timing :)
#12
06/27/2012 (2:03 am)
I'm gonna vote for 2 as the editor is of more interest to me than the behaviors.

I know how they work but in their current form they are more on the painfull and time wasting forefront than anything else, hence I focus on datablock based development to at least get something out of basic OO standards, thats better than fighting the behaviors where they do not follow the component pattern basics.

The concept of behaviors would be really nice but unluckily T2D / iT2D are just years behind what TX 2D had already in its first version and unless thats gonna change I don't care bout them.
The only time I worked with them is when I did an RTS prototype from which I shared some more 'self existing' behaviors on the old torque dev network wiki.
#13
06/27/2012 (4:33 am)
Great to see this blog, I've been using HUDs like this for a while but a GG blog on a this very useful topic is great.

I'm not particular on the next topic as both sound very useful. Eventually I'd like to see a topic on dynamic GUIs. I've found some information but most of what I'm doing right now to generate a GUI in script and update it on the fly has been through experimentation.
#14
06/27/2012 (7:12 am)
@Marc - I use datablocks for my stuff a lot as well, but I believe behaviors have a solid place in any game's development. Hopefully when I write about them you will still find the changes interesting. I'm taking votes all the way until the end of the week, so it's still a toss up.

@Drethon - Thanks for the compliment on the blog. Based on your second statement, you might want to vote for the editor blog then. There are many functions and modules that create dynamic GUIs in the editor.
#15
06/27/2012 (11:37 am)
@Mich, I'm more interested in hearing about any tech discussions on behaviors, although I'd like to hear about any GUI developments soon after.
#16
06/27/2012 (12:52 pm)
Since there are so many behaviour haters, I vote for a good, in-depth blog about behaviours.
#17
06/27/2012 (2:53 pm)
If it's to talk about known bugs then I vote 2 :)
#18
06/27/2012 (2:55 pm)
I've always preferred sprite based HUDs to the GUI editor made HUDs, they just feel more "right" to me. That said they can grow complicated pretty quickly depending on what you try to do..

I vote for behaviors, very curious.
#19
06/27/2012 (2:59 pm)
OMG that is awesomesauce!
Thanks for that Michael!
Will really help.

I got a question though regarding sprite based HUDs and I hope you don't mind asking here:

I wanted to make a sprite based Healthbar. Normally I just have 2 Sprites, each 100px long and 20px high, one red, one green.
I put the green one over the red and just shrink it according to the health of my player.
BUT, in T2D this does not work, since it shrinks on both ends.
I couldn't get this correctly to work.
Is there any method how I can shrink a sprite on one end only?

ps.: If it disturbs you, feel free to move it into a seperate thread.
Thanks :).
#20
06/27/2012 (7:02 pm)
I'll tell you MrSpaceGame I've actually had two caveats to the FancyHUD

  1. Text, I actually pop a proper GuiHUD over it all and use Gui Text, if anyone has suggestions on how to use sceneobject text effectively, let me know
  2. Progress Bars - I use them generally as bars of any kind, health and what not. Though, I can't get them to have a background color and more importantly I can't force them to go in a separate direction. Those two combined have caused me to come up with a way to put them in front of a invertly colored object and I invert the color and value of it and it works backwards

Not too much work, but not too clean and I'd much prefer text sceneobjects.
Page «Previous 1 2