既然游戏角色有好几张图片,那么根据什么决定使用哪一张图片呢?
一个常见的好方法是给角色类加一个枚举,枚举是角色的各种状态,然后在Update或者Draw中写一个switch,根据这个枚举选择显示哪张图片。
有的时候,会有需要状态组合的情况,比如状态有走路、站立,也有开枪和不开枪,组合之后就是走路开枪、站立开枪之类的状态,这时可以使用C#的标志枚举,用法如下:
[Flags] //Flags声明这是个标志枚举 public enum MeiteluStateEnum { IsStanding = 0, IsShooting = 2, IsDieing1 = 4, IsDieing2 = 8, IsLeft = 16,//左方向 }
标志枚举中的各个枚举值使用2的倍数,然后使用异或^来减去一个枚举,使用或|来加上一个枚举。
但是角色光会改变图片是不行的,还需要在游戏画面中改变位置来进行运动,这需要通过改变角色的x、y值来实现。
普通的移动很简单,但是遇到跳跃、滑翔之类的动作可能就要费一番功夫了,这个话题不是本教程讨论的内容,这里先不谈。
在几乎任何游戏开发书籍中都会谈到的就是碰撞检测,这也是几乎所有游戏都要用到的一个东西。我们给每个角色添加类似以下的代码:
public Rectangle CollisionRect { get { return new Rectangle( (int)X + collisionOffset, (int)Y + collisionOffset, frameSize.X - (collisionOffset * 2), frameSize.Y - (collisionOffset * 2) ); } }
这是一个矩形包围盒,意思是游戏角色周围有一个矩形,这个矩形和其他角色的矩形包围盒相交,就是碰撞到,否则就是没碰撞到。
其中,collisionOffset是指的矩形包围盒的矩形离图片边缘的距离,上边代码中的四个collisionOffset可以不一样,各自使用一个变量。
使用类似以下的方法检查碰撞检测:
role1.CollisionRect.Intersects(role2.CollisionRect)
至于这句代码在哪里,最好放一个管理所有角色对象的管理类里,或者根本就是Game1类,而不是某一个角色里,这样比较好组织代码。
游戏一般还得有背景,其实这也很简单,背景也可以看做是一种特殊的角色,只不过这个角色比较“愣”,就会在后边罚站,而不会随便动。
如果Update里的switch中的代码过多,可以考虑重构成多态,然后得到一个状态模式。重构的内容,一两句话说不清楚,可以参考《重构:改善既有代码的设计》。状态模式用在这里,再合适不过了,不过还请读者自己查阅设计模式相关书籍资料。
如果角色有很多种碰撞检测算法,跟障碍物碰撞和跟敌人碰撞返回的Rectangle不一样,也可以用一个策略模式优化代码。