Monogame 程序不断随机丢弃大量帧
Monogame program keeps randomly dropping a ton of frames
我正在 Monogame 中处理 3D 图形,我正在创建 100 个矩形实例 class 我制作了:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace BlockMonglerFixed1
{
public class Rectangle
{
/// <summary>
/// Width of the rectangle
/// </summary>
public int Width { get; set; }
/// <summary>
/// Height of the rectangle
/// </summary>
public int Height { get; set; }
/// <summary>
/// Length of the rectangle
/// </summary>
public int Length { get; set; }
/// <summary>
/// Position of the rectangle
/// </summary>
public Vector3 Position { get; set; }
/// <summary>
/// Rotation vector3 of the rectangle. X = pitch. Y = yaw. Z = roll
/// </summary>
public Vector3 Rotation { get; set; }
/// <summary>
/// GraphicsDevice used to draw the rectangle
/// </summary>
public GraphicsDevice GraphicsDevice { get; set; }
/// <summary>
/// BasicEffect used to to draw the rectangle
/// </summary>
public BasicEffect Effect { get; set; }
/// <summary>
/// Color of the rectangle. Not used if a texture is being used
/// </summary>
public Color Color { get; set; }
/// <summary>
/// Texture of the rectangle. Not used if a color is being used.
/// </summary>
public Texture3D Texture { get; set; }
/// <summary>
/// Determines if the rectangle should move based on its rotation
/// </summary>
public bool MoveBasedOnRotation { get; set; }
int _vertexLength;
VertexBuffer _buffer;
/// <summary>
/// Cube constructor. Generates a new rectangle
/// </summary>
/// <param name="width">Width of rectangle</param>
/// <param name="height">Height of rectangle</param>
/// <param name="length">Length of rectangle</param>
/// <param name="position">Position of the rectangle></param>
/// <param name="rotation">Rotation of the rectangle. This value rotates the rectangle</param>
/// <param name="graphicsDevice">GraphicsDevice used to draw the rectangle</param>
/// <param name="effect">Effect of rectangle</param>
/// <param name="color">Color of rectangle</param>
/// <param name="moveBasedOnRotation">Determines if the rectangle should move based on its rotation</param>
public Rectangle(int width, int height, int length, Vector3 position,
Vector3 rotation, GraphicsDevice graphicsDevice, BasicEffect effect, Color color, bool moveBasedOnRotation)
{
//Dimensions of the rectangle
Width = width;
Height = height;
Length = length * 2;
//Position setup
Position = position;
//Rotation setup
Rotation = rotation;
MoveBasedOnRotation = moveBasedOnRotation;
//Effect setup
Effect = effect;
//Color setup
Color = color;
//Graphics device setup.
GraphicsDevice = graphicsDevice;
//Cube setup
VertexPositionColor[] vertexPositionColors =
{
//Face 1
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
//Face 2
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
//Side 1
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
//Side 2
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
//Bottom
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
//Top
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
};
//Length setup
_vertexLength = vertexPositionColors.Length;
//Buffer setup
_buffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), _vertexLength,
BufferUsage.WriteOnly);
//Set data of the buffer to the vertexList
_buffer.SetData(vertexPositionColors);
}
public Rectangle(int width, int height, int length, Matrix worldMatrix, Matrix projectionMatrix,
Matrix viewMatrix,
GraphicsDevice graphicsDevice, BasicEffect effect, Texture3D texture)
{
throw new NotImplementedException();
}
/// <summary>
/// Sees if the rectangle collides with another object
/// </summary>
/// <param name="otherRectangle">Rectangle to detect collision with</param>
public bool IsColliding(Rectangle otherRectangle)
{
//Get the minimum values of our position
float minX = Position.X - Width;
float minY = Position.Y - Height;
float minZ = Position.Z - Length / 2f;
//Get the maximum values of our position
float maxX = Position.X + Width;
float maxY = Position.Y + Height;
float maxZ = Position.Z + Length / 2f;
//Get the minimum values of the other rectangle's position
float otherMinX = otherRectangle.Position.X - otherRectangle.Width;
float otherMinY = otherRectangle.Position.Y - otherRectangle.Height;
float otherMinZ = otherRectangle.Position.Z - otherRectangle.Length / 2f;
//Get the maximum values of the other rectangle's positions
float otherMaxX = otherRectangle.Position.X + otherRectangle.Width;
float otherMaxY = otherRectangle.Position.Y + otherRectangle.Height;
float otherMaxZ = otherRectangle.Position.Z + otherRectangle.Length / 2f;
//We can calculate if one rectangle is in another by seeing if one of our sides is inside another rectangle
return minX <= otherMaxX && maxX >= otherMinX &&
minY <= otherMaxY && maxY >= otherMinY &&
minZ <= otherMaxZ && maxZ >= otherMinZ;
}
/// <summary>
/// Draws the rectangle to the screen
/// </summary>
public void Draw()
{
//Hold the current position
Vector3 tempPosition = Position;
//Create a new matrix with the position and rotation
Matrix effectWorldMatrix = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up) *
Matrix.CreateTranslation(-new Vector3(0, 0, -Length / 2f)) *
Matrix.CreateRotationX(Rotation.X) *
Matrix.CreateRotationY(Rotation.Y) *
Matrix.CreateRotationZ(Rotation.Z) *
Matrix.CreateTranslation(Position);
//If MoveBasedOnRotation is true, set the translation of our new matrix to the previous translation
//if (!MoveBasedOnRotation) effectWorldMatrix.Translation = tempPosition;
//Set the effect to our respective matrices;
Effect.World = effectWorldMatrix;
Effect.View = Camera.ViewMatrix;
Effect.Projection = Camera.ProjectionMatrix;
//Apply our vertex buffer to the graphics device
GraphicsDevice.SetVertexBuffer(_buffer);
//Disable culling so that we can see our object on both sides
RasterizerState rasterizerState = new RasterizerState {CullMode = CullMode.None};
GraphicsDevice.RasterizerState = rasterizerState;
foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
{
//Apply the pass
pass.Apply();
//Use the graphics device to draw the triangle
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, _vertexLength);
}
}
}
}
我遇到的问题是程序在 60 fps 下运行流畅,但随后 fps 随机下降到接近 0。丢帧的频率似乎与矩形的数量有关。
这里是每帧调用的Draw代码(blocks是矩形数组)
/// <summary>
/// Draw logic. Activates every frame.
/// </summary>
/// <param name="gameTime">How long the program has been running for</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Chocolate);
foreach (var a in blocks)
a.Draw();
fps++;
if (gameTime.TotalGameTime.Milliseconds % 1000 == 0 && enableFpsCounter)
{
Console.WriteLine(fps);
fps = 0;
}
base.Draw(gameTime);
}
仅当有大量矩形(~25 个矩形)时才会出现此问题
这是展示此问题的 gif:
https://gyazo.com/ec41cacd6c89a41c330e151108590050
感谢您的阅读,我很感激能得到的任何帮助。
我设法解决了这个问题,方法是在构造函数内部启动 RasterizerState 而不是 Draw 方法:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace BlockMonglerFixed1
{
public class Rectangle
{
/// <summary>
/// Width of the rectangle
/// </summary>
public int Width { get; set; }
/// <summary>
/// Height of the rectangle
/// </summary>
public int Height { get; set; }
/// <summary>
/// Length of the rectangle
/// </summary>
public int Length { get; set; }
/// <summary>
/// Position of the rectangle
/// </summary>
public Vector3 Position { get; set; }
/// <summary>
/// Rotation vector3 of the rectangle. X = pitch. Y = yaw. Z = roll
/// </summary>
public Vector3 Rotation { get; set; }
/// <summary>
/// GraphicsDevice used to draw the rectangle
/// </summary>
public GraphicsDevice GraphicsDevice { get; set; }
/// <summary>
/// BasicEffect used to to draw the rectangle
/// </summary>
public BasicEffect Effect { get; set; }
/// <summary>
/// Color of the rectangle. Not used if a texture is being used
/// </summary>
public Color Color { get; set; }
/// <summary>
/// Texture of the rectangle. Not used if a color is being used.
/// </summary>
public Texture3D Texture { get; set; }
/// <summary>
/// Determines if the rectangle should move based on its rotation
/// </summary>
public bool MoveBasedOnRotation { get; set; }
int _vertexLength;
VertexBuffer _buffer;
RasterizerState _rasterizerState;
/// <summary>
/// Cube constructor. Generates a new rectangle
/// </summary>
/// <param name="width">Width of rectangle</param>
/// <param name="height">Height of rectangle</param>
/// <param name="length">Length of rectangle</param>
/// <param name="position">Position of the rectangle></param>
/// <param name="rotation">Rotation of the rectangle. This value rotates the rectangle</param>
/// <param name="graphicsDevice">GraphicsDevice used to draw the rectangle</param>
/// <param name="effect">Effect of rectangle</param>
/// <param name="color">Color of rectangle</param>
/// <param name="moveBasedOnRotation">Determines if the rectangle should move based on its rotation</param>
public Rectangle(int width, int height, int length, Vector3 position,
Vector3 rotation, GraphicsDevice graphicsDevice, BasicEffect effect, Color color, bool moveBasedOnRotation)
{
//Dimensions of the rectangle
Width = width;
Height = height;
Length = length * 2;
//Position setup
Position = position;
//Rotation setup
Rotation = rotation;
MoveBasedOnRotation = moveBasedOnRotation;
//Effect setup
Effect = effect;
//Color setup
Color = color;
//Graphics device setup.
GraphicsDevice = graphicsDevice;
//Cube setup
VertexPositionColor[] vertexPositionColors =
{
//Face 1
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
//Face 2
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
//Side 1
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
//Side 2
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
//Bottom
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
//Top
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
};
//Length setup
_vertexLength = vertexPositionColors.Length;
//Buffer setup
_buffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), _vertexLength,
BufferUsage.WriteOnly);
//Set data of the buffer to the vertexList
_buffer.SetData(vertexPositionColors);
_rasterizerState = new RasterizerState {CullMode = CullMode.None};
GraphicsDevice.RasterizerState = _rasterizerState;
}
public Rectangle(int width, int height, int length, Matrix worldMatrix, Matrix projectionMatrix,
Matrix viewMatrix,
GraphicsDevice graphicsDevice, BasicEffect effect, Texture3D texture)
{
throw new NotImplementedException();
}
/// <summary>
/// Sees if the rectangle collides with another object
/// </summary>
/// <param name="otherRectangle">Rectangle to detect collision with</param>
public bool IsColliding(Rectangle otherRectangle)
{
//Get the minimum values of our position
float minX = Position.X - Width;
float minY = Position.Y - Height;
float minZ = Position.Z - Length / 2f;
//Get the maximum values of our position
float maxX = Position.X + Width;
float maxY = Position.Y + Height;
float maxZ = Position.Z + Length / 2f;
//Get the minimum values of the other rectangle's position
float otherMinX = otherRectangle.Position.X - otherRectangle.Width;
float otherMinY = otherRectangle.Position.Y - otherRectangle.Height;
float otherMinZ = otherRectangle.Position.Z - otherRectangle.Length / 2f;
//Get the maximum values of the other rectangle's positions
float otherMaxX = otherRectangle.Position.X + otherRectangle.Width;
float otherMaxY = otherRectangle.Position.Y + otherRectangle.Height;
float otherMaxZ = otherRectangle.Position.Z + otherRectangle.Length / 2f;
//We can calculate if one rectangle is in another by seeing if one of our sides is inside another rectangle
return minX <= otherMaxX && maxX >= otherMinX &&
minY <= otherMaxY && maxY >= otherMinY &&
minZ <= otherMaxZ && maxZ >= otherMinZ;
}
/// <summary>
/// Draws the triangle to the screen
/// </summary>
public void Draw()
{
//Hold the current position
Vector3 tempPosition = Position;
//Create a new matrix with the position and rotation
Matrix effectWorldMatrix = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up) *
Matrix.CreateTranslation(-new Vector3(0, 0, -Length / 2f)) *
Matrix.CreateRotationX(Rotation.X) *
Matrix.CreateRotationY(Rotation.Y) *
Matrix.CreateRotationZ(Rotation.Z) *
Matrix.CreateTranslation(Position);
//If MoveBasedOnRotation is true, set the translation of our new matrix to the previous translation
//if (!MoveBasedOnRotation) effectWorldMatrix.Translation = tempPosition;
//Set the effect to our respective matrices;
Effect.World = effectWorldMatrix;
Effect.View = Camera.ViewMatrix;
Effect.Projection = Camera.ProjectionMatrix;
//Apply our vertex buffer to the graphics device
GraphicsDevice.SetVertexBuffer(_buffer);
foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
{
//Apply the pass
pass.Apply();
//Use the graphics device to draw the triangle
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, _vertexLength);
}
}
}
}
我正在 Monogame 中处理 3D 图形,我正在创建 100 个矩形实例 class 我制作了:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace BlockMonglerFixed1
{
public class Rectangle
{
/// <summary>
/// Width of the rectangle
/// </summary>
public int Width { get; set; }
/// <summary>
/// Height of the rectangle
/// </summary>
public int Height { get; set; }
/// <summary>
/// Length of the rectangle
/// </summary>
public int Length { get; set; }
/// <summary>
/// Position of the rectangle
/// </summary>
public Vector3 Position { get; set; }
/// <summary>
/// Rotation vector3 of the rectangle. X = pitch. Y = yaw. Z = roll
/// </summary>
public Vector3 Rotation { get; set; }
/// <summary>
/// GraphicsDevice used to draw the rectangle
/// </summary>
public GraphicsDevice GraphicsDevice { get; set; }
/// <summary>
/// BasicEffect used to to draw the rectangle
/// </summary>
public BasicEffect Effect { get; set; }
/// <summary>
/// Color of the rectangle. Not used if a texture is being used
/// </summary>
public Color Color { get; set; }
/// <summary>
/// Texture of the rectangle. Not used if a color is being used.
/// </summary>
public Texture3D Texture { get; set; }
/// <summary>
/// Determines if the rectangle should move based on its rotation
/// </summary>
public bool MoveBasedOnRotation { get; set; }
int _vertexLength;
VertexBuffer _buffer;
/// <summary>
/// Cube constructor. Generates a new rectangle
/// </summary>
/// <param name="width">Width of rectangle</param>
/// <param name="height">Height of rectangle</param>
/// <param name="length">Length of rectangle</param>
/// <param name="position">Position of the rectangle></param>
/// <param name="rotation">Rotation of the rectangle. This value rotates the rectangle</param>
/// <param name="graphicsDevice">GraphicsDevice used to draw the rectangle</param>
/// <param name="effect">Effect of rectangle</param>
/// <param name="color">Color of rectangle</param>
/// <param name="moveBasedOnRotation">Determines if the rectangle should move based on its rotation</param>
public Rectangle(int width, int height, int length, Vector3 position,
Vector3 rotation, GraphicsDevice graphicsDevice, BasicEffect effect, Color color, bool moveBasedOnRotation)
{
//Dimensions of the rectangle
Width = width;
Height = height;
Length = length * 2;
//Position setup
Position = position;
//Rotation setup
Rotation = rotation;
MoveBasedOnRotation = moveBasedOnRotation;
//Effect setup
Effect = effect;
//Color setup
Color = color;
//Graphics device setup.
GraphicsDevice = graphicsDevice;
//Cube setup
VertexPositionColor[] vertexPositionColors =
{
//Face 1
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
//Face 2
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
//Side 1
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
//Side 2
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
//Bottom
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
//Top
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
};
//Length setup
_vertexLength = vertexPositionColors.Length;
//Buffer setup
_buffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), _vertexLength,
BufferUsage.WriteOnly);
//Set data of the buffer to the vertexList
_buffer.SetData(vertexPositionColors);
}
public Rectangle(int width, int height, int length, Matrix worldMatrix, Matrix projectionMatrix,
Matrix viewMatrix,
GraphicsDevice graphicsDevice, BasicEffect effect, Texture3D texture)
{
throw new NotImplementedException();
}
/// <summary>
/// Sees if the rectangle collides with another object
/// </summary>
/// <param name="otherRectangle">Rectangle to detect collision with</param>
public bool IsColliding(Rectangle otherRectangle)
{
//Get the minimum values of our position
float minX = Position.X - Width;
float minY = Position.Y - Height;
float minZ = Position.Z - Length / 2f;
//Get the maximum values of our position
float maxX = Position.X + Width;
float maxY = Position.Y + Height;
float maxZ = Position.Z + Length / 2f;
//Get the minimum values of the other rectangle's position
float otherMinX = otherRectangle.Position.X - otherRectangle.Width;
float otherMinY = otherRectangle.Position.Y - otherRectangle.Height;
float otherMinZ = otherRectangle.Position.Z - otherRectangle.Length / 2f;
//Get the maximum values of the other rectangle's positions
float otherMaxX = otherRectangle.Position.X + otherRectangle.Width;
float otherMaxY = otherRectangle.Position.Y + otherRectangle.Height;
float otherMaxZ = otherRectangle.Position.Z + otherRectangle.Length / 2f;
//We can calculate if one rectangle is in another by seeing if one of our sides is inside another rectangle
return minX <= otherMaxX && maxX >= otherMinX &&
minY <= otherMaxY && maxY >= otherMinY &&
minZ <= otherMaxZ && maxZ >= otherMinZ;
}
/// <summary>
/// Draws the rectangle to the screen
/// </summary>
public void Draw()
{
//Hold the current position
Vector3 tempPosition = Position;
//Create a new matrix with the position and rotation
Matrix effectWorldMatrix = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up) *
Matrix.CreateTranslation(-new Vector3(0, 0, -Length / 2f)) *
Matrix.CreateRotationX(Rotation.X) *
Matrix.CreateRotationY(Rotation.Y) *
Matrix.CreateRotationZ(Rotation.Z) *
Matrix.CreateTranslation(Position);
//If MoveBasedOnRotation is true, set the translation of our new matrix to the previous translation
//if (!MoveBasedOnRotation) effectWorldMatrix.Translation = tempPosition;
//Set the effect to our respective matrices;
Effect.World = effectWorldMatrix;
Effect.View = Camera.ViewMatrix;
Effect.Projection = Camera.ProjectionMatrix;
//Apply our vertex buffer to the graphics device
GraphicsDevice.SetVertexBuffer(_buffer);
//Disable culling so that we can see our object on both sides
RasterizerState rasterizerState = new RasterizerState {CullMode = CullMode.None};
GraphicsDevice.RasterizerState = rasterizerState;
foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
{
//Apply the pass
pass.Apply();
//Use the graphics device to draw the triangle
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, _vertexLength);
}
}
}
}
我遇到的问题是程序在 60 fps 下运行流畅,但随后 fps 随机下降到接近 0。丢帧的频率似乎与矩形的数量有关。
这里是每帧调用的Draw代码(blocks是矩形数组)
/// <summary>
/// Draw logic. Activates every frame.
/// </summary>
/// <param name="gameTime">How long the program has been running for</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Chocolate);
foreach (var a in blocks)
a.Draw();
fps++;
if (gameTime.TotalGameTime.Milliseconds % 1000 == 0 && enableFpsCounter)
{
Console.WriteLine(fps);
fps = 0;
}
base.Draw(gameTime);
}
仅当有大量矩形(~25 个矩形)时才会出现此问题
这是展示此问题的 gif: https://gyazo.com/ec41cacd6c89a41c330e151108590050
感谢您的阅读,我很感激能得到的任何帮助。
我设法解决了这个问题,方法是在构造函数内部启动 RasterizerState 而不是 Draw 方法:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace BlockMonglerFixed1
{
public class Rectangle
{
/// <summary>
/// Width of the rectangle
/// </summary>
public int Width { get; set; }
/// <summary>
/// Height of the rectangle
/// </summary>
public int Height { get; set; }
/// <summary>
/// Length of the rectangle
/// </summary>
public int Length { get; set; }
/// <summary>
/// Position of the rectangle
/// </summary>
public Vector3 Position { get; set; }
/// <summary>
/// Rotation vector3 of the rectangle. X = pitch. Y = yaw. Z = roll
/// </summary>
public Vector3 Rotation { get; set; }
/// <summary>
/// GraphicsDevice used to draw the rectangle
/// </summary>
public GraphicsDevice GraphicsDevice { get; set; }
/// <summary>
/// BasicEffect used to to draw the rectangle
/// </summary>
public BasicEffect Effect { get; set; }
/// <summary>
/// Color of the rectangle. Not used if a texture is being used
/// </summary>
public Color Color { get; set; }
/// <summary>
/// Texture of the rectangle. Not used if a color is being used.
/// </summary>
public Texture3D Texture { get; set; }
/// <summary>
/// Determines if the rectangle should move based on its rotation
/// </summary>
public bool MoveBasedOnRotation { get; set; }
int _vertexLength;
VertexBuffer _buffer;
RasterizerState _rasterizerState;
/// <summary>
/// Cube constructor. Generates a new rectangle
/// </summary>
/// <param name="width">Width of rectangle</param>
/// <param name="height">Height of rectangle</param>
/// <param name="length">Length of rectangle</param>
/// <param name="position">Position of the rectangle></param>
/// <param name="rotation">Rotation of the rectangle. This value rotates the rectangle</param>
/// <param name="graphicsDevice">GraphicsDevice used to draw the rectangle</param>
/// <param name="effect">Effect of rectangle</param>
/// <param name="color">Color of rectangle</param>
/// <param name="moveBasedOnRotation">Determines if the rectangle should move based on its rotation</param>
public Rectangle(int width, int height, int length, Vector3 position,
Vector3 rotation, GraphicsDevice graphicsDevice, BasicEffect effect, Color color, bool moveBasedOnRotation)
{
//Dimensions of the rectangle
Width = width;
Height = height;
Length = length * 2;
//Position setup
Position = position;
//Rotation setup
Rotation = rotation;
MoveBasedOnRotation = moveBasedOnRotation;
//Effect setup
Effect = effect;
//Color setup
Color = color;
//Graphics device setup.
GraphicsDevice = graphicsDevice;
//Cube setup
VertexPositionColor[] vertexPositionColors =
{
//Face 1
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
//Face 2
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
//Side 1
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
//Side 2
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
//Bottom
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, -Height, 0), Color),
//Top
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(-Width, Height, 0), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
new VertexPositionColor(new Vector3(-Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, -Length), Color),
new VertexPositionColor(new Vector3(Width, Height, 0), Color),
};
//Length setup
_vertexLength = vertexPositionColors.Length;
//Buffer setup
_buffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), _vertexLength,
BufferUsage.WriteOnly);
//Set data of the buffer to the vertexList
_buffer.SetData(vertexPositionColors);
_rasterizerState = new RasterizerState {CullMode = CullMode.None};
GraphicsDevice.RasterizerState = _rasterizerState;
}
public Rectangle(int width, int height, int length, Matrix worldMatrix, Matrix projectionMatrix,
Matrix viewMatrix,
GraphicsDevice graphicsDevice, BasicEffect effect, Texture3D texture)
{
throw new NotImplementedException();
}
/// <summary>
/// Sees if the rectangle collides with another object
/// </summary>
/// <param name="otherRectangle">Rectangle to detect collision with</param>
public bool IsColliding(Rectangle otherRectangle)
{
//Get the minimum values of our position
float minX = Position.X - Width;
float minY = Position.Y - Height;
float minZ = Position.Z - Length / 2f;
//Get the maximum values of our position
float maxX = Position.X + Width;
float maxY = Position.Y + Height;
float maxZ = Position.Z + Length / 2f;
//Get the minimum values of the other rectangle's position
float otherMinX = otherRectangle.Position.X - otherRectangle.Width;
float otherMinY = otherRectangle.Position.Y - otherRectangle.Height;
float otherMinZ = otherRectangle.Position.Z - otherRectangle.Length / 2f;
//Get the maximum values of the other rectangle's positions
float otherMaxX = otherRectangle.Position.X + otherRectangle.Width;
float otherMaxY = otherRectangle.Position.Y + otherRectangle.Height;
float otherMaxZ = otherRectangle.Position.Z + otherRectangle.Length / 2f;
//We can calculate if one rectangle is in another by seeing if one of our sides is inside another rectangle
return minX <= otherMaxX && maxX >= otherMinX &&
minY <= otherMaxY && maxY >= otherMinY &&
minZ <= otherMaxZ && maxZ >= otherMinZ;
}
/// <summary>
/// Draws the triangle to the screen
/// </summary>
public void Draw()
{
//Hold the current position
Vector3 tempPosition = Position;
//Create a new matrix with the position and rotation
Matrix effectWorldMatrix = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up) *
Matrix.CreateTranslation(-new Vector3(0, 0, -Length / 2f)) *
Matrix.CreateRotationX(Rotation.X) *
Matrix.CreateRotationY(Rotation.Y) *
Matrix.CreateRotationZ(Rotation.Z) *
Matrix.CreateTranslation(Position);
//If MoveBasedOnRotation is true, set the translation of our new matrix to the previous translation
//if (!MoveBasedOnRotation) effectWorldMatrix.Translation = tempPosition;
//Set the effect to our respective matrices;
Effect.World = effectWorldMatrix;
Effect.View = Camera.ViewMatrix;
Effect.Projection = Camera.ProjectionMatrix;
//Apply our vertex buffer to the graphics device
GraphicsDevice.SetVertexBuffer(_buffer);
foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
{
//Apply the pass
pass.Apply();
//Use the graphics device to draw the triangle
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, _vertexLength);
}
}
}
}