//public Object WayPointsLock = new Object(); public PathFindRequest(MoveCommand command, PathNode startNode, int priority, bool queued, bool avoidUnits) { Command = command; StartNode = startNode; AvoidUnits = avoidUnits; Priority = priority; Queued = queued; AttackCommand attackCommand = command as AttackCommand; if (attackCommand != null) { Target = attackCommand.Target; } HarvestCommand harvestCommand = command as HarvestCommand; if (harvestCommand != null) { Target = harvestCommand.TargetResource; } ReturnCargoCommand returnCargoCommand = command as ReturnCargoCommand; if (returnCargoCommand != null) { Target = returnCargoCommand.TargetStructure; } }
void processUnitAttackCommandBatch(NetIncomingMessage msg) { float scheduledTime = msg.ReadFloat(); short team = msg.ReadInt16(); bool queued = msg.ReadBoolean(); short count = msg.ReadInt16(); RtsObject target; short targetIsStructure = msg.ReadInt16(); if (targetIsStructure == 0) { short targetID = msg.ReadInt16(); short targetTeam = msg.ReadInt16(); target = Player.Players[targetTeam].UnitArray[targetID]; } else { short targetID = msg.ReadInt16(); short targetTeam = msg.ReadInt16(); target = Player.Players[targetTeam].StructureArray[targetID]; } for (int i = 0; i < count; i++) { Unit unit = Player.Players[team].UnitArray[msg.ReadInt16()]; if (unit != null) { AttackCommand attackCommand = new AttackCommand(unit, target, false, false); Player.Players[target.Team].ScheduledActions.Add(new ScheduledUnitCommand(scheduledTime, attackCommand, queued)); //Rts.pathFinder.AddHighPriorityPathFindRequest(attackCommand, (int)Vector2.DistanceSquared(attackCommand.Unit.CenterPoint, attackCommand.Destination), false); } } }
void performAttackIfStarted(AttackCommand command) { if (attackStarted) { if (timeSinceLastAttack >= initialAttackDelay) { attackStarted = false; RtsBullet b = new RtsBullet(this, command.Target, centerPoint, BulletSize, 200); b.Texture = BulletTexture; } } }
// when attacking void checkForPush(AttackCommand command) { lock (PotentialCollisions) { foreach (Unit unit in PotentialCollisions) { if (Intersects(unit)) { float angle = (float)Math.Atan2(unit.centerPoint.Y - centerPoint.Y, unit.centerPoint.X - centerPoint.X); float distance = Radius + unit.Radius; float force = distance - Vector2.Distance(unit.centerPoint, centerPoint); if (unit == command.Target) { PushSimple(angle + (float)Math.PI, force); } //else if (unit.IsAttacking && ((AttackCommand)unit.Commands[0]).Target == command.Target) //{ // PushSimple(angle + (float)Math.PI, force); //} else if (unit.IsAttacking && unit.isWithinRangeOfTarget) { PushSimple(angle + (float)Math.PI, force); avoidingUnits = true; isWithinRangeOfTarget = true; } else { //pushCount++; float sizeRatio = this.Diameter / unit.Diameter; float pushForce = force * (.1f * sizeRatio); unit.Push(this, angle, pushForce); PushSimple(angle + (float)Math.PI, force - pushForce); //unit.Push(this, angle, force * (.1f); //PushSimple(angle + (float)Math.PI, force * .9f); } } } } }
public void NextCommand() { if (Commands.Count == 0) return; UnitCommand lastCommand = Commands[0]; lastCommand.Active = false; Commands.RemoveAt(0); //Player.Players[Team].UnitCommands.Remove(lastCommand); IgnoringCollision = false; MoveCommand lastMoveCommand = lastCommand as MoveCommand; if (lastMoveCommand != null) { lastMoveDestination = lastWayPoint; if (Commands.Count > 0 && Commands[0] is MoveCommand) { MoveCommand newMoveCommand = (MoveCommand)Commands[0]; //if (Team == Player.Me.Team) Rts.pathFinder.AddPathFindRequest(newMoveCommand, false, false, false); //newMoveCommand.WayPoints = PathFinder.FindPath(CurrentPathNode, newMoveCommand.Destination, false); IgnoringCollision = (newMoveCommand is HarvestCommand || newMoveCommand is ReturnCargoCommand); return; } } // look for new target immediately if on attack move command if (Commands.Count > 0 && Commands[0] is AttackMoveCommand) { AttackMoveCommand attackMoveCommand = (AttackMoveCommand)Commands[0]; RtsObject target = FindNearestTarget(); if (target != null) { Commands[0] = new AttackCommand(this, target, true, false); Commands.Insert(1, attackMoveCommand); //IgnoringCollision = false; //return; } } timeSinceLastRecalculatePath = 0; attackStarted = false; }
public void GiveCommand(MoveCommand command) { if (Busy) { if (Commands.Count > 1) { //for (int i = 1; i < Commands.Count - 1; i++) // Player.Players[Team].UnitCommands.Remove(Commands[i]); Commands.RemoveRange(1, Commands.Count - 1); } return; } IgnoringCollision = (command is HarvestCommand || command is ReturnCargoCommand); // use previous path with new destination tacked on until new path is calculated // (LoL style) int commandPriority = -1; if (Commands.Count > 0 && !command.Calculated) { MoveCommand lastMoveCommand = Commands[0] as MoveCommand; if (lastMoveCommand != null) { if (lastMoveCommand.Destination == command.Destination) return; command.WayPoints = lastMoveCommand.WayPoints; command.WayPoints.Add(command.Destination); Rts.pathFinder.Tools.SmoothPathEnd(command.WayPoints, this); commandPriority = ((int)Vector2.DistanceSquared(lastMoveCommand.Destination, command.Destination) + (int)Vector2.DistanceSquared(centerPoint, command.Destination)) / 2; } } deactivateAllCommands(); clearCommands(); Commands.Add(command); lastWayPoint = centerPoint; lastMoveDestination = command.Destination; timeSinceLastRecalculatePath = 0; //command.WayPoints = PathFinder.FindPath(CurrentPathNode, command.Destination, false); if (command is ReturnCargoCommand || command is HarvestCommand) commandPriority = int.MaxValue / 2 + (int)Vector2.DistanceSquared(centerPoint, command.Destination); else if (commandPriority == -1) commandPriority = (int)Vector2.DistanceSquared(centerPoint, command.Destination); //AttackCommand attackCommand = command as AttackCommand; //if (attackCommand != null) //PathFinder.AddHighPriorityPathFindRequest(this, command, CurrentPathNode, commandPriority, false); //else //if (Team == Player.Me.Team) //PathFinder.AddHighPriorityPathFindRequest(command, commandPriority, false); // look for target if attack move command if (command is AttackMoveCommand) { RtsObject target = FindNearestTarget(); if (target != null) { Commands[0] = new AttackCommand(this, target, true, false); Commands.Insert(1, command); return; } timeSinceLastLookForTarget = lookForTargetDelay; } }
void performAttackIfStarted(AttackCommand command) { if (attackStarted) { if (timeSinceLastAttack >= initialAttackDelay) { attackStarted = false; RtsBullet b = new RtsBullet(type.BulletType, this, command.Target, centerPoint, BulletSize, BulletSpeed); } } }
void LookForNewTarget(AttackCommand command) { }
void AttackMove(AttackMoveCommand command, GameTime gameTime) { /*List<RtsObject> targets = new List<RtsObject>(); lock (VisibleTiles) { foreach (MapTile tile in VisibleTiles) { foreach (Unit unit in PathFinder.PathNodes[tile.Y, tile.X].UnitsContained) { if (unit.Team != Team) { Commands[0] = new AttackCommand(unit); Commands.Insert(1, command); return; } } } }*/ if (timeSinceLastLookForTarget >= lookForTargetDelay) { timeSinceLastLookForTarget = 0; RtsObject target = FindNearestTarget(); if (target != null) { Commands[0] = new AttackCommand(this, target, true, false); Commands.Insert(1, command); return; } } Move(command, gameTime); }
//int initialAttackDelay = 0;// = 150; void Attack(AttackCommand command, GameTime gameTime) { avoidingUnits = false; isWithinRangeOfTarget = false; // if original target is gone, stop attack if (command.Target == null || command.Target.IsDead) { attackStarted = false; if (command.HoldPosition) GiveCommand(new HoldPositionCommand(this)); else NextCommand(); return; } clearPushStatus(); clearHitWallStatus(); //float angle = (float)Math.Atan2(command.Target.CenterPoint.Y - centerPoint.Y, command.Target.CenterPoint.X - centerPoint.X); float distanceToTarget = Vector2.Distance(centerPoint, command.Target.CenterPoint) - (Radius + command.Target.Radius); if (distanceToTarget <= attackRange) { isWithinRangeOfTarget = true; // begin attack animation if (timeSinceLastAttack >= attackDelay) { timeSinceLastAttack = 0; attackStarted = true; } turnTowards(command.Target.CenterPoint, 120 / Radius, gameTime); } else if (attackStarted) { isWithinRangeOfTarget = false; attackStarted = false; } else if (!attackStarted) { Vector2 wayPoint = command.WayPoints[0]; if (!command.HoldPosition) { //float moveX = Util.ScaleWithGameTime(speed.X, gameTime); //float moveY = Util.ScaleWithGameTime(speed.Y, gameTime); Speed = MathHelper.Min(Speed + acceleration, MaxSpeed); float moveX = Util.ScaleWithGameTime(Speed, gameTime); float moveY = moveX; Vector2 difference = wayPoint - centerPoint; if (Math.Abs(difference.X) < moveX && Math.Abs(difference.Y) < moveY) { this.CenterPoint = wayPoint; HasMoved = true; lastWayPoint = wayPoint; if (command.WayPoints.Count > 1) command.NextWayPoint(this, Rts.pathFinder); return; } float angle = (float)Math.Atan2(wayPoint.Y - centerPoint.Y, wayPoint.X - centerPoint.X); moveX *= (float)Math.Cos(angle); moveY *= (float)Math.Sin(angle); lastMove.X = moveX; lastMove.Y = moveY; PrecisePosition += lastMove; HasMoved = true; } checkForWallHit(command); // checkForPush sets avoidingUnits checkForPush(command); command.Destination = command.Target.CenterPoint; if (!turnTowards(wayPoint, 120 / Radius, gameTime)) { Speed = MathHelper.Max(Speed - Util.ScaleWithGameTime(acceleration, gameTime), 0); } if (!command.HoldPosition) { if (timeSinceLastRecalculatePath >= recalculatePathDelay)// && command.Calculated) { timeSinceLastRecalculatePath = 0; Rts.pathFinder.AddPathFindRequest(command, false, true, avoidingUnits); } // repath to avoid units /*if (avoidingUnits) { if (timeSinceLastRecalculatePath >= recalculatePathDelay)// && command.Calculated) { timeSinceLastRecalculatePath = 0; PathFinder.AddLowPriorityPathFindRequest(this, command, CurrentPathNode, (int)Vector2.DistanceSquared(centerPoint, command.Destination), true); } } // normal repathing else if (timeSinceLastRecalculatePath >= recalculatePathDelay)// && command.Calculated) { timeSinceLastRecalculatePath = 0; PathFinder.AddLowPriorityPathFindRequest(this, command, CurrentPathNode, (int)Vector2.DistanceSquared(centerPoint, command.Destination), false); }*/ } } // periodically switch or lose target if (command.Target.Team != Team && timeSinceLastLookForTarget >= lookForTargetDelay) { timeSinceLastLookForTarget = 0; // switch to closer target if possible if (command.WillingToChangeTarget) { RtsObject newTarget = FindNearestTarget(); if (newTarget == null) { if (command.HoldPosition) GiveCommand(new HoldPositionCommand(this)); else NextCommand(); } else { command.Target = newTarget; return; } } //else if (command.WillingToChangeTarget) // command.Target = newTarget; // lose target if out of vision //if (!command.Target.CurrentPathNode.Tile.Visible) if (!command.Target.Visible) { //if (command.HoldPosition) // GiveCommand(new HoldPositionCommand()); //else // nextCommand(); command.Target = null; } } }
public void Update(GameTime gameTime) { int elapsedMilliseconds = (int)gameTime.ElapsedGameTime.TotalMilliseconds; timeSinceLastRecalculatePath += elapsedMilliseconds; timeSinceLastAttack += elapsedMilliseconds; updateCurrentPathNode(); if (Commands.Count == 0) { return; } UnitCommand command = Commands[0]; if (command is AttackCommand) { AttackCommand attackCommand = (AttackCommand)command; if (attackCommand.Target.IsDead) { nextCommand(); } else { Attack(attackCommand, gameTime); performAttackIfStarted(attackCommand); } } else if (command is MoveCommand) { MoveCommand moveCommand = (MoveCommand)command; /*if (timeSinceLastRecalculatePath >= recalculatePathDelay && moveCommand.Calculated) * { * timeSinceLastRecalculatePath = 0; * PathFinder.AddLowPriorityPathFindRequest(this, moveCommand, CurrentPathNode, (int)Vector2.Distance(centerPoint, moveCommand.Destination), false); * }*/ //if (instanceFrameCount % reCalculatePathFrameDelay == 1) // PathFinder.SmoothPath(moveCommand.WayPoints, this); Move(moveCommand, gameTime); } // update attack command destinations for (int i = 0; i < Commands.Count; i++) { AttackCommand c = Commands[i] as AttackCommand; if (c != null) { if (c.Target.IsDead) { Commands.Remove(c); i--; } else { c.Destination = c.Target.CenterPoint; } } } // update queued command starting points for (int i = 1; i < Commands.Count; i++) { MoveCommand c = Commands[i] as MoveCommand; MoveCommand previous = Commands[i - 1] as MoveCommand; if (c != null && previous != null) { c.WayPoints[0] = previous.Destination; } } // recalculate queued paths /*if (command is MoveCommand && instanceFrameCount % (reCalculatePathFrameDelay) == 0) * { * MoveCommand moveCommand = (MoveCommand)command; * for (int i = 1; i < Commands.Count; i++) * { * MoveCommand c = Commands[i] as MoveCommand; * MoveCommand previousCommand = Commands[i - 1] as MoveCommand; * if (c != null && previousCommand != null) * { * int y = (int)MathHelper.Clamp(previousCommand.Destination.Y / Map.TileSize, 0, Map.Height - 1); * int x = (int)MathHelper.Clamp(previousCommand.Destination.X / Map.TileSize, 0, Map.Width - 1); * * PathNode node = PathFinder.PathNodes[y, x]; * if (!node.Tile.Walkable) * node = PathFinder.FindNearestPathNode(y, x); * * c.WayPoints = PathFinder.FindPath(node, c.Destination, false); * } * } * }*/ }
void Attack(AttackCommand command, GameTime gameTime) { avoidingUnits = false; isWithinRangeOfTarget = false; if (command.Target.IsDead) { nextCommand(); return; } clearPushStatus(); clearHitWallStatus(); //float angle = (float)Math.Atan2(command.Target.CenterPoint.Y - centerPoint.Y, command.Target.CenterPoint.X - centerPoint.X); float distanceToTarget = Vector2.Distance(centerPoint, command.Target.CenterPoint) - (Radius + command.Target.Radius); if (distanceToTarget <= attackRange) { isWithinRangeOfTarget = true; // begin attack animation if (timeSinceLastAttack >= attackDelay) { timeSinceLastAttack = 0; attackStarted = true; } turnTowards(command.Target.CenterPoint, 120 / Radius, gameTime); } else if (!attackStarted) { float moveX = Util.ScaleWithGameTime(speed.X, gameTime); float moveY = Util.ScaleWithGameTime(speed.Y, gameTime); Vector2 wayPoint = command.WayPoints[0]; Vector2 difference = wayPoint - centerPoint; if (Math.Abs(difference.X) < moveX && Math.Abs(difference.Y) < moveY) { this.CenterPoint = wayPoint; lastWayPoint = wayPoint; if (command.WayPoints.Count > 1) command.NextWayPoint(this, PathFinder); return; } float angle = (float)Math.Atan2(wayPoint.Y - centerPoint.Y, wayPoint.X - centerPoint.X); moveX *= (float)Math.Cos(angle); moveY *= (float)Math.Sin(angle); lastMove.X = moveX; lastMove.Y = moveY; PrecisePosition += lastMove; checkForWallHit(); // checkForPush sets avoidingUnits checkForPush(command); command.Destination = command.Target.CenterPoint; turnTowards(wayPoint, 120 / Radius, gameTime); } if (avoidingUnits) { if (timeSinceLastRecalculatePath >= recalculatePathDelay * 2) { timeSinceLastRecalculatePath = 0; //command.WayPoints = PathFinder.FindPath(CurrentPathNode, command.Target.CenterPoint, true); PathFinder.AddLowPriorityPathFindRequest(this, command, CurrentPathNode, (int)Vector2.DistanceSquared(centerPoint, command.Destination), true); } } else if (timeSinceLastRecalculatePath >= recalculatePathDelay) { timeSinceLastRecalculatePath = 0; //command.WayPoints = PathFinder.FindPath(CurrentPathNode, command.Target.CenterPoint, false); PathFinder.AddLowPriorityPathFindRequest(this, command, CurrentPathNode, (int)Vector2.DistanceSquared(centerPoint, command.Destination), false); } }
void Attack(AttackCommand command, GameTime gameTime) { avoidingUnits = false; isWithinRangeOfTarget = false; if (command.Target.IsDead) { nextCommand(); return; } clearPushStatus(); clearHitWallStatus(); //float angle = (float)Math.Atan2(command.Target.CenterPoint.Y - centerPoint.Y, command.Target.CenterPoint.X - centerPoint.X); float distanceToTarget = Vector2.Distance(centerPoint, command.Target.CenterPoint) - (Radius + command.Target.Radius); if (distanceToTarget <= attackRange) { isWithinRangeOfTarget = true; // begin attack animation if (timeSinceLastAttack >= attackDelay) { timeSinceLastAttack = 0; attackStarted = true; } turnTowards(command.Target.CenterPoint, 120 / Radius, gameTime); } else if (!attackStarted) { float moveX = Util.ScaleWithGameTime(speed.X, gameTime); float moveY = Util.ScaleWithGameTime(speed.Y, gameTime); Vector2 wayPoint = command.WayPoints[0]; Vector2 difference = wayPoint - centerPoint; if (Math.Abs(difference.X) < moveX && Math.Abs(difference.Y) < moveY) { this.CenterPoint = wayPoint; lastWayPoint = wayPoint; if (command.WayPoints.Count > 1) { command.NextWayPoint(this, PathFinder); } return; } float angle = (float)Math.Atan2(wayPoint.Y - centerPoint.Y, wayPoint.X - centerPoint.X); moveX *= (float)Math.Cos(angle); moveY *= (float)Math.Sin(angle); lastMove.X = moveX; lastMove.Y = moveY; PrecisePosition += lastMove; checkForWallHit(); // checkForPush sets avoidingUnits checkForPush(command); command.Destination = command.Target.CenterPoint; turnTowards(wayPoint, 120 / Radius, gameTime); } if (avoidingUnits) { if (timeSinceLastRecalculatePath >= recalculatePathDelay * 2) { timeSinceLastRecalculatePath = 0; //command.WayPoints = PathFinder.FindPath(CurrentPathNode, command.Target.CenterPoint, true); PathFinder.AddLowPriorityPathFindRequest(this, command, CurrentPathNode, (int)Vector2.DistanceSquared(centerPoint, command.Destination), true); } } else if (timeSinceLastRecalculatePath >= recalculatePathDelay) { timeSinceLastRecalculatePath = 0; //command.WayPoints = PathFinder.FindPath(CurrentPathNode, command.Target.CenterPoint, false); PathFinder.AddLowPriorityPathFindRequest(this, command, CurrentPathNode, (int)Vector2.DistanceSquared(centerPoint, command.Destination), false); } }
// when attacking protected void checkForPush(AttackCommand command) { //lock (PotentialCollisions) { foreach (Unit unit in PotentialCollisions) { if (!unit.IgnoringCollision && Intersects(unit)) { float angle = (float)Math.Atan2(unit.centerPoint.Y - centerPoint.Y, unit.centerPoint.X - centerPoint.X); float distance = Radius + unit.Radius; float force = distance - Vector2.Distance(unit.centerPoint, centerPoint); if (unit.Team != Team || unit == command.Target) { PushSimple(angle + (float)Math.PI, force); } //else if (unit.IsAttacking && ((AttackCommand)unit.Commands[0]).Target == command.Target) //{ // PushSimple(angle + (float)Math.PI, force); //} else if (unit.IsAttacking && unit.isWithinRangeOfTarget) { PushSimple(angle + (float)Math.PI, force); avoidingUnits = true; isWithinRangeOfTarget = true; } else { //pushCount++; float sizeRatio = this.Diameter / unit.Diameter; float pushForce = force * (.1f * sizeRatio); unit.Push(this, angle, pushForce); PushSimple(angle + (float)Math.PI, force - pushForce); //unit.Push(this, angle, force * (.1f); //PushSimple(angle + (float)Math.PI, force * .9f); } } } } }
void giveAttackCommand(Vector2 mousePosition) { foreach (Unit unit in Unit.Units) { if (unit.Contains(mousePosition)) { UnitAnimation redCircleAnimation = new UnitAnimation(unit, unit.Width, .75f, 8, false, redCircleTexture, transparentTexture); redCircleAnimation.Start(); foreach (Unit u in SelectedUnits) { if (u != unit) { if (keyboardState.IsKeyUp(Keys.LeftShift)) { AttackCommand command = new AttackCommand(unit); u.GiveCommand(command); Unit.PathFinder.AddHighPriorityPathFindRequest(u, command, u.CurrentPathNode, (int)Vector2.DistanceSquared(u.CenterPoint, command.Destination), false); //u.GiveCommand(new AttackCommand(unit)); } else u.QueueCommand(new AttackCommand(unit)); } } return; } } giveMoveCommand(mousePosition); }