使用 Bullet,BulletManager 在 XNA 中创建子弹攻击目标(十五)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛。在这里分享一下经验,仅为了和各位朋友交流经验。平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXNA 吧,最后请高手绕道而行吧,以免浪费时间。(为了突出重点和减少篇幅,有些示例代码可能不够严谨。)
子弹
子弹在游戏中很重要,几乎所有的游戏都有子弹或者类似子弹的东西。下面我们来介绍一下 Bullet 类。
Bullet 类派生自 Spirit 类,下面是他的字段:
internal readonly int Power;
private int life;字段 Power 表示子弹的威力,字段 life 表示子弹的生命值。子弹每一次攻击目标都将扣除自己的生命值,如果生命值小于等于 0,则子弹将被销毁。如果子弹初始生命值为 0,则表示生命值无限。
Bullet 类的构造函数的参数和 Spirit 类似,字段 isMoving 被设置为 true,这表示子弹一开始就处于移动状态,不过你需要设置子弹的移动速度。
protected Bullet ( /* IPlayScene scene */ IScene scene, int type, Vector2 location, string movieName, float speed, int angle, HitArea hitArea, int width, int height, int power, int life, double destroySecond, bool isMovieRotable, bool isAreaLimited, bool isAreaEntered, double areaSecond )
: base ( scene, type, location, movieName,
null,
speed, angle, hitArea, width, height, destroySecond, isMovieRotable, isAreaLimited, isAreaEntered, areaSecond )
{
this.Power = power < ? : power;
this.life = life; this.isMoving = true;
} protected override void move ( )
{
this.Location.X += this.xSpeed;
this.Location.Y += this.ySpeed;
} protected override Vector2 getMovieLocation ( )
{ return this.Location - this.halfSize; }在方法 move 中,我们根据 xSpeed 和 ySpeed 来移动子弹的位置。方法 getMovieLocation 中,我们设置了电影的位置,这样使电影的中心和子弹的中心一致。
internal virtual void Attack ( IList<IAssailable> targets )
{ if ( null == targets )
return; foreach ( IAssailable target in targets )
{
target.Injure ( this.Power, this.type ); if ( this.life > )
{
this.life -= this.Power; if ( this.life <= )
{
this.Destroy ( );
break;
} } } }方法 Attack 可以让子弹攻击一些目标,这样目标都需要实现 IAssailable 接口。我们不会直接扣除目标的生命值,而是调用他们的 Injure 方法,这样每一个目标都可以完成自己的任务。
子弹管理器
BulletManager 类派生自类 SpiritManager<T>,默认的绘制顺序是 2000。
HitTesting 事件用来让外界测试碰撞,通过参数 BulletHitAreaEventArgs,BulletManager 可以知道子弹是否击中了目标,如果子弹击中了目标,则将调用子弹的 Attack 方法。
我们需要调用字段 Spirits 的 ToArray 方法,因为 Spirits 在循环中是可能变化的。
internal event EventHandler<BulletHitAreaEventArgs> HitTesting; internal BulletManager ( )
: base ( )
{ } internal override void Update ( GameTime time )
{ if ( null == this.HitTesting )
return; foreach ( Bullet bullet in this.Spirits.ToArray ( ) )
if ( null != bullet.HitArea )
{
BulletHitAreaEventArgs hitAreaArg = new BulletHitAreaEventArgs ( bullet );
this.HitTesting ( bullet, hitAreaArg ); if ( hitAreaArg.IsHit )
bullet.Attack ( hitAreaArg.Targets ); hitAreaArg.Dispose ( );
} }在本次的示例中,方法 HitTest 并没有调用,该方法将返回和参数 area 发生碰撞的子弹。
internal List<Bullet> HitTest ( HitArea area, int mode )
{
List<Bullet> bullets = new List<Bullet> ( ); foreach ( Bullet bullet in this.Spirits )
if ( mode == && bullet.Type < && area.HitTest ( bullet.HitArea ) )
bullets.Add ( bullet );
else if ( mode == && bullet.Type >= && area.HitTest ( bullet.HitArea ) )
bullets.Add ( bullet ); return bullets;
}
示例
场景 SceneT16 中,点击按钮将创建子弹并击中小鸟。
Bird 类在前面的示例中出现过,我们为他实现了 IAssailable 接口,在 Injure 方法中,我们扣除小鸟的生命值,如果生命值小于等于 0,则销毁小鸟并将字段 IsDied 设置为 true。
internal class Bird
: Spirit, IAssailable
{
private int life = ;
internal bool IsDied = false; internal Bird ( IScene scene, Vector2 location )
: base ( scene, , location,
"bird", null,
, ,
new SingleRectangleHitArea ( new Rectangle ( -, -, , ) ),
,
,
,
true,
false,
false, )
{ } public bool Injure ( int life, int type )
{
this.life -= life;
Debug.WriteLine ( "life={0}", this.life ); if ( this.life <= )
{
Debug.WriteLine ( "life<0" );
this.IsDied = true;
this.Destroy ( );
} return true;
} protected override Vector2 getMovieLocation ( )
{ return this.Location - this.halfSize; } }类 MyBullet 派生自 Bullet,我们修改了 updateSpeed 方法,用来设置 xSpeed 和 ySpeed。
internal class MyBullet
: Bullet
{ internal MyBullet ( IScene scene, Vector2 location, int angle )
: base ( scene, , location, "mybutton", , angle,
new SingleRectangleHitArea ( new Rectangle ( -, -, , ) ),
, ,
, ,
,
false,
true,
true, )
{ } protected override void updateSpeed ( )
{
this.xSpeed = Calculator.Cos ( this.angle ) * this.speed;
this.ySpeed = Calculator.Sin ( this.angle ) * this.speed; base.updateSpeed ( );
} }在按钮的 Selected 方法,我们将调用 BulletManager 的 Append 方法来创建并添加 MyBullet,这样就产生了新的子弹。
方法 bulletHitTesting 用来判断子弹是否击中了小鸟。参数 e 的 HitArea 字段表示子弹的碰撞区域,设置 e 的 IsHit 字段为 true,则表示发生了碰撞,e 的 Targets 字段表示目标。
internal sealed class SceneT16
: CommandScene
{
// ... private Bird bird;
private BirdManager birdManager;
private BulletManager bulletManager;
private readonly Button goButton; internal SceneT16 ( )
: base ( Vector2.Zero, GestureType.None, "background1",
new Resource[] {
new Resource ( "bird2.image", ResourceType.Image, @"image\bird2" ),
new Resource ( "bullet.image", ResourceType.Image, @"image\bullet" ),
new Resource ( "go.image", ResourceType.Image, @"image\button1" ),
},
new Making[] {
new Movie ( "bird", "bird2.image", , , , "live",
new MovieSequence ( "live", true, new Point ( , ), new Point ( , ) )
),
new Movie ( "mybutton", "bullet.image", , , , "b",
new MovieSequence ( "b", new Point ( , ) )
),
new Button ( "b.go", "go.image", "GO", new Vector2 ( , ), , , new Point ( , ) ),
}
)
{
this.birdManager = new BirdManager ( );
this.birdManager.Scene = this; this.bulletManager = new BulletManager ( );
this.bulletManager.Scene = this;
this.bulletManager.HitTesting += this.bulletHitTesting; this.goButton = this.makings[ "b.go" ] as Button; this.goButton.Selected += this.goButtonSelected;
} private void bulletHitTesting ( object sender, BulletHitAreaEventArgs e )
{ if ( !this.bird.IsDied && e.HitArea.HitTest ( this.bird.HitArea ) )
{
e.IsHit = true;
e.Targets = new IAssailable[] { this.bird };
} } private void goButtonSelected ( object sender, ButtonEventArgs e )
{ this.bulletManager.Append ( new MyBullet ( this, new Vector2 ( , ), ) ); } protected override void updating ( GameTime time )
{
this.bulletManager.Update ( time ); base.updating ( time );
} public override void LoadContent ( )
{
base.LoadContent ( ); this.bird = new Bird ( this, new Vector2 ( , ) );
this.birdManager.Append ( this.bird );
} public override void UnloadContent ( )
{
this.birdManager.RemoveAll ( );
this.bulletManager.RemoveAll ( ); base.UnloadContent ( );
} public override void Dispose ( )
{
this.birdManager.Dispose ( ); this.bulletManager.HitTesting -= this.bulletHitTesting;
this.bulletManager.Dispose ( ); this.goButton.Selected -= this.goButtonSelected; base.Dispose ( );
} }
本期视频 http://v.youku.com/v_show/id_XNTg2ODM0MDQ0.html
项目地址 http://wp-xna.googlecode.com/
更多内容 WPXNA
平方开发的游戏 http://zoyobar.lofter.com/
QQ 群 213685539
欢迎访问我在其他位置发布的同一文章:http://www.wpgame.info/post/decc4_791a9f
使用 Bullet,BulletManager 在 XNA 中创建子弹攻击目标(十五)的更多相关文章
- 使用 Region,RegionManager 在 XNA 中创建特殊区域(十八)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...
- 使用 CommandScene 类在 XNA 中创建命令场景(十二)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...
- 使用 NPC,NPCManager 在 XNA 中创建 NPC
使用 NPC,NPCManager 在 XNA 中创建 NPC 平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐 ...
- 两种方式在Tableau Desktop 中创建子弹图(Bullet Chart)
子弹图,顾名思义是由于该类信息图的样子很想子弹射出后带出的轨道.起初,子弹图的发展是为了取代仪表盘上常见的那种里程表,时速表等基于圆形的信息表达方式.子弹图无修饰的线性表达方式使我们能够在狭小的空间中 ...
- 使用 Item,ItemManager 在 XNA 中创建物品和道具(十六)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...
- 使用 NPC,NPCManager 在 XNA 中创建 NPC(十九)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...
- 使用 Pinup,PinupManager 在 XNA 中创建贴图(十七)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...
- 使用 Spirit 类在 XNA 中创建游戏中的基本单位精灵(十三)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...
- 使用 Button 类在 XNA 中创建图形按钮(九)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...
随机推荐
- IOS防作弊产品技术原理分析
由于时间和水平有限,本文会存在诸多不足,希望得到您的及时反馈与指正,多谢! 工具环境: iPhone 6.系统版本 10.1.1IDA Pro 7.0 0x00:防作弊产品介绍 1.由于IOS系统的不 ...
- cocos2d-x-2.2.0_win7+vs2010搭建_eclipse+ndk-r9+cygwin搭建_教程以及编译问题汇总
声明:我是才用c/c++和cocos2d-x的如果有错误欢迎指出 文章内容我亲测过可以通过,同时我也会一直更新内容 感谢那些把自己的东西分享出来的人 原文地址:http://www.cnblogs.c ...
- 数据字典的设计--3.首页添加删除表格(JS实现)
页面效果: JS代码: 1.添加表格 function insertRows(){ //获取表格对象 var tb1 = $("#dictTbl"); var tempRow = ...
- mysql服务器系统优化
1.选择合适的IO调度 对于mysql的系统,如果是SSD,那么应该使用NOOP调度算法,如果是磁盘,就应该使用Deadline调度算法.默认是CFQ echo dealine > /sys/b ...
- vue-初识
一:vue基础1.1.Vue是一套构建用户界面的渐进式框架1.2.引入vue:<script src="https://unpkg.com/vue/dist/vue.js"& ...
- TP5.0:同一个控制器访问不同方法
首先,我把TP框架的内容放置在manualtp5文件夹 在manualtp5/application/index/controller/index控制器中定义两个方法: 我们都知道,如果我们网址中不输 ...
- 域名设置A记录或CNAME记录,但无法被解析,可能是因为状态为:clientHold
解决方案: 访问https://whois.aliyun.com/查询域名状态是否为“注册商禁止解析”: 若是,联系注册商根据对方要求进行操作以便解除. https://icann.org/epp#c ...
- 【洛谷3275】[SCOI2011] 糖果(差分约束系统入门题)
点此看题面 大致题意: 有\(N\)个小朋友,要求每个人都得到糖果,且每个人的糖果总数满足一定的关系式,请你求出至少共分给小朋友们多少糖果. 关系式的转换 首先,我们可以将题目中给定的式子进行转换: ...
- 题解 CF656G 【You're a Professional】
又是一道假黑题 它教会我们不要看难度标签 虽然这道题的数据范围很小,用cin能过,但我还是要讲一下快读 快读嘛,顾名思义,就是 快速读入 的意思 有同学就会问了,快速读入的原理是什么? 答:它的原理其 ...
- python内置函数map/reduce/filter
python有几个内置的函数很有意 思:map/filter/reduce,都是对一个集合进行处理,filter很容易理解用于过滤,map用于映射,reduce用于归并. 是python列表方法的三架 ...