// can you move from one map node to another bool canMove(MapNodeBS start, MapNodeBS destination) { bool result = false; Color color = Color.red; Vector3 startPos = mapNodeToVector(start); Vector3 destPos = mapNodeToVector(destination); float dist = Vector3.Distance(startPos, destPos); if (MaxMapNodeDist > dist) { RaycastHit2D hitInfo = Physics2D.Raycast(startPos, destPos - startPos, dist, -1, 5f); // is there a collider in the way with hieght at least 5 (walls) if (hitInfo.collider == null) { //color = Color.green; //Debug.DrawLine(mapNodeToVector(start), mapNodeToVector(destination), color, 2000f); result = true; } else { //Debug.DrawLine(mapNodeToVector(start), mapNodeToVector(destination), color, 2000f); } } return(result); }
// returns the closest map node to the loc that is visible (not through a wall or person) public MapNodeBS VectorToMapNode(Vector3 loc) { MapNodeBS closestNode = null; float closestDist = Mathf.Infinity; foreach (MapNodeBS node in mapNodes) { // can we see the node? if (canSeeIgnoreCharacters(loc, node.transform.position)) { // is it the closest? float dist = Vector3.Distance(loc, node.transform.position); if (dist <= closestDist) { closestDist = dist; closestNode = node; } } } return(closestNode); }
// Update is called once per frame void Update() { Vector2 newPos = transform.position; // default bool is_moving = false; bool canSeeTarg = false; // NOW: lose % of intensity every X seconds float TimeMult = 1f; // The ratio of delta time into X seconds if (Time.deltaTime < forgetNoiseRate) { TimeMult = (forgetNoiseRate - Time.deltaTime) / forgetNoiseRate; } // drop intensity by a certain % each frame, drops quickly, stays nonzero for a long time if (targetIntensity > 0f) { targetIntensity = targetIntensity * TimeMult; } // lose intensity if we reach destination if (Vector2.Distance(transform.position, softTarget) < minForgetDistance) { targetIntensity = 0; } // only do logic every delayTime seconds if (Time.time > nextSyncTime) { nextSyncTime = Time.time + delayTime; // control which target mode we are in if (hardTarget != null) { targetmode = TargetMode.HardTarget; canSeeTarg = GAMESTATE.canSee(gameObject, hardTarget); // if the hard target gets too far away, switch to soft target float dist = Vector2.Distance(hardTarget.transform.position, transform.position); // if we cant see the hard target, set soft target and create a path if (canSeeTarg == false) { targetmode = TargetMode.FollowPath; softTarget = hardTarget.transform.position; pathDestinationTarget = softTarget; hardTarget = null; if (path == null) { //print("Find path1 at " + Time.time); path = GAMESTATE.findPath(transform.position, pathDestinationTarget); if (null == path) { targetmode = TargetMode.SoftTarget; } else { pathTarget = path[0]; pathDestinationTarget = softTarget; } } } // if hard target moves out of range, go back to soft else if (dist > hardDetectRange) { targetmode = TargetMode.SoftTarget; softTarget = hardTarget.transform.position; // set the soft target to the old pos targetIntensity = maxIntensity; hardTarget = null; path = null; } } // is the intensity great enough to follow? if so, set soft target else if (targetIntensity > minIntensity) { // there already is a soft target canSeeTarg = GAMESTATE.canSeeIgnoreCharacters(transform.position, softTarget); if (canSeeTarg == false) { // follow path if we cant see where the sound came from // if we dont yet have a path, get one, or if this is a new soft target, generate a new path targetmode = TargetMode.FollowPath; if (path == null || (pathDestinationTarget != softTarget)) { path = GAMESTATE.findPath(transform.position, pathDestinationTarget); // there is no path if (null == path) { targetmode = TargetMode.SoftTarget; } else { pathTarget = path[0]; pathDestinationTarget = softTarget; } } } else { // otherwise just go towards it targetmode = TargetMode.SoftTarget; path = null; } } else { targetmode = TargetMode.NoTarget; softTarget = transform.position; targetIntensity = 0; path = null; } //print(Vector3.Magnitude(character.rigidbod.velocity) + " " + Time.time); } // handle behavior based off of the target mode switch (targetmode) { case (TargetMode.NoTarget): { character.State = Character_BS.AnimState.Idle; break; } case (TargetMode.SoftTarget): { is_moving = true; character.SetFacing(softTarget); // face the soft target VECTOR character.State = Character_BS.AnimState.Walk; Vector2 dir = new Vector2(softTarget.x, softTarget.y); dir -= new Vector2(transform.position.x, transform.position.y); dir.Normalize(); character.rigidbod.velocity = dir * character.walkSpeed; break; } case (TargetMode.HardTarget): { is_moving = true; character.SetFacing(hardTarget); // face the target game object character.State = Character_BS.AnimState.Run; Vector2 dir = hardTarget.transform.position - transform.position; float dist = dir.magnitude; dir.Normalize(); character.rigidbod.velocity = dir * character.runSpeed; if (dist < meleeDist) { // makes melee attack if (character.meleeWeapon.canAttack(is_moving) == true) { GAMESTATE.MakeAttack(gameObject, dir, character.meleeWeapon); } } break; } case (TargetMode.FollowPath): { // If we can see the next pathTarget, also just choose it (instead of walking too far the wrong way) float dist = Vector2.Distance(transform.position, pathTarget.transform.position); int i = path.IndexOf(pathTarget); is_moving = true; if (i + 1 < path.Count) { bool skipNode = GAMESTATE.canSeeIgnoreCharacters(transform.position, path[i + 1].transform.position); if (dist <= minPathNodeDist || skipNode == true) { // get the next path target pathTarget = path[i + 1]; //print("going to next node " + Time.time); } } // if too close to last path else if (dist <= minPathNodeDist) { targetIntensity = 0; is_moving = false; } if (is_moving == true) { Vector2 pathvector = pathTarget.transform.position; character.SetFacing(pathvector); // face the soft target VECTOR character.State = Character_BS.AnimState.Walk; Vector2 dir = pathvector; dir -= new Vector2(transform.position.x, transform.position.y); dir.Normalize(); character.rigidbod.velocity = Vector2.Lerp(character.rigidbod.velocity, dir * character.walkSpeed, 0.5f); } break; } default: { break; } } }
// returns the vector in gamespace that corresponds to this map node public Vector3 mapNodeToVector(MapNodeBS node) { Vector3 result = new Vector3(node.transform.position.x, node.transform.position.y, 10); return(result); }
// finds path between two locations, in squares public List <MapNodeBS> findPath(Vector3 start, Vector3 end) { MapNodeBS startNode = VectorToMapNode(start); MapNodeBS endNode = VectorToMapNode(end); Queue <List <MapNodeBS> > pathsQueue = new Queue <List <MapNodeBS> >(); // queue of paths to process List <MapNodeBS> path = new List <MapNodeBS>(); path.Add(startNode); pathsQueue.Enqueue(path); List <List <MapNodeBS> > successPaths = new List <List <MapNodeBS> >(); int numPaths = 0; int i = 0; // iteratively go through all paths while ((i < maxIter) && (numPaths < maxPaths)) { i++; if (pathsQueue.Count > 0) { path = pathsQueue.Dequeue(); } else { // just break out of while and let it continue processing what we have break; } MapNodeBS nd = path[path.Count - 1]; // does the path contain the destination? if (nd == endNode) { successPaths.Add(path); numPaths += 1; } if (nd != null && nd.adjacentNodes != null) { foreach (MapNodeBS adj in nd.adjacentNodes) { // is this node already in our path? if so, dont use it if (path.Contains(adj) == false) { List <MapNodeBS> newPath = new List <MapNodeBS>(); foreach (MapNodeBS mp in path) { newPath.Add(mp); } newPath.Add(adj); pathsQueue.Enqueue(newPath); // enqueue new path } } } } // how many good paths did we get? look through and return one if (numPaths > 0) { float totalLength = 0; float minLength = Mathf.Infinity; List <MapNodeBS> bestPath = null; MapNodeBS prevP = null; //Dictionary<List<MapNodeBS>, float> pathLengths = new Dictionary<List<MapNodeBS>, float>(); foreach (List <MapNodeBS> l in successPaths) { totalLength = 0; prevP = null; foreach (MapNodeBS p in l) { if (prevP != null) { //Debug.DrawLine(mapNodeToVector(p), mapNodeToVector(prevP), Color.blue, 2000f); totalLength += Vector3.Distance(mapNodeToVector(p), mapNodeToVector(prevP)); } prevP = p; } if (totalLength < minLength) { bestPath = l; minLength = totalLength; } //print(totalLength); //pathLengths[l] = totalLength; } // TODO: Instead select randomly from a few good paths // DRAW BEST PATH prevP = null; foreach (MapNodeBS p in bestPath) { if (prevP != null) { Debug.DrawLine(mapNodeToVector(p), mapNodeToVector(prevP), Color.yellow, 10f); totalLength += Vector3.Distance(mapNodeToVector(p), mapNodeToVector(prevP)); } prevP = p; } return(bestPath); } else { return(null); } }
public void addAdjacentNode(MapNodeBS node) { adjacentNodes.Add(node); }