Game Development Community

dev|Pro Game Development Curriculum

Moveable, Destroyable, Mission Area Aware ITEMS

by Robert Brower · 01/24/2003 (11:45 am) · 4 comments

01/22/03 - Robert Brower.

Prelude... I am working on a first person shooter in space. It is similar to the classic arcade game 'Asteroids'. I needed a way to create asteroids that would float around the mission area. One of the problems with this was that I needed a way to confine the asteroids to the mission area. Another problem was that projectiles normally don't collide with Items. To solve these problems follow these steps. If you are working on a space related game then you can also include the optional modifications by Wendell Brown and Chris 'Dark' Evans. I implemented some of their changes but not all of them.


The following instructions will enable you to create destructable Item objects that have mission area bounds checking.


1. torque\engine\game\item.h

Insert the following block of code into the private section of the class right after Box3F mWorkingQueryBox;

// RFB ->
void checkMissionArea();
bool mInMissionArea;
// <- RFB

-----------------------------------------------------------------------------

2. torque\engine\game\item.cc

Insert the following block of code right after #include "math/mathIO.h".

// RFB -> adding item mission area bounds check
#include "game/missionArea.h"
// <- RFB

Insert the following block of code inside Item::Item() right after mWorkingQueryBox.max.set(-1e9, -1e9, -1e9);

// RFB ->
mInMissionArea = true;
// <- RFB

Insert the following block of code inside Item::updatePos(). Insert it after the water condition as shown in the
following block of code.

// water
if(bool(safePtr))
{
if(!mInLiquid && mWaterCoverage != 0.0f)
{
Con::executef(mDataBlock,4,"onEnterLiquid",scriptThis(), Con::getFloatArg(mWaterCoverage),
Con::getIntArg(mLiquidType));
mInLiquid = true;
}
else if(mInLiquid && mWaterCoverage == 0.0f)
{
Con::executef(mDataBlock,3,"onLeaveLiquid",scriptThis(), Con::getIntArg(mLiquidType));
mInLiquid = false;
}
}
// RFB ->
checkMissionArea();
// <- RFB

Insert the following function.

void Item::checkMissionArea()
{
// Checks to see if the item is in the Mission Area...
Point3F pos;
MissionArea * obj = dynamic_cast(Sim::findObject("MissionArea"));

F32 flightCeiling = obj->getFlightCeiling();
F32 ceilingRange = obj->getFlightCeilingRange();

const RectI &area = obj->getArea();
getTransform().getColumn(3, &pos);

if ((pos.x < area.point.x || pos.x > area.point.x + area.extent.x ||
pos.y < area.point.y || pos.y > area.point.y + area.extent.y)) {
if(mInMissionArea) {
mInMissionArea = false;
Con::executef(mDataBlock,3,"onLeaveMissionArea",scriptThis());
}
}
else if(!mInMissionArea)
{
mInMissionArea = true;
Con::executef(mDataBlock,3,"onEnterMissionArea",scriptThis());
}
}
-----------------------------------------------------------------------------

3. torque\engine\game\projectile.cc

Change csmDynamicCollisionMask to include ItemObjectType as shown in the following block of code.

const U32 Projectile::csmDynamicCollisionMask = PlayerObjectType |
VehicleObjectType |
ItemObjectType | // RFB -> adding items to this damage mask
DamagableItemObjectType;

-----------------------------------------------------------------------------

4. Add the following torque script functions to the item class of your choice. Substitute the word 'Asteroid'
for whatever your object is called. You can define your own behavior if you want but I am creating asteroids
that will wrap around to the other side of the mission area when they leave the mission area.

function Asteroid::onLeaveMissionArea(%this, %obj)
{
//echo("Asteroid " @ %obj @ " left the mission area");
%pos = %obj.getTransform();
//echo("Asteroid " @ %obj @ " position = " @ %pos);

%missionArea = nameToId("MissionArea");
if (isObject(%missionArea))
{
// get mission area bounds
%area = %missionArea.getArea();
%minx = getWord(%area, 0);
%miny = getWord(%area, 1);
%maxx = %minx + getWord(%area, 2);
%maxy = %miny + getWord(%area, 3);
%minz = -1 * %missionArea.flightCeiling;
%maxz = %missionArea.flightCeilingRange;

// get asteroid location
%ax = getWord(%pos, 0);
%ay = getWord(%pos, 1);
%az = getWord(%pos, 2);

// max x reached?
if (%ax >= %maxx)
%ax = %ax - (%maxx - %minx);

// min x reached?
if (%ax <= %minx)
%ax = %ax + (%maxx - %minx);

// max y reached?
if (%ay >= %maxy)
%ay = %ay - (%maxy - %miny);

// min y reached?
if (%ay <= %miny)
%ay = %ay + (%maxy - %miny);

// max z reached?
if (%az >= %maxz)
%az = %az - (%maxz - %minz);

// min z reached?
if (%az <= %minz)
%az = %az + (%maxz - %minz);

%pos = %ax @ " " @ %ay @ " " @ %az;
//echo("Asteroid " @ %obj @ " new position = " @ %pos);
%obj.setTransform(%pos);

}
}

function Asteroid::onEnterMissionArea(%this, %obj)
{
//echo("Asteroid " @ %obj @ " entered the mission area");
//%pos = %obj.getTransform();
//echo("Asteroid " @ %obj @ " position = " @ %pos);
}

-----------------------------------------------------------------------------

5. Optional Space Environment modifications by Wendell Brown.

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

-----------------------------------------------------------------------------

6. Optional 'Zero-G' modifications by Chris 'Dark' Evans

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

-----------------------------------------------------------------------------

Good luck with your torque project! If you have questions or problems, post them so we can figure them out. Thanks!

Robert Brower

#1
01/25/2003 (10:25 am)
Excellent. Looks like a very promising resource. I'll definitely give this a try.
-Ed
#2
04/10/2003 (6:55 pm)
I don't see any code here showing an example of destroyable items.
Can you post the entire asteroids.cs file?
#3
04/23/2003 (9:04 pm)
function Asteroid::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
{
if (%obj.getDamageState() $= "Destroyed")
return;
%obj.applyDamage(%damage);
}

function Asteroid::onDamage(%this, %obj)
{
%damage = %obj.getDamageLevel();
if (%damage >= %this.destroyedLevel / %obj.scaleLevel)
{
if(%obj.getDamageState() !$= "Destroyed")
{
%obj.setDamageState(Destroyed);
}
}
else
{
if(%obj.getDamageState() !$= "Enabled")
%obj.setDamageState(Enabled);
}
}

function Asteroid::onDestroyed(%data, %obj, %prevState)
{
if (isObject(%obj))
{
%pos = %obj.getTransform();
%explosion = new explosion() {
dataBlock = "AsteroidExplosion";
position = %pos;
};
MissionCleanup.add(%explosion);
radiusDamage(%explosion,%pos,30,30,"Asteroid",30);
%minX = %obj.minX;
%maxX = %obj.maxX;
%minY = %obj.minY;
%maxY = %obj.maxY;
%minZ = %obj.minZ;
%maxZ = %obj.maxZ;
%obj.schedule(300, "delete");
}
}
#4
09/11/2007 (5:51 pm)
Hello. I had some troubles using this resource in my project (see here for details).
I uploaded a patch to apply on a clean 1.4.2 TGE install on my website here, and I left this resource's code commented out.
Can you give me some hints on what I done wrong? Thanks in advance for anything.

Bye, Berserk.
.