/* Apply this script to the enemy object. Enemy must have the following Components: RigidBody BoxCollider EBullet script (set ShotProjectile to your projectile, Erun and Eshoot to different sprites if Applicable Speed to 5.0 to start and then adjust LeftBoundary to 3 units less than your enemy is at in the X RightBoundary to 3 units more than your enemy is at in the x StandOffDistance to 2 (this tells the enemy where to stope and shoot from) TargetObject: Selection your player with the target Chase speed set to 3 to see the difference ChaseTriggerDistance set to 5, this is the point that it detects the player object Leave the others for now.) Feel free to modify these settings after you have it functioning. IgnoreSpaceEffects (If you want it to pace back and forth off the ground) You must use this in conjunction with an archetype that is your projectile. The projectile object must have the projectile script as well as: RigidBody (set to Dynamic) SphereCollider (set to Ghost) Projectile Script (set speed to 5.0) Orientation (set to 0, 0, 1 and forwardXUpZ) Ignore Space Effects (check gravity and drag) */ class EBullet : ZilchComponent { //This is your archetype for the bullet [Property] var ShotProjectile : Archetype = null; // Pacing Properties and variables var InitialPos : Real; var WithinBoundaries : Boolean = true; [Property] var ERun : SpriteSource =null; [Property] var EShoot : SpriteSource =null; var LastLoc : Real = 0.0; [Property] var Speed : Real = 5.0; [Property] var LeftBoundary : Real = -4.0; [Property] var RightBoundary : Real = 5.0; [Property] var StandOffDistance : Real = 2.0; var PaceDirection: Real3 = Real3(0.0, 0.0, 0.0); var StartPosition: Real3 = Real3(); var ChaseDirection2 : Real3= Real3(); // Chasing Properties and variables [Property] var TargetObject: CogPath = null; [Property] var ChaseSpeed: Real = 1.0; [Property] var ChaseTriggerDistance: Real = 5.0; var DistanceFromTarget: Real = 0.0; var ChaseDirection: Real = Real(); var ChaseColor:Real4 = Real4(1.0, 0.0, 0.0, 1.0); var TargetIsWithinRange: Boolean = false; [Property] var First: Real3 = Real3(); // Shooting Properties [Property] var ShootDelay: Real = 1.0; [Property] var NextShot: Real = 0.1; // Variables for smoothing state transitions var OriginalColor: Real4 = Real4(); var ShotTimer: Real = 0.0; // Dependencies [Dependency] var Transform: Transform = null; [Dependency] var Sprite: Sprite = null; var TargetStop: Real3 = Real3(); var TargetStopX: Integer = 0; var OwnerXTranslation: Integer = 0; var Stop: Boolean = false; function Initialize(init : CogInitializer) { // We need to update the enemy's behavior every logic Zero.Connect(this.Space, Events.LogicUpdate, this.OnLogicUpdate); // Have to know where we started to know how far we've moved this.StartPosition = this.Owner.Transform.Translation; this.OriginalColor = this.Owner.Sprite.Color; this.InitialPos = this.Owner.Transform.Translation.X; this.First = this.Owner.Transform.Translation; } function OnLogicUpdate(event : UpdateEvent) { // Calculate the direction and distance of target this.CalculateChaseDirectionAndDistance(); // Evaluate whether Ai should chase, shoot or pace this.TargetIsWithinRange = (this.DistanceFromTarget <= this.ChaseTriggerDistance); if (this.TargetIsWithinRange) { //if the target is not in shooting range distance chase if(this.Stop == false) { //Make the Enemey run if(this.Owner.Sprite.SpriteSource != this.ERun) { this.Owner.Sprite.SpriteSource=this.ERun; } //Go after target this.ChaseTarget(event); //see if the target is the set distance away if(this.Owner.Transform.Translation.X - this.TargetObject.Cog.Transform.Translation.X <= this.StandOffDistance) { this.Stop = true; this.Owner.Sprite.FlipX=false; } else if (this.Owner.Transform.Translation.X - this.TargetObject.Cog.Transform.Translation.X >= -this.StandOffDistance) { this.Stop = true; this.Owner.Sprite.FlipX=true; } } else { //make the enemy look like it is shooting and lock the poition if(this.Owner.Sprite.SpriteSource != this.EShoot) { this.Owner.Sprite.SpriteSource = this.EShoot; this.Owner.RigidBody.Static = true; } //check what way to face if(this.ChaseDirection <0) { this.Owner.Sprite.FlipX=false; } else if (this.ChaseDirection>0) { this.Owner.Sprite.FlipX=true; } //otherwise shoot the target this.ShootAtTarget(event); //check the distance again if(this.Owner.Transform.Translation.X - this.TargetObject.Cog.Transform.Translation.X >= 5) { this.Stop = true; } else if (this.Owner.Transform.Translation.X - this.TargetObject.Cog.Transform.Translation.X <= -5) { this.Stop = true; } } } else { //Make the enemy run if the target is not in range of anything if(this.Owner.Sprite.SpriteSource != this.ERun) { this.Owner.Sprite.SpriteSource=this.ERun; } this.PaceBackAndForth(event); } } function PaceBackAndForth(event: UpdateEvent) { this.Move(event.Dt); //if the object is past the left boundary if (this.Owner.Transform.Translation.X < this.LeftBoundary) { //change directions. this.Speed *= -1; this.Owner.Sprite.FlipX = true; } //if the object is past the right boundary, else if (this.Owner.Transform.Translation.X > this.RightBoundary) { //change directions. this.Speed *= -1; this.Owner.Sprite.FlipX = false; } if(this.Speed<0) { this.Owner.Sprite.FlipX = false; } if(this.Speed>0) { this.Owner.Sprite.FlipX = true; } } function Move(deltaTime : Real) { var movement = Real3(0.0, 0.0, 0.0); var currentPos = this.Owner.Transform.Translation; movement += Real3(this.Speed, 0.0, 0.0); currentPos += movement * deltaTime; this.Owner.Transform.Translation = currentPos; } function CalculateChaseDirectionAndDistance() { // Get direction toward target this.ChaseDirection = this.TargetObject.Cog.Transform.Translation.X - this.Owner.Transform.Translation.X; // Extract distance by finding magnitude this.DistanceFromTarget = Math.Length(Real3(this.ChaseDirection, 0, 0)); // Extract direction by normalizing this.ChaseDirection2 = Math.Normalize(Real3(this.ChaseDirection, 0, 0)); } function ChaseTarget(event: UpdateEvent) { // Apply movement this.Owner.Transform.Translation += this.ChaseDirection2 * event.Dt * this.ChaseSpeed; } function ShootAtTarget(event: UpdateEvent) { this.ShotTimer += event.Dt; // Don't shoot until the next shot timer is reached if (this.ShotTimer > this.NextShot) { // Update next shot timer this.NextShot = this.ShotTimer + this.ShootDelay; // Create a projectile originating from the enemy's position var projectileObject = this.Space.CreateAtPosition(this.ShotProjectile, this.Owner.Transform.Translation); if (projectileObject != null) { // Shoot in the direction of the target (which is the same as the chase Direction) projectileObject.Projectile.Direction = this.ChaseDirection2; // Make sure projectile moves faster than the enemy projectileObject.Projectile.Speed = 15.0 + this.ChaseSpeed; } } } }