public virtual void GoTo(EnumDirections d) { MazeSection next = null; if (this.CurrentLocation != null) { next = this.CurrentLocation.Get(d); if (next != null && next.Allowed) { this.NextLocation = next; if (d == EnumDirections.West || d == EnumDirections.East) this.FacingDirection = d; this.animation.Start(d, Constants.DEFAULT_BLOCK_WIDTH); } } }
public Block(MyGame g, MazeSection section) : base(g, @"Sprites\section.png", new Rectangle(0, 0, Constants.DEFAULT_BLOCK_WIDTH, Constants.DEFAULT_BLOCK_WIDTH)) { this.Section = section; }
public static Maze GetDefaultFor(ContentManager cm) { Int32 width, height; String blueprint = Path.Combine(Environment.CurrentDirectory, cm.RootDirectory, "maze_blueprint.txt"); String[] lines = File.ReadAllLines(blueprint); Dictionary<Char, MazeSection> linkedSections = new Dictionary<char, MazeSection>(); if (lines != null && lines.Length > 0) { height = lines.Length; width = lines[0].Length; MazeSection[,] sections = new MazeSection[height,width]; for (int y = 0; y < height; y++) { String line = lines[y]; MazeSection lastW = null; for (int x = 0; x < line.Length; x++) { Char c = line[x]; MazeSection s = new MazeSection(x, y); s.W = lastW; s.Checkpoint = c == 'R'; s.HasCookie = c == '-'; s.Allowed = (c == '-' || c == '_' || char.IsDigit(c)); //Redefinindo o 'oeste' o último leste if (lastW != null) { lastW.E = s; } //Redefinindo o 'sul' do último norte e avançando o norte para o elemento ao lado if (y > 0) { s.N = sections[y - 1, x]; s.N.S = s; } lastW = s; sections[y,x] = s; //Estamos lidando com uma linked section ? if (char.IsDigit(c)) { if (linkedSections.ContainsKey(c)) { MazeSection linkedS = linkedSections[c]; if (s.E == null) { s.E = linkedS; linkedS.W = s; } else if (linkedS.W == null) { s.W = linkedS; linkedS.E = s; } else if (linkedS.N == null) { s.N = linkedS; linkedS.S = s; } else if (linkedS.S == null) { s.S = linkedS; linkedS.N = s; } } else { linkedSections.Add(c,s); } } } } return new Maze(sections); } else throw new FileLoadException("Formato de arquivo de bluprint inválido"); }
protected void ChaseSection(MazeSection destination) { //Localizações dos elementos var currLocation = this.Ghost.CurrentLocation; var currEndLocation = destination; var prevLocation = this.Ghost.PreviousLocation; //Essa é a seção inicial, PathFindingNode currNode = new PathFindingNode(); currNode.h = 0; currNode.g = 0; currNode.parent = null; currNode.location = currLocation; List<PathFindingNode> closedSet = new List<PathFindingNode>(); List<PathFindingNode> openSet = new List<PathFindingNode>(); closedSet.Add(currNode); do { //Percorrendo as opções de caminho que temos List<MazeSection> opcoes = new List<MazeSection> { currLocation.W, currLocation.N, currLocation.E, currLocation.S }; foreach (var o in opcoes) { if (o != null) { //A seção precisa estar ativa e não ser a seção anteriormente visitada if (o.Allowed && (prevLocation == null || o.ID != prevLocation.ID)) { //Seção não deve existir na lista de seções fechadas if (!closedSet.Any(x => x.location.ID == o.ID)) { //...nem na lista de seções abertas if (!openSet.Any(x => x.location.ID == o.ID)) { PathFindingNode node = new PathFindingNode(); node.location = o; node.parent = currNode; node.h = this.Heuristics(node.location, currEndLocation); //heuristica manhattan //Ok, esse nó participará do teste openSet.Add(node); } } } } } if (openSet.Count == 0) { break; } //Procuramos o melhor nó localizado (custo) var minNode = openSet[0]; foreach (var m in openSet) { if (m.h < minNode.h) { minNode = m; } } currNode = minNode; currLocation = currNode.location; //Removendo da lista de nós abertos para pesquisa e incluíndo na lista de nós proibidos openSet.Remove(minNode); closedSet.Add(currNode); } while (currNode.location.ID != currEndLocation.ID); if (currNode.location.ID == currEndLocation.ID) { ///* LinkedList<PathFindingNode> path = new LinkedList<PathFindingNode>(); PathFindingNode lastPathNode = currNode; MazeSection nextSectionToMove = null; MazeSection mySection = this.Ghost.CurrentLocation; while (lastPathNode != null) { path.AddFirst(lastPathNode); lastPathNode = lastPathNode.parent; } nextSectionToMove = path.Count > 1 ? path.First.Next.Value.location : path.First.Value.location; if (nextSectionToMove.ID == mySection.N.ID) { this.nextDirection = EnumDirections.North; } else if (nextSectionToMove == mySection.S) { this.nextDirection = EnumDirections.South; } else if (nextSectionToMove == mySection.E) { this.nextDirection = EnumDirections.East; } else if (nextSectionToMove == mySection.W) { this.nextDirection = EnumDirections.West; } this.Ghost.GoTo(this.nextDirection); //*/ } }
private Int32 Heuristics(MazeSection start, MazeSection end) { if (start != null && end != null) { return (Int32)Math.Abs((start.ID.X - end.ID.X) + (start.ID.Y - end.ID.Y)); } else { return 99999; } }
private void FindNextDestination() { //Modo perseguição sempre avança em busca do alvo if (this.Ghost.State == Ghost.States.Chase) { this.scatterNextDestination = null; ChaseSection(this.Target.CurrentLocation); } else if (this.Ghost.State == Components.Ghost.States.Scatter) { if (this.scatterNextDestination == null) { this.scatterNextDestination = this.Ghost.Region.Item1; } else if (this.scatterNextDestination.ID == this.Ghost.CurrentLocation.ID) { this.scatterNextDestination = (this.scatterNextDestination.ID == this.Ghost.Region.Item1.ID) ? this.Ghost.Region.Item2 : this.Ghost.Region.Item1; } this.ChaseSection(this.scatterNextDestination); } }
private void RegisterNewGhost(String ghostType, Puckman p, MazeSection r1, MazeSection r2) { Ghost g1 = new Ghost(this.Game as MyGame, ghostType); g1.Region = Tuple.Create(r1, r2); g1.CurrentLocation = this.Maze.GetGhostLairSection(); g1.Initialize(); this.Components.Add(g1); GhostAIController iaCtrl1 = new GhostAIController(this.Game as MyGame, g1, p); iaCtrl1.Initialize(); this.Components.Add(iaCtrl1); }