XNA框架基础——从头开始

从头开始

您已经准备好了一切,现在就让我们开始编码吧!本节您将在XNA Studio模板的帮助下创建一个简单的游戏项目,然后在Update和Draw方法中添加少量代码以实现一些小功能。在下一小节学习了SpriteBatch类之后,您将创建您的第一个游戏。

您的第一个项目

打开XNA Game Studio Express,在菜单栏中选择“文件→新建项目”,在弹出的新窗口中选择“Windows Game”模板,然后在项目名称处输入新项目的名称,比如“HelloWorld”或者就使用默认的名称“WindowsGame1”,在位置处输入新项目的保存位置,最后点击“确定”按钮。另外,在该窗口中还可以创建基于初学者工具包的游戏项目,比如“Spacewar Windows Starter Kit”。如下图1-10所示:

201007210905
图1-10

在新创建的项目中包含两个类文件:Game1.cs和Program.cs。其中Program.cs文件包含了该应用程序的入口点Main方法,如下所示:


using (Game1 game = new Game1())

{

..game.Run();

} // using

Game1.cs文件包含了类Game1(继承自类Microsoft.Xna.Framework.Game),它包含了之前讲过的三个方法:Initialize、Update和Draw。Initialize方法此时不执行任何操作,只是调用基类的Initialize方法进行基本的初始化操作。Update方法主要包含下面的几行代码,用来检查Gamepad上的“Back”按钮是否被按下,如果按下则退出游戏,否则调用基类的Update方法:


// Allows the game to exit

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)

   this.Exit();

Draw方法主要执行一个操作,将游戏窗口的背景色设置成一个特定的颜色,如下所示:


graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
按F5运行

现在按下键盘上的F5键,或者选择菜单栏上的“调试→启动调试”命令运行游戏,此时将弹出如图1-11-(1)所示的窗口,它的了蓝色背景就是在Draw方法中设置的。

201007210906
图1-11

您也可以把背景色改为绿色,比如Color.Green,然后再按F5运行程序,可以得到如图1-11-(2)所示的窗口,代码如下:


graphics.GraphicsDevice.Clear(ClearOptions.DepthBuffer,

  Color.Green, 1, 0);

参数ClearOptions的默认值是ClearOptions.Target | ClearOptions.DepthBuffer,意思是背景色和Depth缓存都被清除。

修改代码

现在,您可以想一想如何修改您的代码来实现一些操作。比如,按下键盘上的Escape键可以退出游戏。之前说过,XNA默认的会在Update方法中检查Xbox 360控制器上的Back按钮是否被按下来决定是否退出游戏,代码如下:


// Allows the default game to exit on Xbox 360 and Windows

if (GamePad.GetState(PlayerIndex.One).Buttons.Back ==

ButtonState.Pressed)

  this.Exit();

在“第三章-辅助类”中您将学习到Input类的使用,不过现在您可以使用一种快速的方法来操作键盘,下面的代码演示了当您按下Escape键时也能退出程序:


// Get current gamepad and keyboard states

GamePadState gamePad = GamePad.GetState(PlayerIndex.One);

KeyboardState keyboard = Keyboard.GetState();

// Back or Escape exits our game on Xbox 360 and Windows

if (gamePad.Buttons.Back == ButtonState.Pressed ||

  keyboard.IsKeyDown(Keys.Escape))

  this.Exit();

第二章将详细讨论Sprites的知识,不过现在您可以稍微提前一点来学习在游戏中加载图像:给游戏加上一个背景图,然后操作键盘或者GamePad来移动该背景图,就像在一个竞速游戏或者Tile引擎中的一样,这些在很多2D的角色扮演游戏中经常会用到。对于更加复杂的Tile引擎,您还会需要石头、草、水、泥土等texture,甚至在草和水之间加一些过渡纹理(Transition Textures)。这将需要更多的texture和自定义代码,不过这也不是很难,如果您真的对Tile引擎感兴趣,您在网络上可以找到很多相关的信息。

在您的第一个项目中添加的texture如图1-12所示:

201007210907
图1-12

要把这个texture(CityGroundSmall.jpg)加入到您的项目中,只需要在解决方案资源管理器(Solution Explorer)中把它拖拽到您的项目中即可,然后右键点击该文件查看“属性”,如图1-13所示:

201007210908
图1-13

通常您可能只会看到一些“生成操作(Build Action)”和“复制到输出目录”的选项(比如,您可能想把一个.dll或者.xml文件包含进来)。但如果XNA Studio检测到受支持的内容文件格式,您还会看到一些高级属性,此时会有另外三个重要设置:资源名称(Asset Name)、内容导入器(Content Importer)、内容处理器(Content Processor)。其中资源名称在将来选择加载资源时使用,而且内容文件的资源名称必须是唯一的,不能有重复。对于内容导入器,您可以像图1-13-(1)所示的情况中选择“Texture-XNA Framework”,或者为.x类型的文件选择“模型导入器(Model Importer)”,或者为.fx类型的文件选择“特效导入器(Effect Importer)”,如图1-13-(2)所示。

内容处理器则包含更多的选项,比如,为这里的texture(CityGroundSmall.jpg)可以选择“Texture (Sprite, 32bpp) - XNA Framework”或者“Texture (Model, DXT, mipmapped) - XNA Framework”。DXT是一种压缩格式,在dds类型的文件中也经常使用,而且在游戏中这种格式用于texture效果非常好,因为它的压缩比高达1:6(如果包含透明像素则是1:4),这意味着在硬盘和显卡内存中的相同大小的空间上您可以存放多达 6倍数量的texture。对于2D sprite通常最好不要进行压缩,因为查看它们实际尺寸的时候使用32bpp(bits per pixel)可以保证最好的质量。关于内容管道的内容在本部分随后将会讲到。

现在如果您按下F5或者F6(生成解决方案)上述添加的texture将被处理,并在项目的输出文件夹中产生一个新的文件“CityGroundSmall.xnb”,而且在项目的输出窗口中会显示下面的信息:


Building CityGroundSmall.jpg -> bin\x86\Debug\CityGroundSmall.xnb

现在您要做的最后一件事就是加载已经导入的纹理文件,在Initialize方法中进行操作并且在类中添加一个变量backgroundTexture,并使用之前您指定的资源名称(Asset Name)(资源名称默认的是您添加的内容文件的名称)。要渲染您的texture到输出屏幕上,您需要下一章要讨论的SpriteBatch类,它先设置Alpha Blending,然后把texture画到sprite中,最后把所有东西都画到屏幕上,代码如下:


Texture2D backgroundTexture;

SpriteBatch sprites;

protected override void Initialize()

{

  backgroundTexture = content.Load<Texture2D>("CityGroundSmall");

  sprites = new SpriteBatch(graphics.GraphicsDevice);

  base.Initialize();

} // Initialize()

要显示背景您必须在Draw方法中启动SpriteBatch,并把texture渲染到sprites中:


protected override void Draw(GameTime gameTime)

{

  graphics.GraphicsDevice.Clear(Color.Green);

  

  sprites.Begin();

  sprites.Draw(backgroundTexture, Vector2.Zero, Color.White);

  sprites.End();

  base.Draw(gameTime);

} // Draw(gameTime)

上述代码将在您的输出屏幕的(0,0)坐标处显示该背景,SpriteBatch.Draw方法中的Color参数也可以重新设置,不过这里暂时并不重要。按下F5您将看到图1-14所示的结果:

201007210909
图1-14

为您的项目做的最后一件事就是添加使用键盘或者GamePad来滚动背景的功能,这样您就可以把可滚动的Tile渲染到整个背景。像下面这样修改Update方法您将可以捕获键盘或者GamePad输入:


float scrollPosition = 0;

protected override void Update(GameTime gameTime)

{

  // Get current gamepad and keyboard states

  GamePadState gamePad = GamePad.GetState(PlayerIndex.One);

  KeyboardState keyboard = Keyboard.GetState();

  // Back or Escape exits our game on Xbox 360 and Windows

  if (gamePad.Buttons.Back == ButtonState.Pressed ||

    keyboard.IsKeyDown(Keys.Escape))

    this.Exit();

  // Move 400 pixels each second

  float moveFactorPerSecond = 400 *

  (float)gameTime.ElapsedRealTime.TotalMilliseconds / 1000.0f;

  // Move up and down if we press the cursor or gamepad keys.

  if (gamePad.DPad.Up == ButtonState.Pressed ||

    keyboard.IsKeyDown(Keys.Up))

    scrollPosition += moveFactorPerSecond;

  if (gamePad.DPad.Down == ButtonState.Pressed ||

    keyboard.IsKeyDown(Keys.Down))

    scrollPosition -= moveFactorPerSecond;

  base.Update(gameTime);

} // Update(gameTime)

前面几行代码和之前的例子是相同的。接下来要计算每一帧要移动多少像素,如果一秒钟只画一帧,那么变量moveFactorPerSecond的值就是400;如果一秒钟画60帧,那么一帧需要1/60秒,此时该变量的值就是400/60(其中gameTime.ElapsedRealTime表示相邻两帧之间的时间间隔)。

每当用户按下Up或者Down键的时候变量scrollPosition的值都会发生变化,此时在Draw方法中把scrollPosition的值加到坐标y上,就可以把背景来回上下移动了,代码如下:


protected override void Draw(GameTime gameTime)

{

  graphics.GraphicsDevice.Clear(Color.Green);



  sprites.Begin();

  int resolutionWidth = graphics.GraphicsDevice.Viewport.Width;

  int resolutionHeight = graphics.GraphicsDevice.Viewport.Height;

  for (int x = 0; x <= resolutionWidth / backgroundTexture.Width;

    x++)

  for (int y = -1; y <= resolutionHeight / backgroundTexture.Height;

    y++)

  {

    Vector2 position = new Vector2(

      x * backgroundTexture.Width,

      y * backgroundTexture.Height +

      ((int)scrollPosition) % backgroundTexture.Height);

    sprites.Draw(backgroundTexture, position, Color.White);

  } // for for

  sprites.End();

  base.Draw(gameTime);

} // Draw(gameTime)

现在运行您的游戏就可以上下来回移动,这对于您的第一个小应用是不是很酷?

你可能感兴趣的:(框架)