12.07.2015 Views

Topic 11: Behaviour via Coroutines via Iterators - Undergraduate

Topic 11: Behaviour via Coroutines via Iterators - Undergraduate

Topic 11: Behaviour via Coroutines via Iterators - Undergraduate

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

CITS4242:Game Design and MultimediaFaculty of Engineering,Computing and MathematicsSCHOOL OF COMPUTER SCIENCE & SOFTWARE ENGINEERING<strong>Topic</strong> <strong>11</strong>:<strong>Behaviour</strong> <strong>via</strong> <strong>Coroutines</strong><strong>via</strong> <strong>Iterators</strong>


Implementing <strong>Behaviour</strong>// Continued from previous slideFaculty of Engineering,Computing and MathematicsSCHOOL OF COMPUTER SCIENCE & SOFTWARE ENGINEERINGprotected override void OnTick(){base.OnTick();updateTaskTimer -= TickDelta;if (updateTaskTimer


DefenderAI – FlockWithRevenge/// Flock, but take revenge on characters who collide with our character. protected IEnumerable FlockWithRevenge(){while (true){if (collidedWith != null && collidedWith != Target &&collidedWith.Type.InitialAI.Name == "ChaserAI"){foreach (var move in GetRevenge(collidedWith)) yield return move;collidedWith = null;}else{submesh.MaterialName = "RobotGreen";yield return Flock();}}}Target = origTarget;protected Vec2 Flock(){return steer.Wander(2, 4, 2) * WanderMult + steer.Arrive(Target.Position, 2) * ArriveMult +steer.Alignment(neighbours) * AlignMult + steer.Cohesion(neighbours) * CohesMult +steer.Separation(neighbours) * SepMult;}


DefenderAI.cs - GetRevengeIEnumerable GetRevenge(Character avengee){var oldTarget = Target;Target = avengee;submesh.MaterialName = "RobotBlue";for (int i = 0; i < 3f / timeInterval; i++) yield return Vec2.Zero; // Wait before starting revenge.while (true){submesh.MaterialName = "RobotWhite";foreach (var b in HitWith("Ball", avengee)) yield return b; // Do HitWith until it finishes.if (!failed) break;failed = false;submesh.MaterialName = "RobotPurple";foreach (var b in HitWith("Cart", avengee)) yield return b; // Do HitWith until it finishes.if (!failed) break;failed = false;}submesh.MaterialName = "RobotExtraRed";foreach (var b in ChaseHit(avengee)) yield return b; // Do ChaseHit until it finishes.if (!failed) break;failed = false;}String mat = submesh.MaterialName;for (int i = 0; i < 4f / timeInterval; i++) // Wait, flash colour{submesh.MaterialName = (i/10) % 2 == 0 ? "RobotCyan" : mat;yield return Vec2.Zero;}Target = oldTarget;yield break;


DefenderAI.cs – ChaseHit & GetDynamic/// Chase a target until a collision with it occurs./// IEnumerable ChaseHit(Character newTarget){chasing = true;collidedWith = null;int ticks = 0;float moveMult = 10f;while (collidedWith != Target){maxMoveForce = (ticks++ * timeInterval / 6f + 1f) * PlayerCharacter.Difficulty;GetNeighbours(Controlled.Type.Name);yield return steer.Pursuit(Target) * moveMult;}maxMoveForce = 1f;// +sb.Avoid(neighbours) * SepMult;chasing = false;collidedWith = null;}yield break;// caught target, chasing is finished, return no moves.Dynamic GetDynamicOfType(String dynTypeName){Dynamic ret=null;Map.Instance.GetObjects(new Sphere(Controlled.Position, Controlled.ViewRadius * 3f), mapObj =>{var dyn = mapObj as Dynamic;if (dyn != null && dyn.Type.Name == dynTypeName)ret = mapObj as Dynamic;});return ret;}


DefenderAI - HitWith/// Find a particular type of dynamic entity and hit it towards a target. IEnumerable HitWith(String useDynTypeName, Character aimAt){Dynamic useDyn=GetDynamicOfType(useDynTypeName);if (useDyn == null) { failed = true; yield break; }float duration = 0f;while ((duration += timeInterval) < 10f) // Move to about 3m behind Dyn{var DynPos = useDyn.Position.ToVec2();var runTo = DynPos + 3f * (DynPos - aimAt.Position.ToVec2()).GetNormalizeFast();if ((runTo - Controlled.Position.ToVec2()).LengthSqr() < 1f) break;yield return steer.Arrive(new Vec3(runTo.X, runTo.Y, useDyn.Position.Z), 1f);}if (duration > 10f) { failed = true; yield break; } // Failed to get in correct position.bool hit = false;Body.CollisionDelegate cd = (ref CollisionEvent ce) =>{if (ce.OtherShape.Body.UserData != null){var ent = ce.OtherShape.Body.UserData as Entity;if (ent != null & ent.Type == Target.Type) hit = true;}};foreach(var body in useDyn.PhysicsModel.Bodies) body.Collision += cd;}}while (!hit && (duration += timeInterval) < 30 * 15){if(useDyn.Position.Z < Controlled.MainBody.GetGlobalBounds().Maximum.Z) maxMoveForce = 5f;yield return steer.Pursuit(useDyn) * maxMoveForce; // Hit with a lot of extra force.maxMoveForce = 1f;}foreach (var body in useDyn.PhysicsModel.Bodies) body.Collision -= cd;if (!hit) { failed = true; yield break; }


DefenderAI - Points of interestFaculty of Engineering,Computing and MathematicsSCHOOL OF COMPUTER SCIENCE & SOFTWARE ENGINEERINGNote the following ways that behaviours are combined in DefenderAI:- The avoid and the FlockWithRevenge behaviours are run at the sametime (in parallel), with avoid taking priority.- FlockWithRevenge normally does the Flock behaviour, but it swaps tothe GetRevenge behaviour when hit by a “Chaser”, and continues untilGetRevenge completes.- GetRevenge tries three different ways of getting revenge in order, andcontinues until one of them succeeds.– So, we have sequencing, looping and goal directed behaviour.- HitWith attempts to locate the object, then gets on the opposite side ofit from the target, and hits it. It fails if it can't get to the right positionwithin 10sec.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!