2015-01-22 2 views
-4

У меня проблема с этим кодом, и я был бы рад, если кто-нибудь не возражал бы мне помочь. Я не знаю, почему я получил ошибку, поэтому было бы здорово, если бы кто-нибудь мог сказать мне, почему это происходит.Это не может быть отрицательным и должно быть меньше, чем размер толпы

я получаю следующее сообщение об ошибке:

Index was out of range. It may not be negative and must be smaller than the size of the crowd.

Редактировать: СРЮ забыл отметить, что это проблема: P

Вот код:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Audio; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.GamerServices; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Media; 

namespace WindowsGame2 
{ 
    /// <summary> 
    /// This is the main type for your game 
    /// </summary> 
    public class Game1 : Microsoft.Xna.Framework.Game 
    { 
     GraphicsDeviceManager graphics; 
     SpriteBatch spriteBatch; 

     private Rectangle Bounds = Rectangle.Empty; 
     SpriteFont font; 

     Texture2D gfx_shot; 
     Texture2D gfx; 
     Texture2D gfx_acc; 
     Texture2D gfx_meteor; 

     Vector2 position; 
     Vector2 ship_speed = new Vector2(); 
     List<Vector2> shot_pos = new List<Vector2>(); 
     List<Vector2> shot_speed = new List<Vector2>();   
     List<Vector2> meteor_pos = new List<Vector2>(); 
     List<Vector2> meteor_speed = new List<Vector2>(); 

     Random myRnd = new Random(); 

     float angle = 0; 
     const float ship_acc = 0.1f; 
     const float ship_max_speed = 4; 
     const int shot_delay = 200; 
     int shot_time; 
     int score = 0; 

     double shot_rad = 3.25, 
      meteor_rad = 33; 

     bool accelerate; 

     public Game1() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 
     } 

     /// <summary> 
     /// Allows the game to perform any initialization it needs to before starting to run. 
     /// This is where it can query for any required services and load any non-graphic 
     /// related content. Calling base.Initialize will enumerate through any components 
     /// and initialize them as well. 
     /// </summary> 
     protected override void Initialize() 
     { 
      // TODO: Add your initialization logic here 

      base.Initialize(); 
     } 

     /// <summary> 
     /// LoadContent will be called once per game and is the place to load 
     /// all of your content. 
     /// </summary> 
     protected override void LoadContent() 
     { 
      // Create a new SpriteBatch, which can be used to draw textures. 
      spriteBatch = new SpriteBatch(GraphicsDevice); 

      // Här läggs SpriteBatch till som gör att man kan använda dem som en texture 
      gfx = Content.Load<Texture2D>("ship"); 
      gfx_acc = Content.Load<Texture2D>("ship_acc"); 
      gfx_shot = Content.Load<Texture2D>("shot"); 
      font = Content.Load<SpriteFont>("myFont"); 

      // Positionen av rymdskäpet 
      position = new Vector2(200, 200); 

      gfx_meteor = Content.Load<Texture2D>("meteor"); 
      int i; 
      for (i = 0; i < 10; i++) 
      { 
       meteor_pos.Add(new Vector2(myRnd.Next(800), myRnd.Next(600))); 
       double tmp_angle = (myRnd.Next(1000) * Math.PI * 2)/1000.0; 
       double tmp_speed = 0.5 + 3.0 * (myRnd.Next(1000)/1000.0); 
       meteor_speed.Add(new Vector2((float)(tmp_speed * Math.Cos(tmp_angle)), 
        (float)(tmp_speed * Math.Sin(tmp_angle)))); 
      } 

      if (i < 10) 
      { 
       meteor_pos.Add(new Vector2(myRnd.Next(800), myRnd.Next(600))); 
       double tmp_angle = (myRnd.Next(1000) * Math.PI * 2)/1000.0; 
       double tmp_speed = 0.5 + 3.0 * (myRnd.Next(1000)/1000.0); 
       meteor_speed.Add(new Vector2((float)(tmp_speed * Math.Cos(tmp_angle)), 
        (float)(tmp_speed * Math.Sin(tmp_angle)))); 
       i++; 
      } 
     } 

     /// <summary> 
     /// UnloadContent will be called once per game and is the place to unload 
     /// all content. 
     /// </summary> 
     protected override void UnloadContent() 
     { 
      // TODO: Unload any non ContentManager content here 
     } 

     /// <summary> 
     /// Allows the game to run logic such as updating the world, 
     /// checking for collisions, gathering input, and playing audio. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     protected override void Update(GameTime gameTime) 
     { 
      // Allows the game to exit 
      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
       this.Exit(); 

      // Denna funktion känner av snap trycken för att köra rymdskäppet 
      KeyboardState ks = Keyboard.GetState(); 

      if (ks.IsKeyDown(Keys.Left)) 
      { 
       angle -= 0.05f; 
      } 
      if (ks.IsKeyDown(Keys.Right)) 
      { 
       angle += 0.05f; 
      } 
      if (ks.IsKeyDown(Keys.Up)) 
      { 
       accelerate = true; 

       ship_speed.X += ship_acc * (float)Math.Cos(angle); 
       ship_speed.Y += ship_acc * (float)Math.Sin(angle); 
       if (ship_speed.Length() > ship_max_speed) 
       { 
        ship_speed.Normalize(); 
        ship_speed *= ship_max_speed; 
       } 
      } 
      else 
      { 
       accelerate = false; 
      } 

      position += ship_speed; 

      // Detta kollar om rymdskäpet åker utanför skärmen. Om den gör det ska den komma in på andra sidan 
      if (position.X < -80) 
      { 
       position.X = graphics.GraphicsDevice.Viewport.Width + 80; 
      } 
      if (position.X > graphics.GraphicsDevice.Viewport.Width + 80) 
      { 
       position.X = -80; 
      } 
      if (position.Y < -60) 
      { 
       position.Y = graphics.GraphicsDevice.Viewport.Height + 60; 
      } 
      if (position.Y > graphics.GraphicsDevice.Viewport.Height + 60) 
      { 
       position.Y = -60; 
      } 

      // Här kollar den alla viktiga detaljer om hur skoten funkar 
      shot_time -= gameTime.ElapsedGameTime.Milliseconds; 
      if (shot_time < 0) 
      { 
       shot_time = 0; 
      } 

      if (ks.IsKeyDown(Keys.Space) && shot_time == 0) 
      { 
       shot_time = shot_delay; 
       shot_pos.Add(new Vector2(position.X, position.Y)); 
       shot_speed.Add(new Vector2(5 * (float)Math.Cos(angle), 5 * (float)Math.Sin(angle))); 
      } 

      for (int i = 0; i < shot_pos.Count; i++) 
      { 
       shot_pos[i] += shot_speed[i]; 
       if (shot_pos[i].X < -100 || shot_pos[i].X > graphics.GraphicsDevice.Viewport.Width + 100 
        || shot_pos[i].Y < -100 || shot_pos[i].Y > graphics.GraphicsDevice.Viewport.Height + 100) 
       { 
        shot_pos.RemoveAt(i); 
        shot_speed.RemoveAt(i); 
        continue; 
       } 

      } 

      // Här updaterar vi Metorernas location 
      for (int i = 0; i < meteor_pos.Count; i++) 
      { 
       meteor_pos[i] += meteor_speed[i]; 
       Vector2 v = meteor_pos[i]; 
       //Utanför skärmen? 
       if (v.X < -80) 
        v.X = graphics.GraphicsDevice.Viewport.Width + 80; 
       if (v.X > graphics.GraphicsDevice.Viewport.Width + 80) 
        v.X = -80; 
       if (v.Y < -60) 
        v.Y = graphics.GraphicsDevice.Viewport.Height + 60; 
       if (v.Y > graphics.GraphicsDevice.Viewport.Height + 60) 
        v.Y = -60; 
       if (v.X == position.X) 
        break; 

       //Uppdatera i listan 
       meteor_pos[i] = v; 
      } 

      for (int a = 0; a < meteor_pos.Count; a++) 
      { 

       double ship_xplus = position.X + meteor_pos[a].X; 
       double ship_xminus = position.X - meteor_pos[a].X; 
       double ship_yplus = position.Y + meteor_pos[a].Y; 
       double ship_yminus = position.Y - meteor_pos[a].Y; 


       if ((ship_xplus * ship_xplus + ship_yplus * ship_yplus) < (shot_rad + meteor_rad) * (shot_rad + meteor_rad)) 
       { 

       } 
       else if ((ship_xminus * ship_xminus + ship_yminus * ship_yminus) < (shot_rad + meteor_rad) * (shot_rad + meteor_rad)) 
       { 

       } 
      } 

      // Test 
      //Om det finns skott o meteoriter så kolla kollision 
      if (shot_pos.Count > 0 && meteor_pos.Count > 0) 
      { 
       for (int i = 0; i < shot_pos.Count; i++) 
       { 
        for (int a = 0; a < meteor_pos.Count; a++) 
        { 
         float xdiff = shot_pos[i].X - meteor_pos[a].X; 
         float ydiff = shot_pos[i].Y - meteor_pos[a].Y; 


         if ((xdiff * xdiff + ydiff * ydiff) < (shot_rad + meteor_rad) * (shot_rad + meteor_rad)) 
         { 
          shot_pos.RemoveAt(i); 
          shot_speed.RemoveAt(i); 
          meteor_pos.RemoveAt(a); 
          meteor_speed.RemoveAt(a); 
          continue; 
         } 
        } 
       } 
      } 

      base.Update(gameTime); 
     } 


     /// <summary> 
     /// This is called when the game should draw itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     protected override void Draw(GameTime gameTime) 
     { 
      GraphicsDevice.Clear(Color.CornflowerBlue); 
      // Starta renderingen av rymdskäppet 
      spriteBatch.Begin(); 

       // Om rymdskäppet accelerar så kör denna renderings processen och lägg till eld bakom rymdskäpet 
       if (accelerate) 
       { 
        spriteBatch.Draw(gfx_acc, position, null, Color.White, angle + (float)Math.PI/2, new Vector2(gfx.Width/2, gfx.Height/2), 1.0f, SpriteEffects.None, 0); 
       } 
       // Om rymdskäppet svänger kör denna renderings processen 
       spriteBatch.Draw(gfx, position, null, Color.White, angle + (float)Math.PI/2, new Vector2(gfx.Width/2, gfx.Height/2), 1.0f, SpriteEffects.None, 0); 

       // Här skriver den hur många skot du har skjutit på skärmen 
       for (int i = 0; i < shot_pos.Count; i++) 
       { 
        spriteBatch.Draw(gfx_shot, shot_pos[i], null, Color.White, 0, new Vector2(gfx_shot.Width/2, gfx_shot.Height/2), 1.0f, SpriteEffects.None, 0); 

       } 

       // Här gör vi en font som skriver hur många skot det är just nu på skärmen 
       spriteBatch.DrawString(font, "Shots: " + shot_pos.Count, new Vector2(10, 10), Color.White); 
       spriteBatch.DrawString(font, "Score: " + score, new Vector2(10, 35), Color.White); 

       // Här gör vi så metorerna renderas utt på skärmen 
       for (int i = 0; i < meteor_pos.Count; i++) 
       { 
        spriteBatch.Draw(gfx_meteor, meteor_pos[i], null, Color.White, 0, 
         new Vector2(gfx_meteor.Width/2, gfx_meteor.Height/2), 1.0f, SpriteEffects.None, 0); 
       } 
      // Avsluta renderingen av rymdskäppet 

       //if (Collision()) 
        //spriteBatch.DrawString(font, "You were killed", new Vector2(10, 10), Color.White); 

      spriteBatch.End(); 
     } 
    } 
} 

Ошибка это: float xdiff = shot_pos [i] .X - meteor_pos [a] .X;

+2

* Путь * слишком много кода.Пожалуйста, по крайней мере, укажите, на какой строке. – BradleyDotNET

+3

Где-то в этом огромном блоге грязного кода вы удаляете элементы из коллекции, которую вы итерируете, испортили свои индексы. –

+2

1) [Перерыв, когда исключение, которое вы видите, выбрано] (https://msdn.microsoft.com/en-us/library/d14azbfh.aspx). 2) Отладка. – dbc

ответ

0

Я думаю, что часть этого - то, что говорит Пирр-Люк Пинео. Вы проходите цикл, удаляя элементы, а затем STILL, проходя через цикл. Это иногда приводит к запредельным (очень вероятно). Я действительно удивлен, что это позволяет вам это сделать.

Если вы посмотрите на обновление (Gametime GameTime) функции вы будете в конечном итоге увидеть ...

if (shot_pos.Count > 0 && meteor_pos.Count > 0) 
{ 
    for (int i = 0; i < shot_pos.Count; i++) 
    { 
     for (int a = 0; a < meteor_pos.Count; a++) 
     { 
      float xdiff = shot_pos[i].X - meteor_pos[a].X; 
      float ydiff = shot_pos[i].Y - meteor_pos[a].Y; 


      if ((xdiff * xdiff + ydiff * ydiff) < (shot_rad + meteor_rad) * (shot_rad + meteor_rad)) 
      { 
       shot_pos.RemoveAt(i); 
       shot_speed.RemoveAt(i); 
       meteor_pos.RemoveAt(a); 
       meteor_speed.RemoveAt(a); 
       continue; 
      } 
     } 
    } 
} 

Я думаю, что главная проблема здесь: Здесь вы велосипеде через 2 списка, но с использованием тех цикла переменные для удаления элементов из 4 разных списков. Вы просматриваете список «shot_pos» и «meteor_pos», но удаляете элементы (на основе позиции индекса) из «shot_pos» (это нормально), «meteor_pos» (это нормально), а затем «shot_speed» + «meteor_speed »(whoooaaa nelly!).

Хотя вы можете быть довольно уверенно, что shot_pos и meteor_pos находятся в радиусе действия, вы не знаете, действительно ли shot_speed и meteor_speed находятся в радиусе действия, потому что вы не проверяете его.

Решение: Я думаю, что без изменения исходного кода слишком много, просто проверка правильности диапазона в порядке.

Значение:

shot_pos.RemoveAt(i); 
if (i< shot_speed.Count){ 
    shot_speed.RemoveAt(i); 
} 
meteor_pos.RemoveAt(a); 
if (a<meteor_speed.Count){ 
    meteor_speed.RemoveAt(a); 
} 
continue; 

Этот вопрос, как я клоню прежде, является то, что вы не имеете никакого способа подтверждения того, что линии передачи данных до этого. Так что shot_speed в i of 2 предназначен для shot_pos at i of 2.

Более сложным решением будет объединение данных, которые объединяются в структуру или класс.

MSDN от учебник для структур на самом деле приличная: [здесь] https://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx

Но я всегда как [этот сайт самый] http://www.dotnetperls.com/struct

0

Я использую немного другой подход, когда мне нужно удалить пуль или метеоров. При столкновении я устанавливаю флаг в true. И тогда я удаляю их все вместе.

В основном коде псевдо

for each m in meteors 
    for each b in bullets 
     if m.collide(b) {b.removeIt = true;} 
    next 
next 

, а затем

bullet.removeAll(function(c) c.removeIt);