实现爆炸特效体系与NPC子弹弹幕。 飞机爆炸也是一个类,爆炸也是个数可变的,也需要特效管理者类。 本来想路视频转GIF的,但是gif文件过大,超过5M又上传不了,而且压缩后失帧严重,仅截取了一部分转为gif, 请大家原谅。 爆炸是一个动画帧,播放完就可以,因为比较简单, 用一个类+id 种类索引通过状态机的形式区分多种不同的爆炸。 构造: update(){} 动画延时播放:当create时,它可能不存在,如果有延时,比如延时5,visible可见性是false,但是vis是true。 在构造最后 TX类 “ TXManager类 在Maingame中申请public tm:TXManager 实现爆炸效果 在上面的设置中,所有的NPC爆炸都是一个样子,如果出现不同的NPC爆炸怎么办? 二.爆炸效果多样性 之后再ZDManager中调用dead方法 父类当中有抽象方法,但是实际执行每个子类的代码。 三.实现NPC的特殊弹幕 添加BOSS更新方法 ①一串子弹 ②实现环形的子弹 ③漩涡形子弹 ④矩阵型子弹 ⑤鞭形子弹 //鞭形子弹 ⑥朝向性子弹 NPC朝向玩家发射子弹并不是跟踪形子弹 朝向性子弹由子弹发射位置和玩家位置决定 过程: 原理: 0角度向上顺时针转过n角度,求角度n = arctan( px-x /y -py) BOSS0中 实现随机类型子弹 白鹭引擎中有像素级的碰撞检测,但是在游戏中,子弹与BOSS的碰撞,假如一颗子弹100*100像素,一颗子弹就检测了10000次,50颗子弹就是50万次,游戏会非常卡。那么不开启像素级碰撞,不规则图形的碰撞怎么解决呢? 不规则图形拆成规则图形。 //宽73,高36 要用矩形中心检测,横坐标在中心,纵坐标在选框中,实际比y多44, 想要我一起学习的可以关注我的公众号 知言不尽 找到我,交流学习,获取图片素材和源代码。
今天是开发飞行射击游戏第五天,爆炸特效体系与NPC子弹弹幕。
简介
实现效果
代码及过程一、特效体系:爆炸
创建特效类TX和特效管理者类TXManager类
1)TX类 public id:number; //代表种类 public vis:boolean; //被工厂管理的都需要vis public fi:number; //代表动画帧播放第几帧 public t:number; //延时计时器 记录延时如:3次主循环出现, public m:number; //状态 public l:number; //特效播放的总时长 public tm:TXManager; //上级指针
如果t是0,就不用延时,一种是倒计时状态,没有出现。另一种是播放状态
m 0是倒计时 1是播放。if(this.t > 0){ //虽然在仓库,但是看不到 //0 是倒计时, 1是播放 this.visible = false; this.m = 0; }else{ this.visible = true; this.m = 1 ; }
```c class TX extends egret.Sprite{ public im:egret.Bitmap; public id:number; //代表种类 public vis:boolean; //被工厂管理的都需要vis public fi:number; //代表动画帧播放第几帧 public t:number; //延时计时器 记录延时如:3次主循环出现, public m:number; //状态 public l:number; //特效播放的总时长 public tm:TXManager; //上级指针 public constructor(id:number,x:number, y:number, t:number,l:number,tm:TXManager) { super(); this.id = id; this.x = x ; this.y = y; this.t = t; this.l = l; this.m = 0; this. fi = 0 ; this.vis = true; //若它是false 工厂内对象消失 this.tm = tm; this.im = Main.createBitmapByName("tx1_1_png"); this.anchorOffsetX = this.im.width/2; this.anchorOffsetY = this.im.height/2; this.addChild(this.im); if(this.t > 0){ //虽然在仓库,但是看不到 //0 是倒计时, 1是播放 this.visible = false; this.m = 0; }else{ this.visible = true; this.m = 1 ; } } public update(){ switch(this.m ){ // case 0: //倒计时 this.t-- ; if(this.t <=0 ){ //出现爆炸 this.visible = true; this.m = 1; //播放 } break; case 1 : //动画播放 this.fi++; // if(this.fi >= this.l){ this.vis =false; //工厂里对象销毁 }else{ //没有播放完,动画帧切换 //动画切换公式 fi从0开始,到9, //10是动画的张数有几张动画就*几。 fi是动画帧,l是动画长度, this.im.texture = RES.getRes("tx1_"+Math.floor(this.fi*10/this.l + 1)+"_png"); } } } }
class TXManager extends egret.Sprite{ public tm:Array<TX>; //Array动态数组(容器),通过添加,添加对象,移除对象。 public game:MainGame; public constructor(game:MainGame) { super(); this.game = game; this.tm = new Array(); } //每create一次就new一个 public create(id:number,x:number,y:number,t:number,l:number,game:MainGame){ //生成子弹 let one = new TX(id,x,y,t,l,this); //添加到世界 this.addChild(one); //放到仓库数组最后 this.tm.push(one); } //更新所有子弹,找到每一颗子弹,每颗更新 public update(){ //整个仓库长度 ,利用循环可 以循环出所有子弹 for(let i = 0 ; i < this.tm.length ; i++){ //找到每颗子弹 let one = this.tm[i]; one.update(); //若子弹太多,仓库会满,所以子弹需要移除 //子弹出屏,vis == false。移除 if(one.vis == false){ //先从场景移除 this.removeChild(one); //仓库移除 this.tm.splice(i ,1); //移除一个对象,长度-1 i--; } } } }
构造:this.tm = tm; this.addChild(this.tm);
更新 this.tm.update();
在ZDManager类中if(npc.hp <= 0 ){ for(let k = 0 ; k < 10 ; k ++){ //-50 到 +50 this.game.tm.create( 0, npc.x + Math.random()*100 -50 , npc.y + Math.random()*100 -50 , Math.floor(Math.random() * 5), 10,this.game); } npc.vis = false; }
有限状态机实现多样化都是在子类中,case。
如果对象和对象当中,想出现不同的现象,需要不同的代码。
需要给每一个子类,每一个特殊的NPC写相应的爆炸,
子类实现不同的dead()方法,
在NPC父类中 添加:public abstract dead();
实现每个NPC不同的死亡效果,在每个子类中都添加。
在NPC0,1中添加public dead(){ for(let k = 0 ; k < 10 ; k ++){ this.nm.game.tm.create( 0, this.x + Math.random()*100 - 50 , this.y + Math.random()*100 - 50 , Math.floor(Math.random() * 5), 10,this.nm.game); } }
boss也是NPC,也得接受NPCManager的管理
创建BOSS0类class BOSS0 extends NPC{ public im:egret.Bitmap; public m:number; public t:number; public constructor(x:number,y:number,nm:NPCManager) { super(nm); this.x = x ;this.y = y; this.im = Main.createBitmapByName("boss50_png"); this.im.anchorOffsetX = this.im.width/2; this.im.anchorOffsetY = this.im.height/2; this.addChild(this.im); this.m = this.t = 0; this.hp = 1000; } public update(){ } public isHit(x:number,y:number):boolean{ return false; } public dead(){ } }
switch(this.m){ //boss停的位置 case 0: this.y+=10; if(this.y >= 150){ this.t = 20 ; this.m = 1; } break; //等待状态 case 1: this.t--; if(this.t <=0){ this.m = 10; this.t = 0 ; } break; //发射子弹 case 10: this.t++; //每隔3次主循环发射一颗 if(this.t % 3 == 0 ){ for(let i = 0 ; i < 5 ; i++){ //5串子弹 //160+i*10 间隔10度发一颗 this.nm.game.nzm.create(1, this.x, this.y, 10 ,160+i*10,this.nm.game ); } } if(this.t >= 20){ this.t = 10; this.m = 1; } break; }
//发射子弹case 10: this.t++; //每隔3次主循环发射一颗 if(this.t % 3 == 0 ){ for(let i = 0 ; i < 36 ; i++){ //5穿子弹 //160+i*10 间隔10度发一颗 this.nm.game.nzm.create(1, this.x, this.y, 10 ,160+i*10,this.nm.game ); } } if(this.t >= 20){ this.t = Math.random()* 20 + 10; this.m = 1; } break;
case 11: this.t++; //随着t的++,发射子弹的角度不断变化 this.nm.game.nzm.create(1, this.x, this.y, 10 ,180+this.t*10,this.nm.game ); //逆时针转 this.nm.game.nzm.create(1, this.x, this.y, 10 ,180 - this.t*10,this.nm.game ); //顺时针转 //子弹发射跟t有关联 间隔10度发一颗 if(this.t >= 36){ this.t = Math.random()* 20 + 10; this.m = 1; } break;
case 12: this.t++; //每10次主循环中15,16,17,18,19发射子弹 5颗 if(this.t % 20 > 14){ for(let i = 0 ; i < 5 ; i++){ //间隔20度打一排,从130度开始打5颗, //每十次主循环是一波,this.t/10,前十次结果为10,11,12,13结果为1,取整*20就是每波的距离 this.nm.game.nzm.create(1,this.x,this.y,10,Math.floor(this.t/20)*20 +130+i*5,this.nm.game ); //135度左右打5颗, } } if(this.t >= 100){ this.t = Math.random() * 20 + 10; this.m =1 ; } break;
后发先至效果
case 13: this.t++; //速度随着时间增加,产生后发先至效果 this.nm.game.nzm.create( 1, this.x - 50, this.y, 6 + this.t *2 ,190 - this.t,this.nm.game ); this.nm.game.nzm.create( 1, this.x+50, this.y, 6 + this.t *2 ,170 + this.t,this.nm.game ); if(this.t >= 10){ this.t = Math.random() * 20 + 10; this.m =1 ; } break;
NZDManager将角度参数设为缺省值 n?:numbe。 若不赋值,值为空。
代码为:
在NZDManager中
//如果n角度是空的,就是没有赋值 if(!n){ n = Math.atan2(this.game.player.x - x,y - this.game.player.y); //注意:三角函数算出的都是弧度制,还需要弧度制转换角度制 n = n * 180/Math.PI; }
//朝向型子弹 case 14 : this.t++; //打5团,每10次主循环打一组, if(this.t % 10 > 4){ this.nm.game.nzm.create( 1, this.x - 50, this.y, 15); } if(this.t >= 50){ this.t = Math.random() * 20 + 10; this.m =1 ; } break;
在等待状态case1中 this.m = Math.floor(Math.random() * 5 ) + 10; //随机类型子弹四.不规则图形的碰撞
图片宽 146 高 166 各中心点 73,83像素
if(Math.abs(x - this.x ) < 45 && Math.abs(y - this.y )< 82){ return true; }
if(Math.abs(x - this.x) < 73 && Math.abs(y -(this.y + 44)) < 36){ return true; }
至此,第五天的开发笔记已经完成,学习需要坚持,坚持到最后一定会有结果,每天写下笔记来记录自己的学习内容, 以后有需要也可以查看,大家可以一起学习。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算