第1步: 安装软件
第2步: 创建新项目
第3步: 查看代码
第4步: 加入一个精灵
第5步: 使精灵可以移动和弹跳
第6步: 继续尝试!
完整的实例
第1步: 安装软件
在动手之前,先确定你已经安装了所需的软件,其中包括August 2006 DirectX SDK.参见所需软件 中的软件列表.
第2步:创建新项目
从开始菜单中启动Microsoft Visual C# 2005 Express Edition.
在Microsoft Visual C# 2005 Express Edition 起始页面出现后,点击文件(File)菜单, 然后选择新项目( New Project).
当出现对话框的时候, 选择Windows Game (XNA) 类型的项目,输入工程名称,点击OK.
创建新项目以后,你会看到设计器视图和它的组件.至此,你的游戏中只有一个被标记为graphics的GraphicsComponent组件.
点击文件菜单(File )-保存全部(Save All).
输入保存工程的路径,这个路径也是你向游戏中加入图象及其他资源的时候的路径.保存完毕将返回设计视图.
第3步:查看代码
一些复杂的工作已经为你做好.如果你现在编译并运行你的游戏, GraphicsComponent组件将为你处理设置屏幕大小,渲染出一个空白屏幕的这些工作. 你的游戏会自动的运行和更新. 你得加入自己的代码来使游戏更有趣一些. 要查看代码,只要在灰色的设计面板中的任意地方双击就可以了,或者在解决方案浏览器中右键点击"Game1.cs",选择查看代码(View Code)
你将会看到已经为你写好的代码: 一个简单的Update循环和一个简单的 Draw循环; 你可以在任一个循环中加入你的代码.
Update 循环是你对游戏逻辑进行更新的最佳场所:移动对象,接收玩家输入,决定对象之间碰撞的结果,等等...
Draw 循环是你渲染对象和屏幕背景的一个最佳的场所.
第4步:加入一个精灵
下一步就是给屏幕上加入一个可见的图象,使用一个小的图象文件,比如.bmp或者.jpg,你也可以自己制作图形,这样就更具有创造性了.
你甚至可以制作不规则图象-比如让边缘和拐角的地方不要显示,这样看起来效果会更好,可以参见例子:怎样制作带有遮掩的纹理图..
当你有了图形文件以后,你可以按照下面的步骤把它拷贝到你的项目的文件夹里面:
右键单击解决方案资源管理器, 点击添加(Add), 再点击已有项(Existing Item).查找你的图象文件并且选中它.解决方案资源管理器中将为这个图象文件增加一项.
点击该项.在解决方案资源管理器下面的属性(Properties)面板中找到"拷贝到输出目录"(Copy To Output Directory)项,把它的值设置为"总是拷贝"(Copy always).这将保证图象文件对你编译生成的游戏程序来说总是可用的.
现在,你必须编写加载精灵,以及在屏幕上显示精灵的代码.你可以使用 怎样绘制一个精灵中给出的代码或者按照这里所讲的方式来写.
回到代码查看视图,找到你的Game1类,在构造函数的后面加入如下的这些代码.
C#
//this is a texture we can render
Texture2D myTexture;
//coordinates to draw the sprite at
int spriteX = 0;
int spriteY = 0;
//this is the object that will draw the sprites
SpriteBatch spriteBatch;
protected override void OnStarting()
{
base.OnStarting();
graphics.GraphicsDevice.DeviceReset += new EventHandler(GraphicsDevice_DeviceReset);
LoadResources();
}
void GraphicsDevice_DeviceReset(object sender, EventArgs e)
{
LoadResources();
}
void LoadResources()
{
myTexture = Texture2D.FromFile(graphics.GraphicsDevice, "mytexture.bmp");
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
请确保在调用Texture2D.FromFile 的时候使用了你刚加入的精灵.以上这些代码加载你的图象,做好画图前的准备,并且将会在图象设备被重新复位的时候重新加载进来(比如,当游戏窗口大小改变的时候)
现在,给Draw 循环中加入代码,使它看起来像这样:
C#
protected override void Draw()
{
if (!graphics.EnsureDevice())
{
return;
}
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
graphics.GraphicsDevice.BeginScene();
// TODO: Add your drawing code here
spriteBatch.Begin();
spriteBatch.Draw(myTexture, new Rectangle(spriteX, spriteY, myTexture.Width, myTexture.Height), Color.White);
spriteBatch.End();
// Let the GameComponents draw
DrawComponents();
graphics.GraphicsDevice.EndScene();
graphics.GraphicsDevice.Present();
}
这些代码在每帧显示的时候在屏幕上绘制精灵.
编译并运行你的游戏,精灵显示出来了.现在,是时候该让它动起来了.
第5步: 使精灵可以移动和弹跳
修改你的Update 函数,让它看起来像下面这样:
C#
//store some info about the sprites motion
int m_dSpriteHorizSpeed = 1;
int m_dSpriteVertSpeed = 1;
protected override void Update()
{
// The time since Update was called last
float elapsed = (float)ElapsedTime.TotalSeconds;
// TODO: Add your game logic here
//move the sprite around
UpdateSprite();
// Let the GameComponents update
UpdateComponents();
}
void UpdateSprite()
{
//move the sprite by speed
spriteX += m_dSpriteHorizSpeed;
spriteY += m_dSpriteVertSpeed;
int MaxX = Window.ClientWidth - myTexture.Width;
int MinX = 0;
int MaxY = Window.ClientHeight - myTexture.Height;
int MinY = 0;
//check for bounce
if (spriteX > MaxX)
{
m_dSpriteHorizSpeed *= -1;
spriteX = MaxX;
}
else if(spriteX < MinX)
{
m_dSpriteHorizSpeed *= -1;
spriteX = MinX;
}
if (spriteY > MaxY)
{
m_dSpriteVertSpeed *= -1;
spriteY = MaxY;
}
else if (spriteY < MinY)
{
m_dSpriteVertSpeed *= -1;
spriteY = MinY;
}
}
这给程序中加入了一点可以让精灵每帧都移动的逻辑,还能让精灵在碰到游戏窗口边缘的时候改变方向.
第6步:继续尝试!
到此为止,你可以做任何想做的尝试了,比如像这里给出的这些点子:
加入第2个精灵,使用BoundingBox对象来使得精灵之间可以相互碰撞. (请参阅 如何检测两个对象是否碰撞)
使得精灵可以根据 键盘, 鼠标, 或者 游戏手柄 的输入来移动. (请参阅输入概述)
创建一些声音事件,使得精灵移动的时候发声(请参阅如何给把声音文件加入到游戏以及怎样播放声音)
使用简单的3D模型来取代精灵,在3D空间中环游(参见 怎样绘制简单的3D模型)
完整的实例
C#
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Components;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
namespace MyFirstXNAGame
{
/// <summary>
/// This is the main type for your game
/// </summary>
partial class Game1 : Microsoft.Xna.Framework.Game
{
public Game1()
{
InitializeComponent();
}
//this is a texture we can render
Texture2D myTexture;
//coordinates to draw the sprite at
int spriteX = 0;
int spriteY = 0;
//this is the object that will draw the sprites
SpriteBatch spriteBatch;
protected override void OnStarting()
{
base.OnStarting();
graphics.GraphicsDevice.DeviceReset += new EventHandler(GraphicsDevice_DeviceReset);
LoadResources();
}
void GraphicsDevice_DeviceReset(object sender, EventArgs e)
{
LoadResources();
}
void LoadResources()
{
myTexture = Texture2D.FromFile(graphics.GraphicsDevice, "mytexture.bmp");
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
//store some info about the sprites motion
int m_dSpriteHorizSpeed = 1;
int m_dSpriteVertSpeed = 1;
protected override void Update()
{
// The time since Update was called last
float elapsed = (float)ElapsedTime.TotalSeconds;
// TODO: Add your game logic here
//move the sprite around
UpdateSprite();
// Let the GameComponents update
UpdateComponents();
}
void UpdateSprite()
{
//move the sprite by speed
spriteX += m_dSpriteHorizSpeed;
spriteY += m_dSpriteVertSpeed;
int MaxX = Window.ClientWidth - myTexture.Width;
int MinX = 0;
int MaxY = Window.ClientHeight - myTexture.Height;
int MinY = 0;
//check for bounce
if (spriteX > MaxX)
{
m_dSpriteHorizSpeed *= -1;
spriteX = MaxX;
}
else if(spriteX < MinX)
{
m_dSpriteHorizSpeed *= -1;
spriteX = MinX;
}
if (spriteY > MaxY)
{
m_dSpriteVertSpeed *= -1;
spriteY = MaxY;
}
else if (spriteY < MinY)
{
m_dSpriteVertSpeed *= -1;
spriteY = MinY;
}
}
protected override void Draw()
{
if (!graphics.EnsureDevice())
{
return;
}
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
graphics.GraphicsDevice.BeginScene();
// TODO: Add your drawing code here
spriteBatch.Begin();
spriteBatch.Draw(myTexture, new Rectangle(spriteX, spriteY, myTexture.Width, myTexture.Height), Color.White);
spriteBatch.End();
// Let the GameComponents draw
DrawComponents();
graphics.GraphicsDevice.EndScene();
graphics.GraphicsDevice.Present();
}
}
}
using System;
namespace MyFirstXNAGame
{
partial class Game1
{
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.graphics = new Microsoft.Xna.Framework.Components.GraphicsComponent();
this.GameComponents.Add(this.graphics);
}
private Microsoft.Xna.Framework.Components.GraphicsComponent graphics;
}
}
using System;
namespace MyFirstXNAGame
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
using (Game1 game = new Game1())
{
game.Run();
}
}
}
}