private bool CanStillPathToNode(NavigationNode currentNode) { Vector3 pos = ParentObject.Transform.AbsoluteTransform.Translation; pos.Y = 0; Vector3 toNode = currentNode.WorldPosition - pos; Vector3 perpendicularVec = Vector3.Cross(toNode, Vector3.Up); perpendicularVec.Y = 0; //width perpendicularVec *= 0.01f; //if we pass all 3 of these tests, this means we have clear LOS //to this node, wide enough to squeeze through. So we can skip prior nodes. if (!mapHandler.IntersectsLevel(pos, currentNode.WorldPosition)) { if (!mapHandler.IntersectsLevel(pos + perpendicularVec, currentNode.WorldPosition + perpendicularVec)) { if (!mapHandler.IntersectsLevel(pos - perpendicularVec, currentNode.WorldPosition - perpendicularVec)) { return(true); } else { return(false); } } else { return(false); } } else { return(false); } }
public void Update(GameTime gameTime) { ParentObject.GetComponent <DoomMovementComponent>().Enabled = true; //when in combat, get much more frequent updates on enemy movements. apiHandler.frequentRequests.Find(x => x.Request.Resource.Contains("world")).Fequency = 4000; //check LOS to monsters. If if (worldObjects == null) { shotsFired = 0; return; } if (worldObjects.Count == 0) { shotsFired = 0; return; } //get all the monsters from the world object list. //monsters are ALL IN CAPS var monsters = worldObjects.Values.Where(x => IsAllUpper(x.GetComponent <DoomComponent>().DoomType)).ToList(); //forget about the dead ones. monsters.RemoveAll(x => x.GetComponent <DoomComponent>().Health <= 0); //can we see any of these guys? List <GameObject> visibleMonsters = new List <GameObject>(); foreach (GameObject monster in monsters) { if (!mapHandler.IntersectsLevel(ParentObject.Transform.AbsoluteTransform.Translation, monster.Transform.AbsoluteTransform.Translation, true)) { //we can see it. visibleMonsters.Add(monster); foreach (DoomLine door in mapHandler.Doors) { if (MonoMathHelper.LineIntersection(ParentObject.Transform.AbsoluteTransform.Translation.ToVector2XZ(), monster.Transform.AbsoluteTransform.Translation.ToVector2XZ(), door.start.ToVector2XZ(), door.end.ToVector2XZ())) { //there's a door between us and the monster. remove it if (visibleMonsters.Contains(monster)) { visibleMonsters.Remove(monster); } } } } } if (visibleMonsters.Count == 0) { shotsFired = 0; return; } //when in combat, get much more frequent updates on enemy movements. apiHandler.frequentRequests.Find(x => x.Request.Resource.Contains("world")).Fequency = 500; GameObject target = null; float closestDist = float.MaxValue; foreach (GameObject vm in visibleMonsters) { Vector3 toMonsterVec = ParentObject.Transform.AbsoluteTransform.Translation - vm.Transform.AbsoluteTransform.Translation; if (toMonsterVec.Length() < closestDist) { target = vm; closestDist = toMonsterVec.Length(); } } if (closestDist > minimumCombatDistance) { shotsFired = 0; return; } //disable movement. ParentObject.GetComponent <DoomMovementComponent>().Enabled = false; DebugShapeRenderer.AddLine(ParentObject.Transform.AbsoluteTransform.Translation, target.Transform.AbsoluteTransform.Translation, Color.OrangeRed); Vector3 targetPosition = target.Transform.AbsoluteTransform.Translation; Vector3 toTarget = targetPosition - ParentObject.Transform.AbsoluteTransform.Translation; toTarget.Y = 0; toTarget.Normalize(); Vector3 rightV = ParentObject.Transform.AbsoluteTransform.Right; rightV.Y = 0; rightV.Normalize(); Vector3 forwardVec = ParentObject.Transform.AbsoluteTransform.Forward; forwardVec.Y = 0; forwardVec.Normalize(); float dot = Vector3.Dot(toTarget, rightV); //game units are roughly 105 in a circle. //so 1 unit = 360 / 105 degrees //1 degree = 105 / 360 var angle = MathHelper.ToDegrees(MonoMathHelper.GetAngleBetweenVectors(toTarget, forwardVec)); float heading = MathHelper.ToDegrees(MonoMathHelper.GetHeadingFromVector((toTarget).ToVector2XZ())); heading = (heading + 360) % 360; if (dot > 0.05f) { if (!turning) { //TurnLeft(2); TurnLeftToHeading(heading); } } if (dot < -0.05f) { if (!turning) { //TurnRight(2); TurnRightToHeading(heading); } } if (dot > -0.3f && dot < 0.3f) { //the node we need is right behind us. Instigate a turn. if (MonoMathHelper.AlmostEquals(180d, angle, 10)) { TurnLeftToHeading(heading); return; } Shoot(); if (shotsFired > 8) { //we keep missing. shift the aim a bit. bool left = RandomHelper.CoinToss(); if (left) { TurnLeft(1); } else { TurnRight(1); } shotsFired = 0; } } }