上一节已经设计好了UML类图,那么现在就开始把图上面的东西演变成代码;
上次那个大体构架的类图只体现出了各个类的关系,还没有决定他们的该有的行为以及属性,现在就来给这幅图给填满、完善。
首先来实现TankeSprite基类,先来列出它该有的行为和属性:
#Attribute
MainGame //主游戏的引用,因为精灵的内部操作需要用的Game实例的一些游戏输入、绘制精灵等等一些方法
Direction //坦克的面朝方向,也决定坦克的移动方向,朝那个方向发射子弹
IsBeHit //是否被其他坦克击中,表示一个坦克现在的状态
TankeTexture2d //坦克纹理贴图的容器,我们游戏上面体现的东西
TankeRect //表示一个坦克的矩形和坐标,用于检测碰撞和在游戏上面体现的位置
#Method
TankeSprite() //构造函数
Init() //初始化函数,例如贴图的载入和初始化操作等一些操作
Move() //坦克的移动行为
Fire() //坦克开火行为
Biast() //爆炸,坦克被击中后的行为
Update() //坦克类的更新
Draw() //坦克类的重绘
暂时先这么多属性和方法,当然还不止这么多,但先设定这么多,后面现代再添加到上面,下面是TankeSprite类填充数据后的类图:
现在开始码代码,先根据类图定出该类的结构:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace TankeWar.Sprites
{
internal abstract class TankeSprite
{
#region Attribute
/// <summary>
/// 主游戏对象
/// </summary>
protected Game MainGame;
/// <summary>
/// 小坦克移动方向
/// </summary>
protected TankeDirection Direction;
/// <summary>
/// 是否被子弹击中
/// </summary>
protected bool IsBeHit;
/// <summary>
/// 坦克贴图
/// </summary>
protected Texture2D TankeTexture2d;
/// <summary>
/// 坦克坐标及大小
/// </summary>
protected Rectangle TankeRect;
#endregion
#region Method
/// <summary>
/// 构造函数
/// </summary>
/// <param name="game">主游戏</param>
public TankeSprite(Game game)
{
Init(game);
}
/// <summary>
/// 精灵初始化
/// </summary>
/// <param name="game"></param>
protected virtual void Init(Game game) { }
/// <summary>
/// 坦克移动
/// </summary>
protected abstract void Move();
/// <summary>
/// 坦克开火
/// </summary>
protected virtual void Fire() { }
/// <summary>
/// 坦克爆炸
/// </summary>
protected virtual void Biast() { }
/// <summary>
/// 游戏更新
/// </summary>
/// <param name="gameTime">提供计时值的快照。</param>
public virtual void Update(GameTime gameTime) { }
/// <summary>
/// 游戏自我绘制
/// </summary>
/// <param name="spriteBatch"></param>
public virtual void Draw(SpriteBatch spriteBatch) { }
#endregion
}
}
结构已经有了,下面开始为这个骨架填充内容,首先要做的时候初始化坦克精灵,一个一个来从Init()开始,这里主要是在坦克实例一产生的时候给它上一层皮,坦克的皮,加载我们的2d纹理贴图,先让我们能直接在屏幕上看到坦克,像第一篇那样,但这次我们不满足只是仅仅在屏幕上而已,要真真正正地让坦克听我们的话,能上下左右移动,而且有4个方向的转动。
首先我们的贴图要稍做一下处理,上次我们是用的贴图只是有一个的坦克方向而已,这次我们要拿一张1×4方向的坦克贴图,每次转动方向的时候会进行判断然后在游戏画面绘制出不同的部分,这个人物行走图是一个原理。那接下来要做的就是将4个不同方向的图片合成一张1×4的图片:
像这样:
合成这样:
为此我还故意写了个小工具,虽然简陋但也能凑合着用,源码也在我的博客里面 这是源码博文链接
修改好我们需要的图片,直接拖动我们的内容管道项目里面,取个名字,PlayerTanke
终于开始码代码了。
首先是坦克贴图的读取,直接用上次那个方法,把处理好的PNG贴图通过管道读到TankeTexture2d里面,这个是在游戏精灵初始化的时候读取,所以写在Init()里面:
/// <summary> /// 精灵初始化 /// </summary> /// <param name="game"></param> protected virtual void Init(Game game) { this.TankeTexture2d = game.Content.Load<Texture2D>("PlayerTanke"); TankeRect = new Rectangle(0, 0, TankeTexture2d.Height, TankeTexture2d.Width / 4); }
载入贴图的同时也把TankeRect给初始化一遍,并且把精灵的只显示出4分之一的部分,因为我们的是一张四个方向不同的图片,全部显示出来的话就是四个方向的贴图了,然后编写Draw()/// <summary> /// 游戏自我绘制 /// </summary> /// <param name="spriteBatch"></param> public virtual void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(TankeTexture2d, TankeRect, TankeRect, Color.White); }
有了这两个方法的话,我们的坦克已经是可以游戏里面运行了,但还不会听我们的指挥,下来就%0�大声