Game Development Community

dynamic circular time bar?

by Isaac Barbosa · in Torque Game Builder · 10/19/2009 (8:30 pm) · 5 replies

Hi,

I´m wondering if a circular time bar is possible in TGB.

If so, please drop some directions to achieve that. I can´t imagine a way to do since masks are not allowed in TGB.

Thanks!

Isaac

#1
10/19/2009 (11:05 pm)
while masks are not really implemented on TGB, you can still achieve that effect if you use your graphical resources wisely.

in your case, a "solution" to your question would be somethin like, making a certain ammount of images that represent the circular bar, starting from a full colorful bar, down to a minimal, depleted bar ... you could make it with 8-16 different sprites, and while it will eat up some ram at runtime, it will still give you the effect you're looking for.

AND, if you wanna give it a cool alpha border, you can make that image too, and make the timebar to go above that one.

its a shitty solution, but it works... and sometimes, you just want your stuff to work, right?.
#2
10/20/2009 (1:38 am)
I see you have the Pro license. I've learned it really, really easy to make new GUI elements and new T2D elements.

If you want to do this in T2D and aren't scared of a little OpenGL, the steps I follow are pretty simple:
1) Copy t2dStaticSprite.{h|cc} to t2dMyNewClass.{h|cc} and add it to your project.
2) Add persisted fields (in your case, maybe a percentage field).
3) Modify onRender to do the OpenGL work. The t2dStaticSprite gives you the information you need to get it rendered into the correct position.

If you're targeting both PC and Mac, you'll have to recompile for both platforms. But I find that having my own custom elements gives me a lot more flexibility and helps me stand apart for the stock engine.
#3
10/20/2009 (11:14 am)
And if you want to do it without touching code:

1) Create 9 alpha-mapped bitmaps named "tfill-" 0 thru 8. tfill-0 is just a single line at the top of a circle, representing the "empty" state of the timer, while tfill-8 is the full circle. Intermediate states were made with a glow effect added for additional snazziness.

2) Next, create a GuiBitmapCtrl entry in your gui somewhat like below. The two fields to note are the bitmap field, which contains the starting state of the timer (here set to full), and the fill field, which holds the "prefix" of the bitmap name, which will be used in the timer function:

new GuiBitmapCtrl(btnTimer1) {
   Profile = "GuiDefaultProfile";
   HorizSizing = "right";
   VertSizing = "top";
   Position = "560 601";
   Extent = "39 39";
   MinExtent = "39 39";
   canSave = "1";
   Visible = "1";
   bitmap = "tfill-8";
   wrap = "0";
   fill = "tfill-"; //Used for a "filling" timer
   dep = $dep; //Used for a "depleting" timer
};

3) Here, I have three functions I used to get the timer effect. One is called stageTimer(), and it does the heavy lifting of the schedule and updating the bitmap for the button, etc. The next is called setStage, and I use it simply to set the stage that the button timer is at. T

he third function is called buttonTimer, and just kicks off an immediate timer (which should probably just be a call to setStage- I may have done that late at night, lol) to set the timer to empty, and then kicks off the timer for the actual timer affect.

The arguments for buttonTimer are:
%ctrl = Name of control you're using
%dir = Direction timer animates in
%stage = Current stage of timer
%stages = Number of stages/bitmaps in timer
%castTime= I was using this as the cast timer, so you can disregard it
%time = This is the length of the timer

The arguments for stageTimer are:
%ctrl = Name of control you're using
%type = Whether animation is filling or depleting
%dir = Direction timer animates in
%stage = Current stage
%stages = Number of stages/bitmaps in timer
%time = Duration of timer

The arguments for setStage:
%ctrl = Name of control you're using
%type = Whether to use filling or depleting bitmaps (you can have both)
%stage = Current stage

function buttonTimer(%ctrl, %dir, %stage, %stages, %castTime, %time)
{
   schedule(0, 0, "stageTimer", %ctrl, 0, %dir, %stage, %stages, %castTime);
   schedule(%castTime+100, 0, "stageTimer", %ctrl, 1, %dir, %stage, %stages, %time);
}

function stageTimer(%ctrl, %type, %dir, %stage, %stages, %time)
{
   setStage(%ctrl, %type, %stage);
   if(%dir) //Ascending (fill)
   {
      if(%stage < %stages)
      {
         schedule((%time/%stages), 0, "stageTimer", %ctrl, %type, %dir, %stage+1, %stages, %time);
         return;
      }
   }
   else //Descending (deplete)
   {
      if(%stage > 0)
      {
         schedule((%time/%stages), 0, "stageTimer", %ctrl, %type, %dir, %stage-1, %stages, %time);
         return;
      }
   }
}

function setStage(%ctrl, %type, %stage)
{ 
   for(%i = 1; %i < 16; %i++)
   {
      %ctrl = "btnTimer" @ %i; //Used when you update multiple timers at once
      if(%type) //Type 1 is "filling", type 0 is "depleting"
         %name = %ctrl.fill @ %stage;
      else
         %name = %ctrl.dep @ %stage;
      %ctrl.setBitmap(%name);
   }
}

I should turn this into a resource some time soon, but until then, enjoy and modify to your tastes =)

Edit: I should point out the %ctrl name of "buttonTimer" being used without the trailing number in the functions because my game has about 15 of these that update at once. The %ctrl name is fed through the loop which adds the number, completing the actual name of the %ctrl to update. Just in case there was any confusion. If that's not your situation, you can change it however you like.
#4
10/20/2009 (12:53 pm)
Thanks to all for their answers.

I have decided to implement a true clock instead of a bar so I will have a better visual element and I will avoid this solution.

Isaac
#5
10/21/2009 (2:36 pm)
Just want to say thanks to Ted for the code here, I was just about to write something like this myself :)