[翻译]XNA 3.0 Game Programming Recipes之eleven
PS:自己翻译的,转载请著明出处
3-1二维图像显示:使用SpriteBatch类加载和绘制图象
问题
您想使二维图像的屏幕创建一个2D游戏或作为用户界面一个3D游戏。你想要一个简单的界面,以便您可以指定在屏幕上图象应该显示的位置。
解决方案
XNA框架提供的功能,绘制图象的能力用一个很好的方式执行,以SpriteBatch类形式。
SpriteBatch类被设计成易用性,这节会显示它的性能。尽管如此, SpriteBatch类是非常强大的,因为它也可让您选择除几种优化的方式,你可以找到详细解释在3-4中。
注意:由于每个图像的是四叉树,它可以作为两个三角形被绘制,其中包括二维图像作为纹理。SpriteBatch会自动为你实现。因为您实际上是渲染三角形,使用SpriteBatch类让您能够充分利用硬件加速。
如何工作的
在图形编程,二维图像通常称为精灵。但是,当二维图像用于覆盖表面时,这就是所谓的纹理。因此,当讨论屏幕上的图象时,我将谈论精灵。当我需要讨论绘制到精灵上的颜色时,我会说话关于纹理。
加载纹理
XNA游戏工作室(GS)支持拖放功能,使您可以轻松导入纹理到您的项目。GS支持广泛的图像格式。首先,找到内容输入您的项目在解决方案资源管理器右上角的窗口。您可以只需将图像文件从Windows资源管理器拖到这个内容项目中。
您也可以手动执行此操作通过右键单击内容条目的解决方案资源管理器并选择添加-添加现有项所示,图3-1 。
接下来,您需要添加一个变量到您的项目,这归结为一个图象的名称,您用你的代码使图象被导入,这可以让您用代码访问图象。添加这一行到您的类变量:
Texture2D myTexture;
添加下面到你类变量的上部分:
接下来,您将连接这变量到图象中,这些都要在LoadContent方法中实现。如果你的图象名称是image1.jpg或image1.png,这个资源名称就是image1.
把图象输出到屏幕上
在XNA中,很容易把图像在屏幕上。这样做是利用SpriteBatch对象。为了方便初学者,一个SpriteBatch对象已经宣布时默认创建一个新的XNA游戏项目,它已经实例化在LoadContent方法。
注意:创建一个SpriteBatch对象花费大量的时间和大量资源。因此,不要每一祯都创建一个新SpriteBatch对象。宁可重新使用一个SpriteBatch对象它在程序开始时被创建。
在你程序中的Draw方法,你要使SpriteBatch对象绘制你的纹理:
绘制多个图象到屏幕上
如果你想使多个精灵到屏幕上,显然您必须先输入它们的纹理到该项目,并连接到一个变量,如以前。顾名思义, 一个单一的SpriteBatch对象可以使一批精灵绘制到屏幕上。本示例使用两个独立的图像文件,并期望他们已经导入到您的XNA项目和与两个纹理变量参数,在“载入纹理”一节。所有这些纹理注意两个在屏幕上不同的位置,造成四个精灵被绘制到屏幕上:
使用另外一个加载spriteBatch.Draw的方法,您可以立即指定在屏幕上的目标矩形,指明图象应该被绘制在哪里。如果目标矩形没有和图象大小相同,图像将被缩小自动适合在目标矩形内。
此代码定义了一个目标矩形具有相同的大小,你的窗口开始, 左上角( 0,0 )角落。因此,该图像将延伸你的整个屏幕,这是有用如果您想使背景:
彩色调制
直到现在,你使用Color.White作为一个参数在spriteBatch.Draw调用中。图象的每一个象素颜色将会用这个颜色混合在输出到屏幕之前。
例如,如果您指定Color.Blue,红色和绿色通道的每个像素的您的纹理将乘以0 ,而蓝色通道将乘以1 。这个将完全删除的红色和绿色部分图片。如果您的图片只有红色的像素,因为红色部分乘以0将所有的像素变成黑色的 。
如果您指定Color.Purple,红颜色通道乘以1 ,绿色通道的0 , 和蓝色通道的1 。因此,在例如红色图像,颜色保持不变。
该Color.White参数是由红,绿,蓝,因此,红,绿, 蓝色通道将乘以1 。因此,用其原来的颜色将你图象绘制到屏幕上。
您将要指定其他值比Color.White略为减少颜色强度或加强,例如,蓝色是靠减少红色和绿色颜色通道的浓度。
使用SpriteBatch类在3D程序中
当你激活SpriteBatch绘制图像,SpriteBatch将修改一些图形卡的设置。当您绘制一些3D对象后,改变这些新设置将产生不良影响的3D绘制中。因此,您可能希望在SpriteBatch以保存原来图形卡的设置,因此一旦已完成他可以存储它们。
这个例子绘制一个单一的图象到屏幕上。注意myTexture变量的定义和初始化,用Draw方法如何绘制到屏幕上:
在XNA中,它也很容易读出的键盘键目前所按下的键。在这么短的 部分,我们将我们的图象使用键盘输入。首先,我们需要跟踪我们的图象的位置,这是通过为它创建一个变量实现的。此行应加上旁边 其他四个变量到你的工程中:
3-1二维图像显示:使用SpriteBatch类加载和绘制图象
问题
您想使二维图像的屏幕创建一个2D游戏或作为用户界面一个3D游戏。你想要一个简单的界面,以便您可以指定在屏幕上图象应该显示的位置。
解决方案
XNA框架提供的功能,绘制图象的能力用一个很好的方式执行,以SpriteBatch类形式。
SpriteBatch类被设计成易用性,这节会显示它的性能。尽管如此, SpriteBatch类是非常强大的,因为它也可让您选择除几种优化的方式,你可以找到详细解释在3-4中。
注意:由于每个图像的是四叉树,它可以作为两个三角形被绘制,其中包括二维图像作为纹理。SpriteBatch会自动为你实现。因为您实际上是渲染三角形,使用SpriteBatch类让您能够充分利用硬件加速。
如何工作的
在图形编程,二维图像通常称为精灵。但是,当二维图像用于覆盖表面时,这就是所谓的纹理。因此,当讨论屏幕上的图象时,我将谈论精灵。当我需要讨论绘制到精灵上的颜色时,我会说话关于纹理。
加载纹理
XNA游戏工作室(GS)支持拖放功能,使您可以轻松导入纹理到您的项目。GS支持广泛的图像格式。首先,找到内容输入您的项目在解决方案资源管理器右上角的窗口。您可以只需将图像文件从Windows资源管理器拖到这个内容项目中。
您也可以手动执行此操作通过右键单击内容条目的解决方案资源管理器并选择添加-添加现有项所示,图3-1 。
接下来,您需要添加一个变量到您的项目,这归结为一个图象的名称,您用你的代码使图象被导入,这可以让您用代码访问图象。添加这一行到您的类变量:
Texture2D myTexture;
添加下面到你类变量的上部分:
1 namespace BookCode
2 {
3 public class Game1:Microsoft.Xna.Framework.Game
4 {
5 GraphicsDeviceManager graphics;
6 GraphicsDevice device;
7 SpriteBatch spriteBatch;
8 Texture2D myTexture;
9 public Game1()
10 {
11 graphics=new GraphicsDeviceManager(this);
12 Content.RootDirectory="Content";
13 }
14 }
15 }
注意:device变量是被GraphicsDevice创建的,因为你要经常使用它。在你的程序中你要经常连接GraphicsDevice.你应该把device=graphics.GraphicsDevice;加入在LoadContent方法中:2 {
3 public class Game1:Microsoft.Xna.Framework.Game
4 {
5 GraphicsDeviceManager graphics;
6 GraphicsDevice device;
7 SpriteBatch spriteBatch;
8 Texture2D myTexture;
9 public Game1()
10 {
11 graphics=new GraphicsDeviceManager(this);
12 Content.RootDirectory="Content";
13 }
14 }
15 }
接下来,您将连接这变量到图象中,这些都要在LoadContent方法中实现。如果你的图象名称是image1.jpg或image1.png,这个资源名称就是image1.
1 myTexture=content.Load<Texture2D>("image1");
这将使管道的内容(见3-9节 )加载图像文件从磁盘和进程中,它成为一个可行的变数。把图象输出到屏幕上
在XNA中,很容易把图像在屏幕上。这样做是利用SpriteBatch对象。为了方便初学者,一个SpriteBatch对象已经宣布时默认创建一个新的XNA游戏项目,它已经实例化在LoadContent方法。
注意:创建一个SpriteBatch对象花费大量的时间和大量资源。因此,不要每一祯都创建一个新SpriteBatch对象。宁可重新使用一个SpriteBatch对象它在程序开始时被创建。
在你程序中的Draw方法,你要使SpriteBatch对象绘制你的纹理:
1 SpriteBatch.Begin();
2 SpriteBatch.Draw(myTexture,new Vector2(50,100),Color.White);
3 SpriteBatch.End();
这将绘制你的图象到屏幕上。第二个参数允许你指定图象在屏幕上的位置。更明确点,你可以定义屏幕上的象素,你想放置图象在top-left角的位置。窗口的左上角是相应的(0,0)点,所以在这种情况下,窗口到左边框到图象之间是50象素,窗口的高到图象之间的是100象素。在本节的最后的参数你可以发现更多的信息。2 SpriteBatch.Draw(myTexture,new Vector2(50,100),Color.White);
3 SpriteBatch.End();
绘制多个图象到屏幕上
如果你想使多个精灵到屏幕上,显然您必须先输入它们的纹理到该项目,并连接到一个变量,如以前。顾名思义, 一个单一的SpriteBatch对象可以使一批精灵绘制到屏幕上。本示例使用两个独立的图像文件,并期望他们已经导入到您的XNA项目和与两个纹理变量参数,在“载入纹理”一节。所有这些纹理注意两个在屏幕上不同的位置,造成四个精灵被绘制到屏幕上:
1 SpriteBatch.Begin();
2 SpriteBatch.Draw(myTexture,new Vector2(50,100),Color.White);
3 SpriteBatch.Draw(anotherTexture,new Vector2(70,100),Color.White);
4 SpriteBatch.Draw(anotherTexture,new Vector2(70,200),Color.White);
5 SpriteBatch.Draw(myTexture,new Vector2(100,200),Color.White);
6 SpriteBatch.End();
图像绘制成一个矩形2 SpriteBatch.Draw(myTexture,new Vector2(50,100),Color.White);
3 SpriteBatch.Draw(anotherTexture,new Vector2(70,100),Color.White);
4 SpriteBatch.Draw(anotherTexture,new Vector2(70,200),Color.White);
5 SpriteBatch.Draw(myTexture,new Vector2(100,200),Color.White);
6 SpriteBatch.End();
使用另外一个加载spriteBatch.Draw的方法,您可以立即指定在屏幕上的目标矩形,指明图象应该被绘制在哪里。如果目标矩形没有和图象大小相同,图像将被缩小自动适合在目标矩形内。
此代码定义了一个目标矩形具有相同的大小,你的窗口开始, 左上角( 0,0 )角落。因此,该图像将延伸你的整个屏幕,这是有用如果您想使背景:
1 SpriteBatch.Begin();
2 PresentationParameters pp=device.PresentationParameters;
3 spriteBatch.Draw(myTexture,new Rectangel(0,0,pp.BackBufferWidth,pp.BackBufferHeight),Color.White);
4 SpriteBatch.End();
请注意,图象被绘制到屏幕仅仅在于调用spriteBatch.End()时。这样的时间安排允许XNA排序优化图像。见3-4节的更多信息关于这一点。2 PresentationParameters pp=device.PresentationParameters;
3 spriteBatch.Draw(myTexture,new Rectangel(0,0,pp.BackBufferWidth,pp.BackBufferHeight),Color.White);
4 SpriteBatch.End();
彩色调制
直到现在,你使用Color.White作为一个参数在spriteBatch.Draw调用中。图象的每一个象素颜色将会用这个颜色混合在输出到屏幕之前。
例如,如果您指定Color.Blue,红色和绿色通道的每个像素的您的纹理将乘以0 ,而蓝色通道将乘以1 。这个将完全删除的红色和绿色部分图片。如果您的图片只有红色的像素,因为红色部分乘以0将所有的像素变成黑色的 。
如果您指定Color.Purple,红颜色通道乘以1 ,绿色通道的0 , 和蓝色通道的1 。因此,在例如红色图像,颜色保持不变。
该Color.White参数是由红,绿,蓝,因此,红,绿, 蓝色通道将乘以1 。因此,用其原来的颜色将你图象绘制到屏幕上。
您将要指定其他值比Color.White略为减少颜色强度或加强,例如,蓝色是靠减少红色和绿色颜色通道的浓度。
使用SpriteBatch类在3D程序中
当你激活SpriteBatch绘制图像,SpriteBatch将修改一些图形卡的设置。当您绘制一些3D对象后,改变这些新设置将产生不良影响的3D绘制中。因此,您可能希望在SpriteBatch以保存原来图形卡的设置,因此一旦已完成他可以存储它们。
1 spriteBatch.Begin(SpriteBlendMode.None,Spr
iteSortMode.Texture,SaveStateMode.SaveState);
代码 这个例子绘制一个单一的图象到屏幕上。注意myTexture变量的定义和初始化,用Draw方法如何绘制到屏幕上:
1 namespace BookCode
2 {
3 public class Game1:Microsoft.Xna.Framework.Game
4 {
5 GraphicsDeviceManager graphics;
6 GraphicsDevice device;
7 SpriteBatch spriteBatch;
8 Texture2D myTexture;
9 public Game1()
10 {
11 graphics=new GraphicsDeviceManager(this);
12 Content.RootDirectory="Content";
13 }
14
15 protected override void Initialize()
16 {
17 base.Initialize();
18 }
19 protected override void LoadContent()
20 {
21 device=graphics.GraphicsDevice;
22 spriteBatch=new SpriteBatch(GraphicsDevice);
23 myTexture=Content.Load<Texture2D>("smile");
24 }
25 protected override void UnloadContent()
26 {}
27 protected override void Update(GameTime gameTime)
28 {
29 if(GamePad.GetState(PlayerIndex.One).Buttons.Back==ButtonState.Pressed)
30 this.Exit();
31 base.Update(gameTime);
32 }
33 protected override void Draw(GameTime gameTime)
34 {
35 device.Clear(ClearOptions.Target|ClearOptions.DepthBuffer,Color.CornflowerBlue,1,0);
36 spriteBatch.Begin();
37 spriteBatch.Draw(myTexture,new Vector2(50,100),Color.White);
38 spriteBatch.End();
39 base.Draw(gameTime);
40 }
41 }
42 }
用键盘输入移动图象2 {
3 public class Game1:Microsoft.Xna.Framework.Game
4 {
5 GraphicsDeviceManager graphics;
6 GraphicsDevice device;
7 SpriteBatch spriteBatch;
8 Texture2D myTexture;
9 public Game1()
10 {
11 graphics=new GraphicsDeviceManager(this);
12 Content.RootDirectory="Content";
13 }
14
15 protected override void Initialize()
16 {
17 base.Initialize();
18 }
19 protected override void LoadContent()
20 {
21 device=graphics.GraphicsDevice;
22 spriteBatch=new SpriteBatch(GraphicsDevice);
23 myTexture=Content.Load<Texture2D>("smile");
24 }
25 protected override void UnloadContent()
26 {}
27 protected override void Update(GameTime gameTime)
28 {
29 if(GamePad.GetState(PlayerIndex.One).Buttons.Back==ButtonState.Pressed)
30 this.Exit();
31 base.Update(gameTime);
32 }
33 protected override void Draw(GameTime gameTime)
34 {
35 device.Clear(ClearOptions.Target|ClearOptions.DepthBuffer,Color.CornflowerBlue,1,0);
36 spriteBatch.Begin();
37 spriteBatch.Draw(myTexture,new Vector2(50,100),Color.White);
38 spriteBatch.End();
39 base.Draw(gameTime);
40 }
41 }
42 }
在XNA中,它也很容易读出的键盘键目前所按下的键。在这么短的 部分,我们将我们的图象使用键盘输入。首先,我们需要跟踪我们的图象的位置,这是通过为它创建一个变量实现的。此行应加上旁边 其他四个变量到你的工程中:
1 Vector2 position=new Vector2(200,100);
你可以为我们的图象设置一个默认的位置。使用Draw方法绘制出这个位置:
1 spriteBatch.Draw(myTexture,position,Color.White);
此代码应运行没有任何问题,显示的图像在一个固定的位置。下一个, 让我们读入我们的键盘的状态。由于这项工作应经常使用,应该在Update方法中实现。下面一行在Update方法读入当前键盘上的键的状态:
1 keyboardState keyState=Keyboard.GetState();
最后,我们能使用keyState变量去检查压下的键和相应的改变图象的位置:
1 if(keyState.IsKeyDown(Keys.Right))
2 position.X++;
3 if(keyState.IsKeyDown(Keys.Left))
4 position.X--;
5 if(keyState.IsKeyDown(Keys.Down))
6 position.Y++;
7 if(keyState.IsKeyDown(Keys.Up))
8 position.Y--;
2 position.X++;
3 if(keyState.IsKeyDown(Keys.Left))
4 position.X--;
5 if(keyState.IsKeyDown(Keys.Down))
6 position.Y++;
7 if(keyState.IsKeyDown(Keys.Up))
8 position.Y--;