平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛。在这里分享一下经验,仅为了和各位朋友交流经验。平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXNA 吧,最后请高手绕道而行吧,以免浪费时间。(为了突出重点和减少篇幅,有些示例代码可能不够严谨。)
元件
游戏中有些元素并不适合作为精灵,所以平方将这些元素归入元件,比如:按钮和标签。而这里我们首先建立了一个基类 Making:
internal abstract class Making : IDisposable{ protected readonly string resourceName; internal readonly string Name; protected bool isVisible = true; internal virtual bool IsVisible { get { return this.isVisible; } set { this.isVisible = value; } } protected Making ( string name, string resourceName ) { this.Name = name; this.resourceName = resourceName; } internal virtual void InitResource ( ResourceManager resourceManager ) { } public virtual void Dispose ( ) { }}我们定义了字段 resourceName 和 Name,分别表示元件所用的资源名称和元件自身的名称。其中资源名称也就是 Resource 结构的 Name 字段。比如:如果元件使用了一张图片,则就需要关联图片的资源名称。而 Name 表示元件名称,必须是唯一的。
Making 的 IsVisible 属性用来控制是否显示元件,你可以在派生类中访问这个属性来决定是否显示。
InitResource 方法用来从 ResourceManager 获取所需要的资源,这里需要由派生类来决定载入哪些资源。
Making 类还实现了 IDisposable 接口,用来释放不需要的内容,但你并不需要释放从 ResourceManager 获取的资源,因为这些资源应该由 ResourceManager 管理。
图形
我们从 Making 类派生了 Shape 类,用来在屏幕上显示一个图形,这是一个简单的类,但是之后我们还会创建更复杂的电影类。
internal class Shape : Making{ internal static void Draw ( Shape shape, GameTime time, SpriteBatch batch ) { if ( !shape.isVisible ) return; batch.Draw ( shape.Texture, shape.location * World.Scale, null, Color.White, 0, Vector2.Zero, World.TextureScale, SpriteEffects.None, shape.order ); } internal Texture2D Texture; protected Vector2 location; public virtual Vector2 Location { get { return this.location; } set { this.location = value; } } protected readonly float order; // ... internal Shape ( string name, string resourceName, Vector2 location, float order ) : base ( name, resourceName ) { this.location = location; this.order = order; } internal override void InitResource ( ResourceManager resourceManager ) { this.Texture = resourceManager.GetTexture ( this.resourceName ); }}Shape 类包含一个 Texture2D 类型的字段,他就是我们需要绘制的图形,这个字段将在 InitResource 方法中得到初始化,我们从 ResourceManager 获取图形资源。
Location 属性表示图形的位置,你可以在任何时候修改图形的位置。而 order 字段是一个保留字段,暂时没有效果。
使用静态方法 Draw 来完成最后的绘制任务,我们还根据元件的 isVisible 字段来确定是否显示图形。注意,在 Draw 方法中的 Scale 和 TextureScale 字段,他们属于 World 类,分别表示整个游戏的比例和图像的缩放比例。
显示图形
最后,我们来显示图形,首先定义 ResourceManager 和 Shape,并初始化他们。
private readonly ResourceManager resourceManager;private readonly Shape birdShape;public World ( Color backgroundColor ) : base ( ){ // ... this.resourceManager = new ResourceManager ( new Resource[] { new Resource ( "bird", ResourceType.Image, @"image\bird" ) } ); this.resourceManager.World = this; this.birdShape = new Shape ( "shape.bird", "bird", new Vector2 ( 50, 50 ) );}我们使用 ResourceManager 定义我们需要的资源,虽然没有使用 LoadContent 方法载入资源,但是你还是可以创建任何元件,这里我们创建了一个关于小鸟的 Shape 类。
protected override void OnNavigatedTo ( NavigationEventArgs e ){ // ... this.resourceManager.LoadContent ( ); this.birdShape.InitResource ( this.resourceManager ); base.OnNavigatedTo ( e );}当我们调用了 LoadContent 方法之后,我们需要使用 InitResource 方法让 Shape 类从 ResourceManager 获取他所需要的图像资源,否则绘制将出现错误。
private void OnDraw ( object sender, GameTimerEventArgs e ){ this.GraphicsDevice.Clear ( this.BackgroundColor ); this.spiritBatch.Begin ( ); Shape.Draw ( this.birdShape, new GameTime ( e.TotalTime, e.ElapsedTime ), this.spiritBatch ); this.spiritBatch.End ( );}最后,我们使用 Shape 的静态方法 Draw 来绘制图形,其中的第二个参数可以设置为 null,因为这里我们不需要他。需要注意的是,你仍然需要调用 SpriteBatch 类的 Begin 和 End 方法。
缩放和移动
通过设置 World 的 TextureScale 和 Scale 字段,可以控制游戏的比例和图像的缩放比例,同时修改他们就可以将游戏调整为何时的大小。在下面的代码中,我将游戏大小减少一半。
public partial class World : PhoneApplicationPage{ internal static float TextureXScale = 1; internal static float TextureYScale = 1; internal static Vector2 TextureScale = new Vector2 ( TextureXScale, TextureYScale ); internal static float XScale = 1; internal static float YScale = 1; internal static Vector2 Scale = new Vector2 ( XScale, YScale ); internal static Vector2 FlipScale = new Vector2 ( YScale, XScale ); public World ( Color backgroundColor ) : base ( ) { // ... TextureXScale = 0.5f; TextureYScale = 0.5f; TextureScale = new Vector2 ( TextureXScale, TextureYScale ); XScale = 0.5f; YScale = 0.5f; Scale = new Vector2 ( XScale, YScale ); FlipScale = new Vector2 ( YScale, XScale ); }}修改 Shape 类的 Location 属性,就可以实现图形的移动。
private void OnUpdate ( object sender, GameTimerEventArgs e ){ this.birdShape.Location += new Vector2 ( 1f, 1f );}在这里,由于我们调整了 Scale,所以在屏幕上小鸟不会移动 1 个像素,而是 0.5 像素。
本期视频
项目地址 更多内容 平方开发的游戏 QQ 群 213685539欢迎访问我在其他位置发布的同一文章: