在XNA中切换全屏会导致丢失设备类错误
我正在尝试编写我的第一个XNA游戏,我想包括ALT+ENTER功能,以便在全屏模式和窗口模式之间切换。我的游戏现在非常基本,没什么特别的。我可以让它在我的LoadContent函数中以窗口(默认)或全屏(通过调用ToggleFullScreen)运行,一切都很好 然而,当我在更新函数中使用完全相同的代码调用ToggleFullScreen时,我的游戏失败了。如果我启动windowed并切换到全屏,它似乎会冻结,只显示一帧,不接受键盘输入(我必须按CTRL+ALT+DEL)。如果启动全屏并切换到windowed,则DrawIndexedPrimitive上会出现错误,并显示消息“当前顶点声明未包含当前顶点着色器所需的所有元素。缺少Normal0。”(这不是真的;我的顶点缓冲区是vertex ExpositionNormalTexture,包含数据,GraphicsDevice状态为Normal). 这两个问题似乎都指向某种程度上与该设备的连接丢失,但我不明白为什么。我在网上找到的每个资源都说切换全屏就像调用ToggleFullScreen函数一样简单,没有提到重置设备或缓冲区。有什么想法吗 编辑:这里有一些代码,没有涉及其他内容:在XNA中切换全屏会导致丢失设备类错误,xna,fullscreen,xna-4.0,Xna,Fullscreen,Xna 4.0,我正在尝试编写我的第一个XNA游戏,我想包括ALT+ENTER功能,以便在全屏模式和窗口模式之间切换。我的游戏现在非常基本,没什么特别的。我可以让它在我的LoadContent函数中以窗口(默认)或全屏(通过调用ToggleFullScreen)运行,一切都很好 然而,当我在更新函数中使用完全相同的代码调用ToggleFullScreen时,我的游戏失败了。如果我启动windowed并切换到全屏,它似乎会冻结,只显示一帧,不接受键盘输入(我必须按CTRL+ALT+DEL)。如果启动全屏并切换到w
protected override void LoadContent()
{
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
graphics.ToggleFullScreen();
basicEffect = new BasicEffect(graphics.GraphicsDevice);
// etc.
}
protected override void Update(GameTime gameTime)
{
if (k.IsKeyDown(Keys.Enter) && (k.IsKeyDown(Keys.LeftAlt) || k.IsKeyDown(Keys.RightAlt)) && !oldKeys.Contains(Keys.Enter)) {
graphics.ToggleFullScreen();
gameWorld.Refresh();
}
// update the world's graphics; this fills my buffers
GraphicsBuffers gb = gameWorld.Render(graphics.GraphicsDevice);
graphics.GraphicsDevice.SetVertexBuffer(gb.vb, 0);
graphics.GraphicsDevice.Indices = gb.ib;
}
protected override void Draw(GameTime gameTime)
{
// buffer reference again; these are persistent once filled in Update, they don't get created anew
GraphicsBuffers gb = gameWorld.Render(graphics.GraphicsDevice);
foreach (EffectPass effectPass in basicEffect.CurrentTechnique.Passes)
{
effectPass.Apply();
basicEffect.Texture = textures;
graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, gb.vb.VertexCount, 0, gb.ib.IndexCount / 3);
}
}
根据AppHub论坛上的一个答案,你必须确保重建投影矩阵 从那个链接 另外,要注意不同的问题 切换全宽比时的纵横比 屏幕。如果你是3D的,你需要 重建投影矩阵。如果 你是2D的,你可能需要 将缩放矩阵传递给您的 SpriteBatch.Begin函数。这 这篇文章有关于做什么的信息 这是二维的
所以你要确保你做到了(不幸的是,发布链接的文章在Ziggyware上,该站点已经消失了很长时间,因此要找到他们链接到的2D示例,如果您有兴趣查看,可能必须使用WaybackMachine之类的存档站点,因为您正在做3D,我想可能不感兴趣).我可以使用以下类切换全屏/窗口模式:
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private Model grid;
Model tank;
int zoom = 1;
Texture2D thumb;
Vector2 position = new Vector2( 400, 240 );
Vector2 velocity = new Vector2( -1, -1 );
Matrix projection, view;
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();
projection = Matrix.CreatePerspectiveFieldOfView( MathHelper.PiOver4,
GraphicsDevice.Viewport.AspectRatio,
10,
20000 );
view = Matrix.CreateLookAt( new Vector3( 1500, 550, 0 ) * zoom + new Vector3( 0, 150, 0 ),
new Vector3( 0, 150, 0 ),
Vector3.Up );
}
/// <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 );
// TODO: use this.Content to load your game content here
thumb = Content.Load<Texture2D>( "GameThumbnail" );
grid = Content.Load<Model>( "grid" );
tank = Content.Load<Model>( "tank" );
}
/// <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
}
int ToggleDelay = 0;
/// <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();
var kbState = Keyboard.GetState();
if ( ( kbState.IsKeyDown( Keys.LeftAlt ) || kbState.IsKeyDown( Keys.RightAlt ) ) &&
kbState.IsKeyDown( Keys.Enter ) && ToggleDelay <= 0 )
{
graphics.ToggleFullScreen();
ToggleDelay = 1000;
}
if ( ToggleDelay >= 0 )
{
ToggleDelay -= gameTime.ElapsedGameTime.Milliseconds;
}
// TODO: Add your update logic here
int x, y;
x = (int)position.X;
y = (int)position.Y;
x += (int)velocity.X;
y += (int)velocity.Y;
if ( x > 480 - 64 )
velocity.X = +1;
if ( x < 0 )
velocity.X = -1;
if ( y < 0 )
velocity.Y = +1;
if ( y > 800 - 64 )
velocity.Y = -1;
position.X = x;
position.Y = y;
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 );
Matrix rotation = Matrix.CreateRotationY( gameTime.TotalGameTime.Seconds * 0.1f );
// Set render states.
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.SamplerStates[ 0 ] = SamplerState.LinearWrap;
grid.Draw( rotation, view, projection );
DrawModel( tank, rotation, view, projection );
// TODO: Add your drawing code here
spriteBatch.Begin();
spriteBatch.Draw( thumb, new Rectangle( (int)position.X, (int)position.Y, 64, 64 ), Color.White );
spriteBatch.End();
base.Draw( gameTime );
}
public void DrawModel( Model model, Matrix world, Matrix view, Matrix projection )
{
// Set the world matrix as the root transform of the model.
model.Root.Transform = world;
// Allocate the transform matrix array.
Matrix[] boneTransforms = new Matrix[ model.Bones.Count ];
// Look up combined bone matrices for the entire model.
model.CopyAbsoluteBoneTransformsTo( boneTransforms );
// Draw the model.
foreach ( ModelMesh mesh in model.Meshes )
{
foreach ( BasicEffect effect in mesh.Effects )
{
effect.World = boneTransforms[ mesh.ParentBone.Index ];
effect.View = view;
effect.Projection = projection;
//switch (lightMode)
//{
// case LightingMode.NoLighting:
// effect.LightingEnabled = false;
// break;
// case LightingMode.OneVertexLight:
// effect.EnableDefaultLighting();
// effect.PreferPerPixelLighting = false;
// effect.DirectionalLight1.Enabled = false;
// effect.DirectionalLight2.Enabled = false;
// break;
// case LightingMode.ThreeVertexLights:
//effect.EnableDefaultLighting();
//effect.PreferPerPixelLighting = false;
// break;
// case LightingMode.ThreePixelLights:
// effect.EnableDefaultLighting();
// effect.PreferPerPixelLighting = true;
// break;
//}
effect.SpecularColor = new Vector3( 0.8f, 0.8f, 0.6f );
effect.SpecularPower = 16;
effect.TextureEnabled = true;
}
mesh.Draw();
}
}
}
//
///这是游戏的主要类型
///
公共类游戏1:Microsoft.Xna.Framework.Game
{
图形管理器图形;
SpriteBatch SpriteBatch;
私有模型网格;
模型罐;
int zoom=1;
拇指纹理;
向量2位置=新向量2(400240);
矢量2速度=新矢量2(-1,-1);
矩阵投影,视图;
公共游戏1()
{
graphics=新的GraphicsDeviceManager(此);
Content.RootDirectory=“Content”;
}
///
///允许游戏在开始运行之前执行任何需要的初始化。
///在这里,它可以查询任何必需的服务,并加载任何非图形化的服务
///相关内容。调用base.Initialize将枚举所有组件
///并对它们进行初始化。
///
受保护的覆盖无效初始化()
{
//TODO:在此处添加初始化逻辑
base.Initialize();
projection=Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
GraphicsDevice.Viewport.AspectRatio,
10,
20000 );
视图=矩阵.CreateLookAt(新矢量3(15005500)*缩放+新矢量3(0150,0),
新矢量3(0,150,0),
向量3.向上);
}
///
///LoadContent将在每个游戏中调用一次,并且是加载的地方
///你所有的内容。
///
受保护的覆盖void LoadContent()
{
//创建一个新的SpriteBatch,可用于绘制纹理。
spriteBatch=新spriteBatch(图形设备);
//TODO:使用此.Content在此处加载游戏内容
thumb=Content.Load(“游戏缩略图”);
网格=Content.Load(“网格”);
储罐=内容物。荷载(“储罐”);
}
///
///UnloadContent将在每个游戏中调用一次,并且是卸载的地方
///所有内容。
///
受保护的覆盖无效UnloadContent()
{
//TODO:在此卸载任何非ContentManager内容
}
int-ToggleDelay=0;
///
///允许游戏运行逻辑,例如更新世界,
///检查碰撞、收集输入和播放音频。
///
///提供计时值的快照。
受保护覆盖无效更新(游戏时间游戏时间)
{
//允许游戏退出
if(GamePad.GetState(PlayerIndex.One).Buttons.Back==ButtonState.Pressed)
这是Exit();
var kbState=Keyboard.GetState();
if((kbState.IsKeyDown(Keys.LeftAlt)| | kbState.IsKeyDown(Keys.righalt))&&
kbState.IsKeyDown(Keys.Enter)和&ToggleDelay=0)
{
ToggleDelay-=gameTime.ElapsedGameTime.毫秒;
}
//TODO:在此处添加更新逻辑
int x,y;
x=(int)position.x;
y=(int)位置y;
x+=(int)速度x;
y+=(int)速度y;
如果(x>480-64)
速度X=+1;
if(x<0)
速度X=-1;
if(y<0)
速度Y=+1;
如果(y>800-64)
速度Y=-1;
位置X=X;
位置Y=Y;
更新(游戏时间);
}
///
///这就是所谓的比赛应该平局的时候。
///
///提供计时值的快照。
受保护覆盖无效绘制(游戏时间游戏时间)
{
图形设备。清晰(颜色:矢车菊蓝);
矩阵旋转=矩阵.CreateRota
graphics.GraphicsDevice.SetVertexBuffer(gb.vb, 0);