Game Development Community

Plastic Gem #6: Data Inheritance

by Paul Dana · 06/16/2008 (6:21 am) · 3 comments

Download Code File


i936.photobucket.com/albums/ad202/vincismurf/banner.jpg


Plastic Gem # 6 : Data Inheritance

Difficulty: Easy

For a list of gems see the Gem A Day page.

Hello again from Plastic Games. Time for gem number six! This gem demonstrates how to do OOP style coding using Torque script data inheritance. You must follow the instructions in Gem #1 , Gem #2, and Gem #3 before you can use this resource.

The previous gem already shows a basic example of Torque script data inheritance with the AnalogClockBase base class. This gem goes into more detail on what you can do with this ability and sets the stage for understanding the next Gems to come.

1) Unzipping the files

After following the instructions in Gem #1, Gem #2, and Gem #3, unzip the pg06_dataInheritance.zip file provided with this resource. Copy the clock.cs file to your ~/server/scripts folder. There will already be a file of that name there from the previous gems. Allow that file to be over-written - we want the new file.

www.plasticgames.com/dev/blog_images/gems/ease_anim.gif
Here are the features we have added to the Grandfather Clock.

1) ability to set the speed of pendulum in the datablock
   2) ability to set the start time in the datablock
   3) ability to override and set pendulum speed and/or the start time on the object itself
   4) utility method to set time right from object itself

Let's take a look at the code and see what this means and how it is done.

2) Setting pendulum speed and start time in datablock

First we added some fields to the AnalogClockBase base class:

// datablocks that extend this one set different defaults here...
   defaultPendulumSpeed = "0.5";
   defaultStartHour = "12";
   defaultStartMinute = "0";

3) Defining the SlowGrandfatherClock datablock

Next we create a new datablock by extending not the base class, but the regular grandfather clock.

// this shows how we don't HAVE to extend AnalogClockBase, we can extend
// our standard grandfather clock if we want...
datablock StaticShapeData(SlowGrandfatherClock : GrandfatherClock)
{
   // we don't have to define shape or category...we get that from GrandfatherClock...	

   // this grandfather clock runs really slow...and starts at 7:45
   defaultPendulumSpeed = "0.2";   
   defaultStartHour = "7";
   defaultStartMinute = "45";
};

Note that this clock's pendulum will move more slowly and it will start at 7:45.

4) Using the default value in the ::onAdd() method

Now we change the code at the bottom of the ::onAdd() method. Here is the part that does the magic.

// OK...so here is the magic. If this object does not have a START TIME or
   // a PENDULUM SPEED set..then set them from the defaults in the datablock...      
   if (%obj.pendulumSpeed $= "")
      %obj.pendulumSpeed = %this.defaultPendulumSpeed;
      
   if (%obj.startHour $= "")
      %obj.startHour = %this.defaultStartHour;
      
   if (%obj.startMinute $= "")
      %obj.startMinute = %this.defaultStartMinute;

   // set the pendulum speed...
   %obj.setThreadSpeed(0, %obj.pendulumSpeed);   
         
   // set the starting time...
   %this.setAnalogClockTime(%obj, %obj.startHour, %obj.startMinute);

We check to see if this object already has fields set for pendulum speed or start time. When would it? If you have saved a placed clock in a .mis file and are reloading it, then those fields will be filled. If the fields are blank then we set them from the defaults from the datablock.

5) Adding utility method in the StaticShape namespace

Methods for StaticShape objects are defined on the datablock not the object itself. For example note that the method to set the time is in the AnalogClock namespace, which comes from the datablock. This can be inconvenient as often what you have is the object itself. For this reason we often add "utility" methods that can be called right from the object itself. The only restriction here is that it's important the method name be unique among all methods at the level of StaticShape, so we are sure to apply this technique only to appropriately descriptive method names:

// UTILITY methods on the object itself

// we define our unique method name in the StaticShape namespace as well
// and just pass the buck...this is clumsy because when you change the method
// params you have to remember to change them here as well but it can make
// the code a lot more readable and help you avoid errors...
function StaticShape::setAnalogClockTime(%obj, %hour, %min)
{
   %obj.getDataBlock().setAnalogClockTime(%obj, %hour, %min);
}

6) Placing Shape in mission Editor

Place the SlowGrandfather Clock in the mission editor using the same steps described in Gem #1: Placeable Shapes.

www.plasticgames.com/dev/blog_images/gems/time_7_45.jpg
Unlike the regular GrandfatherClock which defaults to 10:30, notice how the SlowGrandfatherClock defaults to 7:45. Also notice how slow the pendulum is swinging.

Let's give this clock a name so we can test out our utility method. Ensure that you are still in the Mission Editor and that the grandfather clock you just placed is still selected. Choose "World Editor Inspector" from the Window menu and you should see the fields of the grandfather clock displayed in the inspector window. Enter the name Clock into the name field and hit the apply button.

Now hit the tilde key (~) to drop the Torque console and type in this command:

Clock.setAnalogClockTime(11,15);

www.plasticgames.com/dev/blog_images/gems/time_11_15.jpg
Notice how the clock face now reads 11:15. Handy.

OK now let's test setting the start time by altering fields on the object itself. Again ensure that you are still in the Mission Editor and that the grandfather clock you just placed is still selected and that you are in the inspector mode. Scroll to the bottom of the fields for this object and you will see three dynamic fields that were created when this objects ::onAdd() method was called:

pendulumSpeed
   startHour
   startMinute

These fields may not show up in this order, but all three should be there. Edit the startHour field to read 8 and the startMinute field to read 20 and hit the apply button. Next select "Save" from the file menu. We have told this object that we want the default start time to be 8:20...not the default of 7:45 indicated in the datablock. To see the results of this change we must load this mission again.

www.plasticgames.com/dev/blog_images/gems/time_8_20.jpg
Reload the mission either by quitting the game and re-entering it, or by choosing "Open..." from the File menu and selecting whatever mission you have been editing. You should notice that the slow grandfather clock now reads 8:20.

The Next Gem

That's all for this gem. The next gem introduces a new shape to play with now that we have learned how to manipulate animation threads to our advantage, and have learned a bit about how to leverage data inheritance. The grandfather clock is a great example as it is a familiar object, and it looks rather grand. The next shape is much more plain, but it packs a punch. It is a Marker object that has threads to let you manipulate the shape and color of the marker symbol as well as set the value of a two digit number. It is just amazing the amount of useful stuff you can do with a simple shape like that and these thread resources.

#1
08/07/2008 (4:12 am)
how would one go about syncing the clock with with an actual clock? ... let's say ... the servers clock.
#2
08/17/2008 (3:04 am)
Mikael, the easiest way I could think of is to use the schedule command, that is schedule an event every so often that updates the clock.
#3
01/07/2009 (7:33 am)
I think Joseph is right.