2013-10-13 57 views
5

我有一些XNA塔防的代碼。我已經設置了它,以便敵人(蟲子)從網格的某一邊沿着一條隨機路徑前進,直到它撞到房子(目的地)或者房子旁邊的一排。爲什麼我的隨機路徑代碼不工作?

我調試了這個項目,並且bug被繪製並開始在對角線(類型)路徑中移動。每次都是一樣的(不是隨機的)。我不是不知道我做錯了什麼。它也有時會在我指定的代碼中出現OutOfMemory異常。我不知道如果我解釋得很好,可以隨時提問。網格被森林所包圍,森林不屬於網格的一部分,所以這就是森林的含義。

public class Bug : Sprite 
{ 
    public float startHealth; 
    protected float currentHealth; 
    protected bool alive = true; 
    protected float speed = 0.5f; 
    protected int bountyGiven; 
    public int startplace; 
    public bool at_house; 
    public Queue<Vector2> path = new Queue<Vector2>(); 
    Random random = new Random(); 
    int x; 
    int y; 
    public int end_row; 
    public int end_column; 

    //Defines the space where the house is 
    Vector2 house1 = new Vector2(10, 13) * 91; 
    Vector2 house2 = new Vector2(10, 12) * 91; 
    Vector2 house3 = new Vector2(10, 11) * 91; 
    Vector2 house4 = new Vector2(10, 10) * 91; 
    Vector2 house5 = new Vector2(11, 13) * 91; 
    Vector2 house6 = new Vector2(11, 12) * 91; 
    Vector2 house7 = new Vector2(11, 11) * 91; 
    Vector2 house8 = new Vector2(11, 10) * 91; 
    Vector2 house9 = new Vector2(12, 13) * 91; 
    Vector2 house10 = new Vector2(12, 12) * 91; 
    Vector2 house11 = new Vector2(12, 11) * 91; 
    Vector2 house12 = new Vector2(12, 10) * 91; 

    public float CurrentHealth 
    { 
     get { return currentHealth; } 
     set { currentHealth = value; } 
    } 

    public bool IsDead 
    { 
     get { return currentHealth <= 0; } 
    } 

    public int BountyGiven 
    { 
     get { return bountyGiven; } 
    } 

    public float DistanceToDestination 
    { 
     get { return Vector2.Distance(position, path.Peek()); } 
    } 

    public Bug(Texture2D texture, Vector2 position, float health, 
     int bountyGiven, float speed) 
     : base(texture, position) 
    { 

     this.startHealth = health; 
     this.currentHealth = startHealth; 
     this.bountyGiven = bountyGiven; 
     this.speed = speed; 
     int startq = random.Next(1, 4); 
     set_start(ref startq); 
     //end_row and end_column detremine the row or column at which the bug turns toward the house. 
     end_row = random.Next(10, 13); 
     end_column = random.Next(10, 12); 
     set_path(ref startq); 
    } 

    public void set_start(ref int startq) 
    { 
     //here i am initializing the "0,0" point for the bug so it's 0,0 is't in the forest 
     //startx and starty should equal the number of tiles between the forest edge and the grass edge 
     //startx is the x co-ord in the start place and starty is the y co-ord in the start 
     int startx = 4; 
     int starty = 4; 
     //This generates a random number which determines the start for the bug 
     //Between 0 and 22 because that is the number of edge tiles on one side 
     int start = random.Next(0, 22); 
     //start determines what place on a side the buggie spawns at 
     //startq is a random int (1-4)(defined in constructor) which determnes which side the bug spawns at 

     if (startq == 1) 
     { 
      starty += 22; 
      startx += start; 
     } 

     if (startq == 2) 
     { 
      startx += 22; 
      starty += start; 
     } 

     if (startq == 3) 
     { 
      startx += start; 
     } 

     if (startq == 4) 
     { 
      starty += start; 
     } 
     x = startx; 
     y = starty; 
     path.Enqueue(new Vector2(startx, starty) * 91); 
    } 

    public bool check_for_path_end(ref int startq, ref bool at_house) 
    { 
     bool path_ends; 
     //checks if the bug has reached the house and if so signals using at_house 
     if (path.Peek() == house1 || path.Peek() == house2 || path.Peek() == house3 || path.Peek() == house4 
      || path.Peek() == house5 || path.Peek() == house6 || path.Peek() == house7 || path.Peek() == house8 
      || path.Peek() == house9 || path.Peek() == house10 || path.Peek() == house11 || path.Peek() == house12) 
     { 
      at_house = true; 
      return true; 
     } 
     //Should i add at_house = true to the else ifs? 
     else if (startq == 1 || startq == 3 && path.Peek().Y == end_row) 
     { 
      path.Enqueue(new Vector2(11, end_row) * 91); 
      return true; 
     } 

     else if (startq == 2 || startq == 4 && path.Peek().X == end_column) 
     { 
      path.Enqueue(new Vector2(end_column, 11) * 91); 
      path_ends = true; 
     } 

     else 
     { 
      path_ends = false; 
     } 
     return path_ends; 
    } 

    public void set_path(ref int startq) 
    { 
     bool path_ends; 
     bool legal = true; 
     int X = x; 
     int Y = y; 
     do 
     { 
      //determines which way the bug turns at it's different waypoints 1 = left, 2 = right, 3 = forward 
      int turn = random.Next(1, 3); 
      do 
      { 
       if (startq == 1) 
       { 
        switch (turn) 
        { 
         case 1: 
          x += 1; 
          break; 
         case 2: 
          x -= 1; 
          break; 
         case 3: 
          y += 1; 
          break; 
        } 
       } 

       else if (startq == 2) 
        switch (turn) 
        { 
         case 1: 
          y -= 1; 
          break; 
         case 2: 
          y += 1; 
          break; 
         case 3: 
          x -= 1; 
          break; 
        } 

       else if (startq == 3) 
       { 
        switch (turn) 
        { 
         case 1: 
          x -= 1; 
          break; 
         case 2: 
          x += 1; 
          break; 
         case 3: 
          y += 1; 
          break; 
        } 
       } 

       else if (startq == 4) 
       { 
        switch (turn) 
        { 
         case 1: 
          y += 1; 
          break; 
         case 2: 
          y -= 1; 
          break; 
         case 3: 
          x += 1; 
          break; 
        } 
       } 

       if (y > 3 && y < 28 && x > 3 && x < 28) 
       { 
        //sets up a backup in case the bug goes off track 
        X = x; 
        Y = y; 

這裏就是例外是:

     //Right here is where it gives the out of memory exception 
         path.Enqueue(new Vector2(x, y) * 91); 
         legal = true; 
        } 

        else 
        { 
         //restores x and y to backups X and Y 
         x = X; 
         y = Y; 
         //adds to turn and repeats without randomizing turn or adding waypoints 
         turn += 1; 
         legal = false; 
        } 
       } while (legal == false); 
       path_ends = check_for_path_end(ref startq, ref at_house); 
      } while (path_ends == false); 
     } 

     public bool check_corners() 
     { 
      bool start_is_corner; 
      if (x == 2 && y == 24 || x == 24 && y == 24 || x == 24 && y == 2 || x == 2 && y == 2) 
      { 
       start_is_corner = true; 
       int X = x; 
       int Y = y; 
       if (x == 4 && y == 27) 
       { 
        bool z = true; 
        for (int i = 0; i < 13; ++i) 
        { 
         if (z == true) 
         { 
          Y -= 1; 
          path.Enqueue(new Vector2(X, Y) * 91); 
          z = false; 
         } 
         if (z == false) 
         { 
          X += 1; 
          path.Enqueue(new Vector2(X, Y) * 91); 
          z = true; 
         } 
        } 
       } 
       if (x == 27 && y == 27) 
       { 
        bool z = true; 
        for (int i = 0; i < 13; ++i) 
        { 
         if (z == true) 
         { 
          Y -= 1; 
          path.Enqueue(new Vector2(X, Y) * 91); 
          z = false; 
         } 
         if (z == false) 
         { 
          X -= 1; 
          path.Enqueue(new Vector2(X, Y) * 91); 
          z = true; 
         } 
        } 
       } 
       if (x == 27 && y == 4) 
       { 
        bool z = true; 
        for (int i = 0; i < 13; ++i) 
        { 
         if (z == true) 
         { 
          Y += 1; 
          path.Enqueue(new Vector2(X, Y) * 91); 
          z = false; 
         } 
         if (z == false) 
         { 
          X -= 1; 
          path.Enqueue(new Vector2(X, Y) * 91); 
          z = true; 
         } 
        } 
       } 
       if (x == 4 && y == 4) 
       { 
        bool z = true; 
        for (int i = 0; i < 13; ++i) 
        { 
         if (z == true) 
         { 
          Y += 1; 
          path.Enqueue(new Vector2(X, Y) * 91); 
          z = false; 
         } 
         if (z == false) 
         { 
          X += 1; 
          path.Enqueue(new Vector2(X, Y) * 91); 
          z = true; 
         } 
        } 
       } 
      } 
      else 
      { 
       start_is_corner = false; 
      } 
      return start_is_corner; 
     } 

     public override void Update(GameTime gameTime) 
     { 
      base.Update(gameTime); 
      if (path.Count > 0) 
      { 
       if (DistanceToDestination < speed) 
       { 
        position = path.Dequeue(); 
       } 

       else 
       { 
        Vector2 direction = path.Peek() - position; 
        direction.Normalize(); 

        velocity = Vector2.Multiply(direction, speed); 

        position += velocity; 
       } 
      } 
      else 
       alive = false; 

      if (currentHealth <= 0) 
       alive = false; 
     } 

     public override void Draw(SpriteBatch spriteBatch) 
     { 
      if (alive) 
      { 
       float healthPercentage = (float)currentHealth/(float)startHealth; 

       base.Draw(spriteBatch); 
      } 
     } 
    } 
} 

回答

7

此方法是您的構造函數。這是那裏的問題來自:

public Bug(Texture2D texture, Vector2 position, float health, int bountyGiven, float speed) 
    : base(texture, position) 
{ 

    this.startHealth = health; 
    this.currentHealth = startHealth; 
    this.bountyGiven = bountyGiven; 
    this.speed = speed; 
    int startq = random.Next(1, 4); 
    set_start(ref startq); 
    //end_row and end_column detremine the row or column at which the bug turns toward the house. 
    end_row = random.Next(10, 13); 
    end_column = random.Next(10, 12); 
    set_path(ref startq); // <<<<<<<<<<< HERE! 
} 

你在做什麼在這裏,是你在初始化預先錯誤的路徑。並且您將整個路徑存儲在Queue中。最終,隊列變得如此之大,以致內存不足。

解決方案很簡單。取而代之的初始化Bug,知道每一步他會朝着家出生的,做一個Bug啓動地方和,在每次更新,決定了下一步朝家將是。不要排隊任何東西。

你的錯誤是你在構造函數中做屬於你的Update方法的東西。 擺脫你的set_path方法。一個錯誤並不足以從一開始就知道回家的路。這就是拖延你的遊戲。使用Update方法計算下一步移動,而不是將其從隊列中拉出:您也不需要該隊列。

這就像你在下棋,甚至在你知道你的對手的第一步行動之前,你正在計算你的腦海中的整個遊戲。在比賽開始之前,你的鼻子會流血。

+0

謝謝!我現在意識到這很愚蠢 – Detinator10

2

我真的沒有時間,現在困擾了整個事情,但我可以告訴你什麼是你的內存不足的錯誤發生 - 因爲終止條件沒有抓住它,它正在狂野地建造一條無限的道路。

+0

所以我不停止路徑生成?我明天會檢查一下。我還有很多東西需要學習......(我是一名初學者程序員) – Detinator10

+0

@ user2770939在某些情況下(但並非所有情況下),您都不會停止路徑生成。這就是爲什麼它並不總是打擊。我認爲可能性非常高,有些情況可能通過終止條件泄露。 –

+0

好的,我將在明天再次登錄我的電腦時進行檢查。我的敵人每次都採用完全相同的路徑可能會導致內存不足異常嗎?順便說一句,我是user2770939我改了我的名字 – Detinator10