XNA框架基础——从头开始

摘要:
然后在Update和Draw方法中添加少量代码以实现一些小功能。在此窗口中,您还可以基于初学者工具包创建游戏项目。Program.cs文件包含应用程序入口点的主要方法:它只调用基类的Initialize方法进行基本初始化操作;Update方法主要包含以下代码行。graphics.GraphicsDevice.Clear(Color.CornflowerBlue)

从头开始

您已经准备好了一切,现在就让我们开始编码吧!本节您将在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)

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

免责声明:文章转载自《XNA框架基础——从头开始》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇oracle-session的查询及释放Cmder使用ls中文显示乱码解决方案下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

cocosCreator中Protobuf的简单使用

cocosCreator中Protobuf的简单使用 proto文件格式: pro1.jpeg 准备工具: cocosCreator webStorm或者VSCode 安装node.js 下载protobufjs6.8.6 步骤: 安装protobufjs到全局 npm install -g protobufjs 使用npm install...

AutoCAD中程序创建Ribbon界面执行AutoCAD命令

在基于AutoCAD做二次开发时,常见的教程讲的都是在DLL中定义一些自定义命令,然后通过netload命令加载这个DLL,通过执行自定义命令的方式来执行我们的自定义功能。这样的方式在在学习中是显得很简单,但用在正式产品中就显得太业余了,没有专业精神。当然更professional的当然是和AutoCAD一样,提供一些基于Ribbon的用户界面来调用我们的...

Linux 系统的日志目录

连接时间的日志 连接时间日志一般由/var/log/wtmp和/var/run/utmp这两个文件记录,通过who查看 who /var/log/wtmp 【连接时间日志】 who /var/log/utmp 【连接时间日志】 ac -p //查看每个用户的连接时间 ac -a //查看所有用户的连...

chromium截图实现

声明:本blog是我自己写的,假设要转载,请注明:come from blog of niba! chromium终于显示是在ContentView上。但通过硬件加速。渲染合成的网页之前是在surfaceview上的。 所以。实现chromium的截图能够通过SufraceView的截图去实现。   自己创建一个SurfaceView的子类,例如以下:...

pyinstaller深入使用,打包指定模块,打包静态文件

1.标准用法:     pyinstall  **.py  直接打包    pyinstall -F **.py  打包成单文件    pyinstall -W **.py  去掉控制台窗口,黑窗口    pyinstall -i ***.ico **.py  添加图标 *** 2.高级用法:     打包一遍以后,会在py文件目录下生成spec文件,是...

WEB、FTP服务器所有响应码解释(超详细)

  WEBSERVER响应码:404错误提示---找不到文件或者目录不存在 403错误提示--找不到默认首页 505错误提示--服务器内部错误 1xx-信息提示 这些状态代码表示临时的响应。客户端在收到常规响应之前,应准备接收一个或多个1xx响应。 100-继续。 101-切换协议。 2xx-成功 这类状态代码表明服务器成功地接受了客户端请求。 2...