Game Development Community

Asteroids Tutorial: Adding Waves (Section 5) not working 1.7.4

by Patrick Swinnea · in Torque Game Builder · 09/09/2008 (10:08 am) · 3 replies

Hello! Using Mac version 1.7.4.

I'm having a bit of trouble with Section 5 of the asteroids tutorial.
http://tdn.garagegames.com/wiki/TGB/Tutorials/Asteroids/Section5

This section is about adding Waves (new levels) of asteroids. After you kill all the small asteroids, it should spawn a new wave of Large Asteroids.

According to the tutorial there are 3 scripts needed to do this.

1. The updated spawnArea.cs - copied and pasted from here: http://tdn.garagegames.com/wiki/TGB/Tutorials/Asteroids/Section5/SpawnArea

2. A spawnTracker.cs script - copied and paste from the project page here: http://tdn.garagegames.com/wiki/TGB/Tutorials/Asteroids/Section5

3. An added line to spawnOnRemove.cs. The tutorial says to add the line:

%newObject.spawnOnRemoveCount = %this.count;

to the spawnChildren function within the for loop.

Since the 1st two scripts are copied and pasted, the only place I could be making a script error is in spawnOnRemove.cs. My final spawnOnRemove.cs script looks like this:




if (!isObject(SpawnOnRemoveBehavior))
{
%template = new BehaviorTemplate(SpawnOnRemoveBehavior);

%template.friendlyName = "Spawn On Remove";
%template.behaviorType = "AI";
%template.description = "Spawn objects in place of this when this object is deleted";

%template.addBehaviorField(object, "The object to spawn", object, "", t2dSceneObject);
%template.addBehaviorField(count, "The number of objects to spawn", int, 2);
%template.addBehaviorField(offset, "The distance from the center to spawn the objects", float, 4);
}

function SpawnOnRemoveBehavior::onRemove(%this)
{
%this.spawnChildren();

}

function SpawnOnRemoveBehavior::spawnChildren(%this)
{
if (!isObject(%this.object))
return;

for (%i = 0; %i < %this.count; %i++)
{
%newObject.spawnOnRemoveCount = %this.count;
%newObject = %this.object.cloneWithBehaviors();

%direction = mDegToRad(getRandom(0, 360));
%x = mCos(%direction) * %this.offset;
%y = mSin(%direction) * %this.offset;
%offset = %x SPC %y;

%newObject.position = t2dVectorAdd(%this.owner.position, %offset);


}
}




Is there a particular place within the for loop that the %this.count line should be?

In addition to adding the scripts I reloaded my project after updating the behaviors, added the spawnTracker behavior to the small Asteroid (and set the spawner as spawnMachine) and checked my spawnMachine object to make sure the changes took in the spawnArea behavior.

After my first wave is killed, nothing happens.

So... to troubleshoot I restarted TGB, restarted my computer, deleted all the dso files in my project folder and scrapped my entire project folder and started over from the beginning with a clean project (testing in between every step). Still, no luck.

Also, I continued on to the next step of adding a GUI text to inform the player when they have reached a new wave. This text shows up fine at the start of the game, but usualy won't show up again.

NOW, FOR THE REALLY WEIRD PART! :) Usually, nothing happens after my first wave dies, but SOMETIMES I get another wave immediately, but it's like 10x the number of Asteroids it should be. Sometimes the LEVEL 2 GUI text will pop up and it looks like everything is working, but then after Level 2 - no more enemies. And SOMETIMES, the GUI text skips right to Level 7 or 8, spawning a TON of Asteroids in the process. I have my initial wave at 5 to make it easy to test, but sometimes I'll get 10 or so in the first wave. This was never a problem with the original spawnArea.cs behavior.

Does it sound like I'm making a N00b mistake or is this a bug with Mac version 1.7.4?

Thanks for any help you can provide!

#1
09/10/2008 (9:49 pm)
I found a workaround and I'd thought I'd share what I did. It doesn't create exactly the same gameplay but it might be helpful to someone looking for an alternative to the Asteroids Tutorial method of spawning new levels.

The two main goals here are to 1) create increasing difficulty as time passes and 2) inform the player when they have reached a new level (or difficulty wave).

*THE MAIN DIFFERENCE BETWEEN THIS METHOD AND THE ORIGINAL ASTEROIDS TUTORIAL IS THAT THIS METHOD DOES NOT WAIT UNTIL ALL THE ENEMIES HAVE BEEN DESTROYED BEFORE LAUNCHING A NEW WAVE OF ASTEROIDS.

However, if you WANT to increase the difficulty while there are still enemies in play, this method will get it done.

PART ONE OVERVIEW
For the first part I created physical colliders that create new Spawn Areas at timed intervals during the game.

EXPLANATION
To begin, set up TWO Spawn Areas right on top of each other. For now they will use the ORIGINAL spawnArea.cs script found on the TDN Behaviors page.

The first Spawn Area is the BASE Spawn Area. It's set to spawn at a fairly high interval, say a new asteroid every 3 seconds. Set the spawn count to infinity or a crazy high number so it just spawns forever.

The second Spawn Area is the INCREMENTAL Spawn Area. It's set to a low interval, like 5 or 6 seconds. The spawn count here is also set to infinity.

If you test the game now it will play as if there is one Spawn Area that occasionally spawns 2 asteroids at a time.

*The reason for creating 2 Spawn Areas is that this method involves duplicating an existing Spawn Area to increase difficulty during the game. If you only start with one main Spawn Area, duplicating it makes the 2nd level twice as hard as the first, which DOES NOT provide gradually increasing difficulty. Creating a 2nd, slower spawning Spawn Area and then spawning THAT one, fixes this. (It makes sense when you see it in action).

THE COLLIDERS
The Colliders are basically timed triggers that create new INCREMENTAL Spawn areas.

The Collider setup includes:
1) The Trigger Creator
2) The Invisible Trigger
3) The Invisible Collider

The TRIGGER CREATOR sits offscreen to the far left of the level. It has the Spawn Area behavior and is set to spawn an Invisible Trigger at set intervals (like once every 2 minutes).

The INVISIBLE TRIGGER has Template, Takes Damage, Spawn On Remove and Random Velocity behaviors. The Random Velocity is set at an min/max angle of 90, a speed of 5 and an rotation of 0. This makes the Invisible Trigger move slowly from left (offscreen) to right until it hits the Invisible Collider. The Spawn On Remove is set to spawn one Incremental Spawn Area with an offset of 0.

The INVISIBLE COLLIDER is positioned toward the center of the screen (I'm still tweaking this but centering the Collider seems to position the new Incremental Spawn Area in the right place). It has the Deals Damage behavior.

The Trigger and Collider are set to collide with each other using collision groups (so as not to interfere with the asteroids).

SO... WHAT DO WE HAVE SO FAR?

When the game is started the Base and Incremental Spawn Areas create the initial wave of asteroids. Offscreen, the Trigger Creator spawns an Invisible Trigger and it floats towards the level. When it hits the Invisible Collider it is destroyed and spawns a second Incremental Spawn Area (now there are 3 Spawn Areas total). Meanwhile, the Trigger Creator spawns a new Invisible Trigger, which floats toward the level... etc. etc.

With every new Trigger that collides, the game gets harder and harder.

The length in time of your first level is based solely on the distance from the Trigger Creator to the center of the level. This means your first level will be shorter or longer than the rest of your levels depending on where you place the Trigger Creator.

As an added bonus you can add the Play Sound On Collision to the Trigger so that each new wave is accompanied by a specific sound effect.


PART TWO: ADDING THE GUI TEXT
Adding the GUI Text to inform the player of the new wave is almost identical to the instructions in the Asteroids Tutorial.

Follow the instructions here:
http://tdn.garagegames.com/wiki/TGB/Tutorials/Asteroids/Section6

Add all the lines of code to the spawnArea.cs script EXCEPT for the line added to the Update function. This is easy because the spawnArea.cs script doesn't have an Update function (since we're using the original script and not the Asteroids Tutorial version).

Follow all the rest of the instructions in Section 6.

After your text is all set up with the gameText.cs behavior, go into the Spawn Area behavior settings for the INCREMENTAL Spawn Area and set the textObject to gameText. Don't touch the settings for the Base Spawn Area.

Wallah!

The GUI Text should pop up at the start as "Level 1" and every time a new Incremental Spawn Area is created it will display the appropriate level number.

I know for you hardcore coders this is pretty clunky, but it seems to do the job. Maybe this will help someone in the future. If anything was fuzzy or unclear, let me know and I'll try to clarify it.
#2
12/13/2009 (9:50 pm)
I'm having the same problem sometimes. I'm not sure what the actual problem is yet, but sometimes it happens on Level 1, sometimes on Level 5. When I debug, I get a repeated message:
t2dSceneGraph::addToScene() - Object '1390' is already in a Scenegraph!.

It starts with Object 1390, jumps to object 1398, and then increments by 3 each time
#3
12/14/2009 (6:44 am)
The object already in a scenegraph warning is a minor bug with the cloneWithBehaviors function but it's not serious and can be ignored. You can turn the warning off completely with this:

$pref::T2D::warnSceneOccupancy = false;

I updated section 5 of the tutorial recently to fix an issue with unlimited spawnings. In the spawn tracker behavior, the function onRemoveFromScene was changed to onRemove.

For cases where the next wave or level doesn't spawn - it could be that not all asteroids have been destroyed yet from the current wave. I've found that the max and min bounds for the asteroids' world limits are perhaps a bit too generous. It could result in rare cases with an asteroid with a pure horizontal or vertical velocity hiding outside the camera view. Reducing the world limit bounds to -62.5 -50.5 62.5 50.5 for the large asteroids and -54 -41 54 41 for the small asteroid helps. I also reduced the size of the "spawn machine" object to a width/height of 115/90. To double check, you can also add a few echo commands to track the number of spawns in the scene versus how many have been removed. Something like this:

function SpawnAreaBehavior::update(%this, %object)
{
   %this.asteroidsRemoved = %this.asteroidsRemoved + 1;
   %totalSpawns = %object.spawnOnRemoveCount * %this.count;
   echo("total spawns for current wave" SPC %totalSpawns);
   echo("number of asteroids removed:" SPC %this.asteroidsRemoved);
   
   if (%this.asteroidsRemoved == %totalSpawns)
   {
      %this.asteroidsRemoved = 0;
      %this.count = %this.count + %this.addOnRespawn;
      %this.spawnCount = 0;
      %this.schedule(%this.spawnTime * 1000, "spawn");
   }
}