01.May.07 Lecture 11
Changing model textures, score keeping

Motivate

Learn to Stop complaining. It's far better to use that energy to solve the problem than to simply complain about it. If you really want to try something difficult, try to stop complaining for 21 days in a row.

14 days left.

Unit vectors and vector math

Working on one of the student's projects, there was a problem with a transform on a model was close, but not exact. Be careful when working with vectors and make sure you always use normalize (unit vectors) when calculating dot and cross products. The problem turned out to be one vector used in a cross product that was not normalized. A sign of this is that the result of a caclulation is very close, but not precise. Depending on how close to a unit vector a paramter to dot/cross product is, the results may be off by a small or relatively large amount.

Changing model textures

I've been looking at doing some skinning for my test game and this note is mostly for myself.

It looks like TSShapeInstance has a method setOverrideTexture that will work as long as the object has only one texture which is fine for the models I'm using.

Since I'm using the same popup door for all my targets I simply want to change the texture instead of having a bunch of different dts objects.

http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4051

Using multiple textures with the same object are pretty simple. Use a "BASE.SHAPE" name for your default texture defined in the model. Other textures just change the name of BASE. Then if you want to use a different texture on the model you simply have the corresponding image name for the texture. By default you would have BASE.SHAPE.JPEG (if that's what you called your texture/material) other textures would be ONE.SHAPE.JPEG, or XYZ.SHAPE.JPEG.

Then when you want to change the texture you simply call.

%obj.setSkinName("ONE");

or

%obj.setSkinName("XYZ");

or

%obj.setSkinName("BASE");

or don't make the call to setSkinName and you will be using the default texture "BASE".

This is a good way to save on memory requirements as you can have one model file and add different instances of that file by simply adding appropriately named jpeg files.

This is a sample using my

Score Tracking Client/Server

This past week I worked on adding a scoring component to the game. This required some changes to the damage mechanism because there was really no way to tell who had done the actual shooting. Here are some notes on the process.

First I changed the guil to have a bitmap with two text controls on it. The text controls are the actual score.

new GuiBitmapCtrl() {
      canSaveDynamicFields = "0";
      Profile = "GuiDefaultProfile";
      HorizSizing = "right";
      VertSizing = "bottom";
      position = "667 468";
      Extent = "128 128";
      MinExtent = "8 2";
      canSave = "1";
      Visible = "1";
      hovertime = "1000";
      bitmap = "./hud-bg.png";
      wrap = "0";

      new GuiTextCtrl(CriminalHits) {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "86 62";
         Extent = "12 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "12";
         maxLength = "1024";
      };
      new GuiTextCtrl(CivillianHits) {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "87 81";
         Extent = "12 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "13";
         maxLength = "1024";
      };
   };

I added code to the mission initialization to reset the scores to 0.

function GameConnection::createPlayer(%this, %spawnPoint)
{
   /* ... */
   
   %player.client.criminalHits = 0;
   %player.client.civillianHits = 0;
   CommandToClient(%this,'CriminalHits',%player.client.criminalHits);
   CommandToClient(%this,'CivillianHits',%player.client.civillianHits);
}
        

On the client I added code to receive the messages and update the gui components.

function clientCmdCriminalHits(%hits)
{

  CriminalHits.setText(%hits);
}


function clientCmdCivillianHits(%hits)
{
  CivillianHits.setText(%hits);
}

The actual updating of the score when the popup target was damaged was harder. This is the original call to damage. In popup.cs

function PopupData::damage(%this, %obj, %pos, %dmg, %objname)
      

The problem with this is that there is no reference to the original shooter. %this is the datablock type, %obj is the popup instance, %pos is the position, %dmg is the amount of damage, and %objname is a simple name. There needed to be some way to pass the actual player doing the damage. This required changes to each of the weapons and the shapeBase datablock code which we talked about before.

shotgun.cs (before)

function shotgunProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
   // Apply damage to the object all shape base objects
   if (%col.getType() & $TypeMasks::ShapeBaseObjectType)
      {
      %col.damage(%obj,%pos,%this.directDamage,"shotgunBullet");
	  }

}

shotgun.cs (after). The %col is the actual particle that is hitting the popup. When the partical was created the client field was set in the instance.

function shotgunProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
   // Apply damage to the object all shape base objects
   if (%col.getType() & $TypeMasks::ShapeBaseObjectType)
      {
      %col.damage(%obj,%col,%pos,%this.directDamage,"shotgunBullet");
	  }

}

shapeBase.cs (before)

function ShapeBase::damage(%this, %sourceObject, %position, %damage, %damageType)
{

   %this.getDataBlock().damage(%this, %sourceObject, %position, %damage, %damageType);
}

shapeBase.cs (after)

function ShapeBase::damage(%this, %sourceObject, %col, %position, %damage, %damageType)
{

   %this.getDataBlock().damage(%this, %sourceObject, %col, %position, %damage, %damageType);
}

And finally, the changes to pupup.cs damage.

function PopupData::damage(%this,%obj, %col, %pos, %dmg, %objname)
{

  if (%obj.Up == true)
    {

    // with a shotgun damage is called a bunch of times
	// only want to schedule one down and remove
    if (%obj.isActive)
      {
      // score for the player who hit it.
      %col.client.criminalHits++;

      CommandToClient(%col.client,'CriminalHits',%col.client.criminalHits);

      /* .... */
        

%col in this case is the actual player which was stored in. Now the client receives the score update on each hit to a popup target.

CPSC240 - Games Development
Chapman University
Instructor: W. Wood Harter
(c) copyright 2006-2007 - W. Wood Harter - All Rights Reserved
Screen shots on banner (c) copyright their resprective owners