gpt4 book ai didi

c# - XNA 游戏在非常奇怪的情况下无法启动

转载 作者:太空宇宙 更新时间:2023-11-03 21:48:27 25 4
gpt4 key购买 nike

首先要让开,抱歉,如果我遗漏了一些(非常)明显的东西,我对此还是有点陌生​​。

无论如何,我一直在 XNA 中研究小行星克隆,出于某种原因,如果我点击 Start Debugging 按钮,它偶尔会无法启动。我将问题跟踪到我的 AsteroidsManager 类,它需要一个初始小行星的整数来生成最小和最大速度和旋转速度,以及小行星和粒子的两个纹理列表。现在奇怪了:

temp = new AsteroidManager(1, 20, 50, 1, 2, asteroids, particles, true); //With this constructor, the game always starts fine...

但是如果我增加初始小行星的数量:

temp = new AsteroidManager(10, 20, 50, 1, 2, asteroids, particles, true); //This seems to start about 1/3 times in the Visual Studio debugger, but if I launch it without debugging or from the bin folder, it works fine.

最后,如果我将小行星设置为超过 20 个,它永远不会在调试器中启动,如果我尝试从文件夹启动它,该进程会出现在任务管理器中,但什么也没有发生。或者它只是在启动时崩溃。老实说,我不知道是什么原因造成的,如果需要,我很乐意提供任何代码,但这是我认为相关的内容:

完整的 AsteroidManager:

public class AsteroidManager
{
#region Declarations

public List<GameObject> Asteroids { get; set; }
public bool RegenerateAsteroids { get; set; }

public readonly int InitialAsteroids;
public readonly float MinVelocity;
public readonly float MaxVelocity;
public readonly float MinRotationalVelocity; //in degrees
public readonly float MaxRotationalVelocity; //in degrees
public readonly List<Texture2D> Textures;
public readonly List<Texture2D> ExplosionParticleTextures;

List<ParticleEmitter> emitters;
Random rnd;

const int MINPARTICLES = 50;
const int MAXPARTICLES = 200;
const int PARTICLEFTL = 40;

#endregion

public AsteroidManager(
int initialAsteroids,
float minVel,
float maxVel,
float minRotVel,
float maxRotVel,
List<Texture2D> textures,
List<Texture2D> explosionParticleTextures,
bool regenAsteroids)
{
rnd = new Random();

InitialAsteroids = initialAsteroids;
MinVelocity = minVel;
MaxVelocity = maxVel;
MinRotationalVelocity = minRotVel;
MaxRotationalVelocity = maxRotVel;
Textures = textures;
ExplosionParticleTextures = explosionParticleTextures;
RegenerateAsteroids = regenAsteroids;

Asteroids = new List<GameObject>();
emitters = new List<ParticleEmitter>();

for (int i = 0; i < InitialAsteroids; i++)
addAsteroid();
}

public void Update(GameTime gameTime)
{
for (int i = 0; i < Asteroids.Count; i++)
Asteroids[i].Update(gameTime);

for (int i = 0; i < emitters.Count; i++)
emitters[i].Update(gameTime);

if (Asteroids.Count < InitialAsteroids && RegenerateAsteroids)
addAsteroid();
}

public void Draw(SpriteBatch spriteBatch)
{
for (int i = 0; i < Asteroids.Count; i++)
Asteroids[i].Draw(spriteBatch);

for (int i = 0; i < emitters.Count; i++)
emitters[i].Draw(spriteBatch);
}

public void DestroyAsteroid(GameObject asteroid)
{
int x = rnd.Next(MINPARTICLES, MAXPARTICLES);
List<Color> colors = new List<Color>();
colors.Add(Color.White);

emitters.Add(new ParticleEmitter( //TODO: Test
x,
asteroid.WorldCenter,
ExplosionParticleTextures,
colors,
PARTICLEFTL,
true,
1,
x,
1f,
0.3f,
0f,
180f));

Asteroids.Remove(asteroid);
}

protected void addAsteroid()
{
GameObject tempAsteroid;
bool isOverlap = false;

do //Do-While to ensure that the asteroid gets generated at least once
{
Texture2D text = Textures.PickRandom<Texture2D>();

float rot = MathHelper.ToRadians((float)rnd.NextDouble(0f, 359f));
float rotVel = MathHelper.ToRadians((float)rnd.NextDouble(MinRotationalVelocity, MaxRotationalVelocity));

int colRadius = (((text.Width / 2) + (text.Height / 2)) / 2); //Get the mean of text's height & width

Vector2 vel = Vector2.Multiply( //calculate a random velocity
rot.RotationToVectorFloat(),
(float)rnd.NextDouble(MinVelocity, MaxVelocity));

Vector2 worldPos = new Vector2(
rnd.Next(Camera.WorldRectangle.X, Camera.WorldRectangle.Width),
rnd.Next(Camera.WorldRectangle.Y, Camera.WorldRectangle.Height));

tempAsteroid = new GameObject( //init a temporary asteroid to check for overlaps
text, worldPos, vel, Color.White, false, rot, rotVel, 1f, 0f, colRadius);

foreach (GameObject asteroid in Asteroids)
{
if (tempAsteroid.BoundingBox.Intersects(asteroid.BoundingBox))
{
isOverlap = true;
break;
}
}

} while (isOverlap); //if overlapping, loop

Asteroids.Add(tempAsteroid); //add the temp asteroid
}
}

完整游戏对象:

public class GameObject
{
#region Declarations

public Texture2D Texture { get; set; }
public Vector2 Origin { get; set; }
public Color TintColor { get; set; }
public float Rotation { get; set; } //radians
public float RotationalVelocity { get; set; }
public float Scale { get; set; }
public float Depth { get; set; }
public bool Active { get; set; }
public SpriteEffects Effects { get; set; }

public Vector2 WorldLocation { get; set; }
public Vector2 Velocity { get; set; }

public int CollisionRadius { get; set; } //Radius for bounding circle collision
public int BoundingXPadding { get; set; }
public int BoundingYPadding { get; set; } //Padding for bounding box collision

public int TotalFrames
{
get //simple get
{ return totalFrames; }
set //check if given totalFrames is in possible range
{
if (value <= (Rows * Columns))
totalFrames = value;
else
throw new ArgumentOutOfRangeException();
}
} //Used in spritesheet animation
private int totalFrames;

public int CurrentFrame
{
get { return currentFrame; }
set
{
currentFrame = (int)MathHelper.Clamp(value, 0, totalFrames);
}
}
private int currentFrame;

public int Rows { get; set; }
public int Columns { get; set; }
public bool Animating { get; set; }

public float RotationDegrees
{
get { return MathHelper.ToDegrees(Rotation); }
set { Rotation = MathHelper.ToRadians(value); }
}
public float RotationVelocityDegrees
{
get { return MathHelper.ToDegrees(RotationalVelocity); }
set { RotationalVelocity = MathHelper.ToRadians(value); }
}

public const float VELOCITYSCALAR = 1.0f / 60.0f; //Default to 60fps standard movement

#endregion

#region Properties

public int GetWidth { get { return Texture.Width / Columns; } } //Width of a frame
public int GetHeight { get { return Texture.Height / Rows; } } //Height of a frame
public int GetRow { get { return (int)((float)CurrentFrame / (float)Columns); } } //Current row
public int GetColumn { get { return CurrentFrame % Columns; } } //Current column

public Vector2 SpriteCenter
{ get { return new Vector2(GetWidth / 2, GetHeight / 2); } } //Get this Sprite's center

public Rectangle WorldRectangle //get rectangle in world coords with width of sprite
{
get
{
return new Rectangle(
(int)WorldLocation.X,
(int)WorldLocation.Y,
GetWidth,
GetHeight);
}
}

public Rectangle BoundingBox //get bounding box for use in collision detection
{
get
{
return new Rectangle( //Get bounding box with respect to padding values
(int)WorldLocation.X + BoundingXPadding,
(int)WorldLocation.Y + BoundingYPadding,
GetWidth - (BoundingXPadding * 2),
GetHeight - (BoundingYPadding * 2));
}
}

public Vector2 ScreenLocation
{ get { return Camera.GetLocalCoords(WorldLocation); } } //get screen coordinates

public Rectangle ScreenRectangle
{ get { return Camera.GetLocalCoords(WorldRectangle); } } //get screen rectangle

public Vector2 WorldCenter
{
get { return WorldLocation + SpriteCenter; }
set { WorldLocation = value - SpriteCenter; }
} //gets/sets the center of the sprite in world coords

public Vector2 ScreenCenter
{ get { return Camera.GetLocalCoords(WorldLocation + SpriteCenter); } } //returns the center in screen coords

#endregion

public GameObject( //main constructor, /w added optional parameters and call to SpriteBase init
Texture2D texture,
Vector2 worldLocation,
Vector2 velocity,
Color tintColor,
bool animating = false,
float rotation = 0f, //default to no rotation
float rotationalVelocity = 0f,
float scale = 1f, //default to 1:1 scale
float depth = 0f, //default to 0 layerDepth
int collisionRadius = 0, //collision radius used in bounding circle collision, default to 0 or no bounding circle
int xPadding = 0, //amount of x padding, used in bounding box collision, default to 0, or no bounding box
int yPadding = 0, //amount of y padding, used in bounding box collision, default to 0, or no bounding box
SpriteEffects effects = SpriteEffects.None,
int totalFrames = 0,
int rows = 1,
int columns = 1)

{
if (texture == null) { throw new NullReferenceException("Null texture reference."); }
Texture = texture; //assign parameters
WorldLocation = worldLocation;
TintColor = tintColor;
Rotation = rotation;
RotationalVelocity = rotationalVelocity;
Scale = scale;
Depth = depth;
Effects = effects;
Velocity = velocity;
Animating = animating;
Active = true;

BoundingXPadding = xPadding; BoundingYPadding = yPadding; CollisionRadius = collisionRadius; //assign collision data
Rows = rows; Columns = columns; this.TotalFrames = totalFrames; //assign animation data

Origin = SpriteCenter; //assign origin to the center of a frame
}

#region Methods

public virtual void Update(GameTime gameTime)
{
if (Active) //if object is active
{
WorldLocation += Velocity * (1f / 60f);
Rotation += RotationalVelocity; //Rotate according to the velocity
//Move by Velocity times a roughly 60FPS scalar

if (TotalFrames > 1 && Animating)
{
CurrentFrame++;
if (CurrentFrame >= TotalFrames)
CurrentFrame = 0; //Loop animation
}

if (Camera.IsObjectInWorld(this.WorldRectangle) == false)
{
if (Camera.LOOPWORLD) //if world is looping and the object is out of bounds
{
Vector2 temp = WorldCenter; //temporary Vector2 used for updated position

//X-Axis Component
if (WorldCenter.X > Camera.WorldRectangle.Width)
temp.X = Camera.WorldRectangle.X - (GetWidth / 2); //If X is out of bounds to the right, move X to the left side
if (WorldCenter.X < Camera.WorldRectangle.X)
temp.X = Camera.WorldRectangle.Width + (GetWidth / 2); //If X is out of bound to the left, move X to the right side

//Y-Axis Component
if (WorldCenter.Y > Camera.WorldRectangle.Height)
temp.Y = Camera.WorldRectangle.Y - (GetHeight / 2); //If Y is out of bounds to the bottom, move Y to the top
if (WorldCenter.Y < Camera.WorldRectangle.Y)
temp.Y = Camera.WorldRectangle.Height + (GetHeight / 2); //If Y is out of bounds to the top, move Y to the bottom

WorldCenter = temp; //Assign updated position
}

if (Camera.LOOPWORLD == false)
{
Active = false; //if the object is outside the world but the LOOPWORLD constant is false, set inactive
}
}
}
}

public virtual void Draw(SpriteBatch spriteBatch)
{
if (Active)
{
if (TotalFrames > 1 && Camera.IsObjectVisible(WorldRectangle)) //if multi-frame animation & object is visible
{
Rectangle sourceRectangle = new Rectangle(GetWidth * GetColumn,
GetHeight * GetRow, GetWidth, GetHeight); //get source rectangle to use

spriteBatch.Draw(
Texture,
ScreenCenter,
sourceRectangle, //use generated source rectangle
TintColor,
Rotation,
Origin,
Scale,
Effects,
Depth);
}
else //if single frame sprite
{
if (Camera.IsObjectVisible(WorldRectangle)) //check if sprite is visible to camera
{
spriteBatch.Draw(
Texture,
ScreenCenter, //center of the sprite in local coords
null, //full sprite
TintColor,
Rotation,
Origin,
Scale,
Effects, //spriteeffects
Depth); //layerdepth
}
}
}
}

public bool IsBoxColliding(Rectangle obj) //bounding box collision test
{
return BoundingBox.Intersects(obj);
}

public bool IsBoxColliding(GameObject obj) //overload of previous which takes a GameObject instead of a rectangle
{
if (BoundingBox.Intersects(obj.BoundingBox))
return true;
else
return false;
}

public bool IsCircleColliding(Vector2 objCenter, float objRadius)
{
if (Vector2.Distance(WorldCenter, objCenter) <
(CollisionRadius + objRadius)) //if the distance between centers is greater than the sum
return true; //of the radii, collision has occurred
else
return false; //if not, return false
}

public bool IsCircleColliding(GameObject obj) //overload of previous which takes a GameObject instead of loose values
{
if (Vector2.Distance(this.WorldCenter, obj.WorldCenter) <
(CollisionRadius + obj.CollisionRadius))
return true;
else
return false;
}

public void RotateTo(Vector2 point) //rotates the GameObject to a point
{
Rotation = (float)Math.Atan2(point.Y, point.X);
}

protected Vector2 rotationToVector()
{
return Rotation.RotationToVectorFloat();
} //local version of extension method

#endregion
}

游戏 1 平局:

    protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(); //BEGIN SPRITE DRAW

fpsDisplay.Draw(spriteBatch);
temp.Draw(spriteBatch);

spriteBatch.End(); //END SPRITE DRAW
base.Draw(gameTime);
}

游戏 1 更新:

    protected override void Update(GameTime gameTime)
{
InputHandler.Update(); //update InputHandler

if (InputHandler.IsKeyDown(Keys.Left))
Camera.Position += new Vector2(-3f, 0f);
if (InputHandler.IsKeyDown(Keys.Right))
Camera.Position += new Vector2(3f, 0f);
if (InputHandler.IsKeyDown(Keys.Up))
Camera.Position += new Vector2(0f, -3f);
if (InputHandler.IsKeyDown(Keys.Down))
Camera.Position += new Vector2(0f, 3f);

fpsDisplay.Value = (int)Math.Round(1 / gameTime.ElapsedGameTime.TotalSeconds, 0);
//calculate framerate to the nearest int

temp.Update(gameTime);

base.Update(gameTime);
}

最佳答案

我猜你的重叠代码永远不会找到放置小行星的位置。它进入了一个永不退出的近乎无限(如果空间被适当覆盖,则可能是无限)的循环。您可以使用给定多次尝试的计数器,它只是“放弃”。或者你可以增加它们可以生成的游戏区域的最大大小,或者减小它们的大小;这将减少这种无限循环发生的可能性,但不会因为有足够的小行星而使它不可能发生。

int attempts = 0;

do //Do-While to ensure that the asteroid gets generated at least once
{
attempts++;
...
foreach (GameObject asteroid in Asteroids)
{
if (tempAsteroid.BoundingBox.Intersects(asteroid.BoundingBox))
{
isOverlap = true;
break;
}
}

} while (isOverlap && attempts < 20); //if overlapping, loop, give up after 20 tries

if (attempts == 20)
{
//log it! Or fix it, or something!
}

即使您通过增加游戏大小或减小小行星大小来“修复”此问题,我仍然建议您让它运行最大次数以避免无限循环。

关于c# - XNA 游戏在非常奇怪的情况下无法启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15692809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com