它可能不是负面的,必须小于人群的大小

时间:2015-01-22 20:31:08

标签: c# .net xna

我对此代码存在问题,如果有人会介意帮助我,我会变得更聪明。我真的不知道为什么我会收到错误,所以如果有人能告诉我它为什么会发生这种错误会很棒。

我收到以下错误:

  

指数超出范围。它可能不是负面的,必须小于人群的大小。

编辑:sry忘记标记问题所在: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 个答案:

答案 0 :(得分:0)

我认为其中一部分是Peirre-Luc Pineault所说的。你正在经历一个循环,删除元素,然后STILL通过循环。这有时会导致越界(非常可能)。我真的很惊讶它让你这样做。

如果您查看更新(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个不同的列表中删除元素。您将浏览&#34; shot_pos&#34;和&#34; meteor_pos&#34;,但删除&#34; shot_pos&#34;中的元素(基于索引位置); (没关系),&#34; meteor_pos&#34; (没关系),然后&#34; shot_speed&#34; +&#34; meteor_speed&#34; (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;

正如我之前所说的那样,这个问题是你无法确认这些数据是否正常排列。因此,i为2时的shot_speed意味着在i为2时的shot_pos。

更复杂的解决方案是组合结构或类中的数据。

结构的MSDN教程实际上是不错的:[这里] https://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx

但我总是喜欢[这个网站最多] http://www.dotnetperls.com/struct

答案 1 :(得分: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);