我对此代码存在问题,如果有人会介意帮助我,我会变得更聪明。我真的不知道为什么我会收到错误,所以如果有人能告诉我它为什么会发生这种错误会很棒。
我收到以下错误:
指数超出范围。它可能不是负面的,必须小于人群的大小。
编辑: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;
答案 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);