Game Development Community

Problem with behaviors

by DiegoGdVU · in Torque 2D Beginner · 08/06/2013 (2:56 pm) · 3 replies

I'm having a problem, i'm using slightly modified versions of the dealsDamageBehavior and takesDamageBehavior found in DeathBallToy to do projectiles that hit enemies and destroy them like any normal Shoot 'em up, but the projectiles arent deleting the targets they are hitting they seem to delete the last enemy created, simialr case with projectiles, the ones that are dissapearing seems to be the last projectile generated. I've read the DeathBallToy source and i think im doing everything fine.

enemies.cs
function createEnemy(%Number_of_Enemies)
{
for(%i=0;%i<%Number_of_Enemies;%i++)
   {
		%enemy = new Sprite(fireEnemy)
		{
			size= "4 4"; 
			SceneLayer   = "1";
			SceneGroup = "10";
			Angle= "0";	
			fixedAngle=true;
			CollisionCallback = true;
		};
		
		%enemy.createCircleCollisionShape(1);
		
		%enemy.Image = "mainModule:fireEnemyImage";
		
		%enemy.Position=  getRandom(-20,20) SPC getRandom(-20,20);
		//echo(%enemy.Position);		
		
		myScene.add( %enemy);  

		%takesDamageBehavior = TakesDamageBehavior.createInstance();
		%takesDamageBehavior.initialize(100, "", "", true);
		fireEnemy.addBehavior(%takesDamageBehavior);		
		
	}
}

The code for the projectiles part of player.cs
function playerGolem::throwRock(%this)
{
	%rock = new Sprite()
	{
		image = "mainModule:rockImage";
		SceneLayer   = "1";
		SceneGroup = "10";
		AngularVelocity = "120";
		CollisionCallback = true;
		size = "3 3";
	};
	%rock.setBodyType( dynamic );
	
	%rock.createCircleCollisionShape(1);
	
	%rock.Position = playerGolem.getPosition();
	
	if (strcmp("down",playerGolem.facing)==0)
	{
		%rock.LinearVelocity="0 -20";
	}
	if (strcmp("up",playerGolem.facing)==0)
	{
		%rock.LinearVelocity="0 20";
	}
	if (strcmp("right",playerGolem.facing)==0)
	{
		%rock.LinearVelocity="20 0";
	}
	if (strcmp("left",playerGolem.facing)==0)
	{
		%rock.LinearVelocity="-20 0";
	}

	//Agregar los comportamientos
    %dealsDamageBehavior = DealsDamageBehavior.createInstance();
    %dealsDamageBehavior.initialize(1000, true);
    %rock.addBehavior(%dealsDamageBehavior);
	
	myScene.add(%rock);
	
}

And the modified version of the behaviors, the only major cahnge is the if at the begining.
if(!isObject(DealsDamageBehavior))
{
    // Create the named template and retain it as a custom field on this toy
    %template = new BehaviorTemplate(DealsDamageBehavior);

    // Fill in the details of the behavior
    %template.friendlyName = "Deals Damage";
    %template.behaviorType = "Game";
    %template.description  = "Set the object to deal damage to TakesDamage objects it collides with";

    // Add the custom behavior fields
    %template.addBehaviorField(strength, "The amount of damage the object deals", int, 10);
    %template.addBehaviorField(deleteOnHit, "Delete the object when it collides", bool, 1);

	
}


function DealsDamageBehavior::initialize(%this, %strength, %deleteOnHit)
{
    %this.strength = %strength;  //La fuerza del golpe
    %this.deleteOnHit = %deleteOnHit; //Borra un objeto cuando colisiona
}

//-----------------------------------------------------------------------------

function DealsDamageBehavior::onBehaviorAdd(%this)
{
    %this.owner.collisionCallback = true; //Se hace algo cuando hay colision
    %this.owner.collisionActiveSend = true;
}

//-----------------------------------------------------------------------------

function DealsDamageBehavior::dealDamage(%this, %amount, %victim)
{
    %takesDamage = %victim.getBehavior("TakesDamageBehavior");  //Se verifica si la victima puede recibir 

    if (!isObject(%takesDamage))
        return;
   
    %takesDamage.takeDamage(%amount, %this); //Si puede se le inflige cierta cantidad de 
}

//-----------------------------------------------------------------------------

function DealsDamageBehavior::explode(%this, %position)
{
    if (isObject(%this.explodeEffect))  //Efecto de explosion
    {
        %explosion = %this.explodeEffect.cloneWithBehaviors();
        %explosion.position = %position;
        %explosion.setEffectLifeMode("Kill", 1.0);
        %explosion.playEffect();
    }
}

//-----------------------------------------------------------------------------

function DealsDamageBehavior::onCollision(%this, %object, %collisionDetails)
{
    %this.dealDamage(%this.strength, %object);  
   
    if (%this.deleteOnHit)
    {
        //%this.explode(getWords(%contacts, 0, 1));
        %this.owner.safeDelete();
    }
}

if(!isObject(TakesDamageBehavior))
{
    // Create the named template and retain it as a custom field on this toy
    %template = new BehaviorTemplate(TakesDamageBehavior);

    // Fill in the details of the behavior
    %template.friendlyName = "Takes Damage";
    %template.behaviorType = "Game";
    %template.description  = "Set the object to take damage from DealsDamage objects that collide with it";

    // Add the custom behavior fields
    %template.addBehaviorField(health, "The amount of health the object has", int, 100);
    %template.addBehaviorField(explodeEffect, "The particle effect to play on death", asset, "", ParticleAsset);
    %template.addBehaviorField(deathAnim, "The object's death animation, alternative to explodeEffect", asset, "", AnimationAsset);
    %template.addBehaviorField(deleteOnDeath, "Delete the owner upon dieing", bool, false);


}

function TakesDamageBehavior::initialize(%this, %health, %explodeEffect, %deathAnimation, %deleteOnDeath)
{
    %this.health = %health;
    %this.explodeEffect = %explodeEffect;
    %this.deathAnim = %deathAnimation;
    %this.deleteOnDeath = %deleteOnDeath;
    
    %this.startHealth = %this.health;
   
}

//-----------------------------------------------------------------------------

function TakesDamageBehavior::takeDamage(%this, %amount, %assailant)
{
    %this.health -= %amount;
   
    if (%this.health <= 0)
    {
        // This only works on animated sprites
        if (%this.deathAnim !$= "")
            %this.owner.animation = %this.deathAnim;
      
        if (%this.explodeEffect !$= "")
            %this.explode();
            
        %this.kill();
    }
}

//-----------------------------------------------------------------------------

function TakesDamageBehavior::kill(%this)
{
    %this.owner.setCollisionSuppress();
    %this.owner.active = false;
    %this.owner.alive = false;
    
    if (%this.deleteOnDeath)
        %this.owner.safeDelete();
}

//-----------------------------------------------------------------------------

function TakesDamageBehavior::explode(%this)
{
    %particlePlayer = new ParticlePlayer();
    %particlePlayer.BodyType = static;
    %particlePlayer.SetPosition( %this.owner.getPosition() );
    %particlePlayer.SceneLayer = %this.owner.getSceneLayer();
    %particlePlayer.ParticleInterpolation = true;
    %particlePlayer.Particle = %this.explodeEffect;
    SandboxScene.add( %particlePlayer ); 
}

#1
08/06/2013 (2:59 pm)
In createEnemy() change the last line:

fireEnemy.addBehavior(%takesDamageBehavior); // wrong

%enemy.addBehavior(%takesDamageBehavior); // what you actually want

This adds the instance of the behavior to the actual enemy object. Before you were just adding instance after instance of the behavior to the fireEnemy class, not the actual enemy instance.
#2
08/06/2013 (3:55 pm)
Well that correction was part of the solution, but with only that change the bug persisted, after removing the class name altogether the problems was fixed.

This works fine

function createEnemy(%Number_of_Enemies)
{
for(%i=0;%i<%Number_of_Enemies;%i++)
   {
		%enemy = new Sprite() //Removed class name from here
		{
			size= "4 4"; 
			SceneLayer   = "1";
			SceneGroup = "10";
			Angle= "0";	
			fixedAngle=true;
			CollisionCallback = true;
			
		};
		
		%enemy.createCircleCollisionShape(1);
		
		%enemy.Image = "mainModule:fireEnemyImage";
		
		%enemy.Position=  getRandom(-20,20) SPC getRandom(-20,20);
		//echo(%enemy.Position);		
		
		myScene.add( %enemy);  

		%takesDamageBehavior = TakesDamageBehavior.createInstance();
		%takesDamageBehavior.initialize(100, "", "", true);
		%enemy.addBehavior(%takesDamageBehavior);		
		
	}
}

This produces the bug mentioned early.

function createEnemy(%Number_of_Enemies)
{
for(%i=0;%i<%Number_of_Enemies;%i++)
   {
		%enemy = new Sprite(fireEnemy) 
		{
			size= "4 4"; 
			SceneLayer   = "1";
			SceneGroup = "10";
			Angle= "0";	
			fixedAngle=true;
			CollisionCallback = true;
			
		};
		
		%enemy.createCircleCollisionShape(1);
		
		%enemy.Image = "mainModule:fireEnemyImage";
		
		%enemy.Position=  getRandom(-20,20) SPC getRandom(-20,20);
		//echo(%enemy.Position);		
		
		myScene.add( %enemy);  

		%takesDamageBehavior = TakesDamageBehavior.createInstance();
		%takesDamageBehavior.initialize(100, "", "", true);
		%enemy.addBehavior(%takesDamageBehavior);		
		
	}
}

And this seems to work fine to.

function createEnemy(%Number_of_Enemies)
{
for(%i=0;%i<%Number_of_Enemies;%i++)
   {
		%enemy = new Sprite() 
		{
			size= "4 4"; 
			SceneLayer   = "1";
			SceneGroup = "10";
			Angle= "0";	
			fixedAngle=true;
			CollisionCallback = true;
			Class="fireEnemy";
		};
		
		%enemy.createCircleCollisionShape(1);
		
		%enemy.Image = "mainModule:fireEnemyImage";
		
		%enemy.Position=  getRandom(-20,20) SPC getRandom(-20,20);
		//echo(%enemy.Position);		
		
		myScene.add( %enemy);  

		%takesDamageBehavior = TakesDamageBehavior.createInstance();
		%takesDamageBehavior.initialize(100, "", "", true);
		%enemy.addBehavior(%takesDamageBehavior);		
		
	}
}
#3
08/06/2013 (4:13 pm)
Hah - didn't even think about that. That's setting up every sprite created to try to use the name "fireEnemy". To get the class name to work correctly you do what you have in that last code block. Sorry I missed that....