public override bool Update(GameTime CurrTime) { Vector2 vNewPos; int nCtr, nBestTargetID = -1; float nBestTargetDist = 0, nCurrDist; List <PhysicalObject> aTargetList = cObjMgr[cnTargetGroupID]; bool bRetVal = true; base.Update(CurrTime); if (ctCreated == -1) //Just created, mark the time { ctCreated = CurrTime.TotalGameTime.TotalMilliseconds; } switch (ceProjType) { case eProjectileType_t.Tracking: //Find a target to track for (nCtr = 0; nCtr < aTargetList.Count; nCtr++) { nCurrDist = MGMath.SquaredDistanceBetweenPoints(CenterPoint, aTargetList[nCtr].CenterPoint); if (nBestTargetID == -1) //No target picked { nBestTargetID = nCtr; nBestTargetDist = nCurrDist; } else if (nCurrDist < nBestTargetDist) { nBestTargetID = nCtr; nBestTargetDist = nCurrDist; } } if (nBestTargetID != -1) //Found a valid target, steer toward it { nCurrDist = AITools.SteerTowardTarget(CenterPoint, aTargetList[nBestTargetID].CenterPoint, ObjectRotation, cnMaxTurn); //Set the new movement direction, but don't change the speed SetMovement(nCurrDist, cnMaxSpeed); } if (CurrTime.TotalGameTime.TotalMilliseconds - ctCreated > ctTimeToLive) { //Lived its full life, time to pop bRetVal = false; } break; case eProjectileType_t.Straight: default: //No logic, just flies straight if (cGraphDev.Viewport.Width < CenterPoint.X + Width) //remove it when off screen { bRetVal = false; } if (cGraphDev.Viewport.Height < CenterPoint.Y + Height) //remove it when off screen { bRetVal = false; } if (CenterPoint.X < -1 * Width) { bRetVal = false; } if (CenterPoint.Y < -1 * Height) { bRetVal = false; } break; } //Look for collisions with all possible targets foreach (PhysicalObject CurrObj in aTargetList) { if (CurrObj.TestCollision(this) == true) { //Hit a target! (tell it that it was hit) CurrObj.ReportCollision(CurrTime, this); bRetVal = false; break; } } //Apply the current speed vNewPos = CenterPoint; vNewPos.X += Speed.X; vNewPos.Y += Speed.Y; CenterPoint = vNewPos; if ((ParticleHandler != null) && (bRetVal == false)) { //Missile is expiring, throw some particles for (nCtr = 0; nCtr < 10; nCtr++) { ParticleHandler.AddParticle(new DustParticle(CenterPoint, Rand, cGraphDev, cImgAtlas, "spaceEffects_008.png")); } } //Return True to keep this alive, false to have it removed return(bRetVal); }
public override bool Update(GameTime CurrTime) { int nCtr, nBestTargetID = -1, nBestAvoidID = -1; float nBestTargetDist = 0, nBestAvoidDist = 0, nCurrDist, nAvoidDir, nTargetDir; Vector2 vNewPos; List <PhysicalObject> aTargetList = cObjMgr[cnTargetGroupID]; List <PhysicalObject> aAvoidList = cObjMgr[cnAvoidGroupID]; base.Update(CurrTime); if (cnHealth <= 0) { //This enemy is dead :( //Should fire off some explosion particles return(false); } cTarget = null; cAvoid = null; //Find a target to track for (nCtr = 0; nCtr < aTargetList.Count; nCtr++) { nCurrDist = MGMath.SquaredDistanceBetweenPoints(CenterPoint, aTargetList[nCtr].CenterPoint); if (nBestTargetID == -1) //No target picked { nBestTargetID = nCtr; nBestTargetDist = nCurrDist; cTarget = aTargetList[nCtr]; } else if (nCurrDist < nBestTargetDist) { nBestTargetID = nCtr; nBestTargetDist = nCurrDist; cTarget = aTargetList[nCtr]; } } for (nCtr = 0; nCtr < aAvoidList.Count; nCtr += 1) { nCurrDist = MGMath.SquaredDistanceBetweenPoints(CenterPoint, aAvoidList[nCtr].CenterPoint); if (nBestAvoidID == -1) //No target picked { nBestAvoidID = nCtr; nBestAvoidDist = nCurrDist; cAvoid = aAvoidList[nCtr]; } else if (nCurrDist < nBestAvoidDist) { nBestAvoidID = nCtr; nBestAvoidDist = nCurrDist; cAvoid = aAvoidList[nCtr]; } } if (nBestAvoidDist > cnMaxStrafeDist * cnMaxStrafeDist) { //Thing to avoid is too far away to worry about nBestAvoidID = -1; cAvoid = null; } if (nBestTargetID != -1) //Found a valid target, attack it { if (nBestTargetDist > (cnMaxStrafeDist * cnMaxStrafeDist)) { if (cnLastMove != 1) { cDevConsole?.AddText("Move closer"); } cnLastMove = 1; //Too far away to strafe, move closer nTargetDir = AITools.SteerTowardTarget(CenterPoint, aTargetList[nBestTargetID].CenterPoint, ObjectRotation, cnMaxTurn); } else if (nBestTargetDist < cnMinStrafeDist * cnMinStrafeDist) { if (cnLastMove != 2) { cDevConsole?.AddText("Back away"); } cnLastMove = 2; //Too close, steer away from target nTargetDir = AITools.SteerAwayFromTarget(CenterPoint, aTargetList[nBestTargetID].CenterPoint, ObjectRotation, cnMaxTurn); } else //Close enough, strafe around the target { if (cnLastMove != 3) { cDevConsole?.AddText("Strafe"); } cnLastMove = 3; nTargetDir = AITools.SteerToCircleTarget(CenterPoint, aTargetList[nBestTargetID].CenterPoint, ObjectRotation, cnMaxTurn, cbStrafeCW); } } else { nTargetDir = 0; } if (nBestAvoidID != -1) { nAvoidDir = AITools.SteerAwayFromTarget(CenterPoint, aAvoidList[nBestAvoidID].CenterPoint, ObjectRotation, cnMaxTurn); } else { nAvoidDir = 0; } if (cnTargetGroupID != -1) { if ((nBestAvoidID != -1) && (nBestAvoidDist < nBestTargetDist)) { //Thing to avoid is closer than the target, it gets priority nCurrDist = (0.75f * nAvoidDir) + (0.25f * nTargetDir); } else { //Target is closer, go for the kill nCurrDist = nTargetDir; } } else { //No target so just avoid? nCurrDist = nAvoidDir; } //Set the new movement direction, but don't change the speed SetMovement(nCurrDist, cnMaxSpeed); //Apply current speed vNewPos = CenterPoint; vNewPos.X += cvCurrSpeed.X; vNewPos.Y += cvCurrSpeed.Y; CenterPoint = vNewPos; if (ctHitFlashUntil > CurrTime.TotalGameTime.TotalMilliseconds) { //Flash red when being hit this.TintColor = Color.Red; } else { //Normal condition is white, for no tint this.TintColor = cclrNormalColor; } //Return True to keep this alive, false to have it removed return(true); }
public override bool Update(GameTime CurrTime) { Vector2 MyCenter, TargetCenter, Speed; float Distance; MyCenter.X = TopLeft.X + (Width / 2); MyCenter.Y = TopLeft.Y + (Height / 2); TargetCenter = TargetObject.GetCenterCoordinates(); Rotation = MGMath.GetAngleFromPoints(MyCenter, TargetCenter, true); Distance = MGMath.SquaredDistanceBetweenPoints(MyCenter, TargetCenter); if ((Distance >= MaxDistanceFromTarget * MaxDistanceFromTarget) && (cStrafeDirection != 0)) //Too far away get closer { Speed = MGMath.CalculateXYMagnitude(Rotation, 3); cStrafeDirection = 0; } else if ((Distance >= (MaxDistanceFromTarget * MaxDistanceFromTarget * 0.8f * 0.8f)) && (cStrafeDirection == 0)) //If moving forward overshoot a bit { Speed = MGMath.CalculateXYMagnitude(Rotation, 3); } else if (Distance <= MinDistanceFromTarget * MinDistanceFromTarget) //Too close back away { Speed = MGMath.CalculateXYMagnitude(Rotation + 3.14f, 3); cStrafeDirection = 0; } else if ((Distance <= MinDistanceFromTarget * MinDistanceFromTarget * 1.2f * 1.2f) && (cStrafeDirection == 0)) //If backing away overshoot a bit { Speed = MGMath.CalculateXYMagnitude(Rotation + 3.14f, 3); } else //Close enough, circle { if (cStrafeDirection == 0) { if (cRand.Next(1, 3) == 1) { cStrafeDirection = -1; } else { cStrafeDirection = 1; } } Speed = MGMath.CalculateXYMagnitude(Rotation + 1.57f, 2); Speed.X *= cStrafeDirection; Speed.Y *= cStrafeDirection; } SpeedX = (SpeedX + Speed.X) / 2; SpeedY = (SpeedY + Speed.Y) / 2; TopLeft.X += SpeedX; TopLeft.Y -= SpeedY; if (cLastShot == 0) { cLastShot = CurrTime.TotalGameTime.TotalMilliseconds + 1500 + cRand.Next(1000); } if (cLastShot < CurrTime.TotalGameTime.TotalMilliseconds) { Vector2 BulletOrigin; BulletOrigin.Y = TopLeft.Y + (Height / 2); BulletOrigin.X = TopLeft.X + (Height / 2); Rotation += (float)(cRand.Next(-10, 10) * (Math.PI / 180.0)); //Randmize the direction so that it's not perfect (+/- 10 degrees) BulletManager.AddParticle(BulletTexture, BulletOrigin.Y - 10, BulletOrigin.X - 10, 20, 20, Rotation, 8, new Color(255, 75, 75, 255)); cLastShot = CurrTime.TotalGameTime.TotalMilliseconds + 1500 + cRand.Next(1000); } return(true); }