本节将要实现的游戏效果是,当用户在页面上拖拽了一个炮台后,炮台会自动发射出子弹,当飞跃的子弹打中外星人时,外星人就会从页面上消失,本节代码完成后效果如下:
这里写图片描述
我们看看代入如何实现。第一步是构建子弹对象,代码如下:
// change 1 bullet (damageDeal) { var obj = new this.cjs.Container() obj.addChild(new this.assetsLib.Bullet()) obj.cache(-25, -25, 50, 50) obj.damageDeal = damageDeal | 1 return obj }, // change 2 bulletTick (bullet) { if (this.cjs.Ticker.getPaused()) { return } bullet.y -= 1.5 }
bullet函数构造一个cjs容器对象,然后从资源库中加载子弹图片资源,并调用cache缓存在页面里,damgeDeal用于设置子弹的攻击力。bulletTick在时钟循环函数中被调用,它会不断的修改子弹对象在页面上的y坐标,从而实现子弹在页面上的飞升效果。
图片中发射子弹的炮台是我们以前实现的castle对象,我们要把所有的castle对象加入到一个列表中,这样我们才能知道有多少炮台要发射子弹,所以代码修改如下:
castle () { var b = this.building() b.addChild(new this.assetsLib.Castle()) b.hp = 300 b.shield = 5 b.damageDeal = 2 b.attackSpeed = 120 // change 3 b.tick = 0 // change 10 this.castleList.push(b) return b },
代码用castleList数组来记录所有炮台,其中的tick变量用来设置炮台发射子弹的时间间隔。接着我们要增加一个castleTick函数,在主时钟函数中调用,代码如下:
// change 4 castleTick () { if (this.cjs.Ticker.getPaused()) { return } for (var i = 0; i < this.castleList.length; i++) { var castle = this.castleList[i] castle.tick += 1 if (castle.tick % castle.attackSpeed === 0) { this.summonBullet(castle) } } for (i = 0; i < this.bulletList.length; i++) { this.bulletTick(this.bulletList[i]) } },
主时钟循环函数里,它会反复调用castleTick函数,该函数轮询castleList数组,从中取出炮台对象,增加炮台对象的tick计数器,一旦计数器达到指定值时,它会调用summonBullet函数创建子弹对象,然后该函数又会轮询子弹对象数组,然后调用blletTick函数设置页面上子弹对象的y坐标,从而使得子弹产生往上飞的效果。我们再看summonBullet函数的实现:
// change 5 summonBullet (castle) { var bullet = this.bullet(castle.damageDeal) bullet.x = castle.x + Math.random() * 20 - 10 bullet.y = castle.y this.addBullet(bullet) },// change 7addBullet (bullet) { this.effectLayer.addChild(bullet) this.bulletList.push(bullet) },
该函数就是调用原先实现的bullet函数创建子弹对象,并把子弹在页面上的坐标设置成与对应的炮台一致,然后调用addBullet函数把子弹对象加入特效图层和bulletList数组。这里用到的几个变量要在data()函数中增加:
data () { return { .... // change 6 bulletList: [], // change 9 castleList: [] } }
接着我们要在主轮询函数中添加代码,驱动上面代码的调用,在boardTick函数中增加如下代码:
boardTick () { .... // change 11 this.castleTick() // change 8 轮询敌人队列和子弹队列,看看两者是否相撞 for (i = this.enemyList.length - 1; i >= 0; i--) { for (var j = this.bulletList.length - 1; j >= 0; j--) { var bullet = this.bulletList[j] var pos = bullet.localToLocal(0, 0, this.effectLayer) rowCol = this.screenToRowCol(pos.x, pos.y) if (this.enemyMap[rowCol.col][rowCol.row] !== undefined) { var enemyHit = this.enemyMap[rowCol.col][rowCol.row] this.enemyDamage(enemyHit, bullet.damageDeal) if (enemyHit.hp <= 0) { this.enemyMap[rowCol.col][rowCol.row] = undefined this.removeItem(this.enemyList, enemyHit) this.boardLayer.removeChild(enemyHit) } this.removeItem(this.bulletList, bullet) this.effectLayer.removeChild(bullet) } } } }, .... enemyDamage (enemy, damage) { enemy.hp -= damage },
boardTick函数会被主循环函数调用,它会调用castleTick函数,于是炮台对象会不断的创建子弹对象。然后代码通过两个循环轮询外星人数组和子弹数组,它从子弹数组中取出子弹对象,将子弹所在的坐标转换成页面上的行和列,接着根据行和列到外星人分布图,也就是enemyMap中查询,如果对应的位置有外星人对象,那表明子弹击中了外星人。此时代码调用enemyDamage函数计算外星人被击中后会掉多少血,如果外星人的能力耗尽,那么if(enemyHit.hp <=0)部分的代码会被执行,于是外星人对象就会从页面上被删除。同时不管外星人是否被摧毁,最后的两句代码:
this.removeItem(this.enemyList, bullet)this.effectLayer.removeChild(bullet)
都会把子弹从页面上去除。完成以上代码后,图片所示的效果就可以完成了。
作者:望月从良
链接:https://www.jianshu.com/p/4da6f9223a13
共同学习,写下你的评论
评论加载中...
作者其他优质文章