In this tutorial we add the ability to destroy the enemies.
Destroying an enemy in response to a collision with a players bullet may sound simple enough, but there is a bit of work that has to be done in the background to manage the health of the enemy, decrease that health in response to a collision with a bullet, and finally to display an explosion when the enemy has died.
The explosion, just like any other animated sprite, is defined in the XML files. Like the bullets it exists as a template, but is not added to any groups, so it is not loaded when the level is loaded. Because the explosion will not participate in collision detection or be moved around the screen there is little need to simulate it with the Box2D physics engine. So the spatial component will be a SimpleSpatialComponent, unlike the Box2DSpatialComponent used for the enemies, player and bullets. Apart from that the same rendering and animation components are added to the explosion entity.
In addition a new component called DestroyAfterCountdownComponent is added. The purpose of this component is to destroy an entity after a certain period of time. In this case we want to destroy the explosion entity once the animation has completed.
Pushbutton comes with a handy component called HealthComponent which can be used to maintain the health of an entity, cause damage to an entity by decreasing the health, and destroy the entity once all of its health is gone. This component is added to the enemy template, and we set the initial health of the enemy to 1 (it defaults to 100).
When the health managed by the HealthComponent is reduced to zero the entity is destroyed by default, but it also dispatches an event to let other components know that the entity has died. The DeathHandlerComponent is used to watch for this event and add the a new instance of the explosion entity.
The DamageOnContactConponent, which was introduced in the last tutorial, has been modified to find the health component of the entity that is has collided with and call its damage function, which will reduce the health of the other entity and eventually destroy it. The CollisionEvent which is passed to the collision event listener function has references to two Box2DSpatialComponent called collidee and collider. You can’t assume one or the other belongs to the same entity as the DamageOnContactConponent, so both have to be checked to find the Box2DSpatialComponent that belongs to the other entity involved in the collision.
public class DamageOnContactConponent extends EntityComponent
{
public var damage:int = 0;
public function DamageOnContactConponent()
{
super();
}
protected override function onAdd():void
{
super.onAdd();
owner.eventDispatcher.addEventListener(CollisionEvent.COLLISION_EVENT, OnCollision);
}
protected override function onRemove():void
{
super.onRemove();
owner.eventDispatcher.removeEventListener(CollisionEvent.COLLISION_EVENT, OnCollision);
}
private function OnCollision(event:CollisionEvent):void
{
var mySpatial:Box2DSpatialComponent = owner.lookupComponentByType(Box2DSpatialComponent) as Box2DSpatialComponent;
var other:Box2DSpatialComponent = event.collidee === mySpatial?event.collider:event.collidee;
var otherHealth:HealthComponent = other.owner.lookupComponentByType(HealthComponent) as HealthComponent;
if (otherHealth != null) otherHealth.damage(damage);
owner.destroy();
}
}
The new DeathHandlerComponent component sets the onDied function to be called in the event of a HealthComponent.DIED event. Inside the onDied a new instance of the Explosion template is created and positioned. Notice that we try and pull out a reference to both a Box2DSpatialComponent and SimpleSpatialComponent component in order to set the initial position of the explosion. Of course we know that the explosion entity contains a SimpleSpatialComponent (because that is what we game it in the XML file), but I left this code in to highlight one of the issues with the PushButton component design system, which is that components that perform the same function are quite often unrelated. In this case both the Box2DSpatialComponent and SimpleSpatialComponent provide a way to position an entity in space, the actual position variable is not specified as part of a common interface or base class, forcing us to check for the existence of both components when trying to set the initial position.
public class DeathHandlerComponent extends EntityComponent
{
public var PositionReference:PropertyReference = null;
public function DeathHandlerComponent()
{
super();
}
protected override function onAdd():void
{
super.onAdd();
owner.eventDispatcher.addEventListener(HealthComponent.DIED, onDied);
}
protected override function onRemove():void
{
super.onRemove();
owner.eventDispatcher.removeEventListener(HealthComponent.DIED, onDied);
}
protected function onDied(event:Event):void
{
var position:Point = owner.getProperty(PositionReference);
var entity:IEntity = TemplateManager.instance.instantiateEntity("Explosion");
if (entity != null)
{
var spatial:Box2DSpatialComponent =
entity.lookupComponentByType(Box2DSpatialComponent) as Box2DSpatialComponent;
var simpleSpatial:SimpleSpatialComponent =
entity.lookupComponentByType(SimpleSpatialComponent) as SimpleSpatialComponent;
if (spatial != null)
{
spatial.position = new Point(position.x, position.y);
}
else if (simpleSpatial != null)
{
simpleSpatial.position = new Point(position.x, position.y);
}
var anim:AnimationController =
entity.lookupComponentByType(AnimationController) as AnimationController;
if (anim)
anim.setAnimation(anim.animations[anim.defaultAnimation]);
}
}
}
Finally the DestroyIfOffScreenComponent will count down a internal counter, destroying the entity to which is belongs once that counter has reached zero.
public class DestroyAfterCountdownComponent extends TickedComponent
{
public var TimeToLive:Number = 1;
protected var remainingTime:Number = 1;
public function DestroyAfterCountdownComponent()
{
super();
}
protected override function onAdd():void
{
super.onAdd();
remainingTime = TimeToLive;
}
public override function onTick(tickRate:Number):void
{
remainingTime -= tickRate;
if (remainingTime <= 0)
owner.destroy();
}
}
In C++ an array is a set of consecutive objects of the same type, in memory. We see how to crea...
A database is a set of related tables. This is part 1, division 1 of a series I have on databas...
To easy way lean java programming language with a basic concepts which will help to build basic...
its an tutorial to make a virus /worm in C language...
cracking unix system password all about unix cracking it quite easily...
In this tutorial we add mouse interactivity to the scene....
In this tutorial we allow the view of the isometric scene to be moved with the mouse....
In this tutorial we show the height of an isometric object by adding a shadow....
In this tutorial we modify the appearance of the isometric cube at runtime....
In this tutorial we add some animated isometric boxes to the scene....