Egret实战开发笔记,飞行射击游戏(六)
今天是开发飞行射击游戏第五天,玩家多类型子弹及状态和关卡模式。
简介
实现玩家特殊子弹,激光,追踪导弹。
玩家多状态 下方飞出 正常游戏 胜利等待 胜利飞出 以及
玩家保护 和 关卡切换
实现效果
本来想录视频转GIF的,但是gif文件过大,超过5M又上传不了,而且压缩后失帧严重,仅截取了一部分转为gif, 请大家原谅。
一.激光
ZD类中
正常的子弹按照自己的轨迹运动,激光每次跟着玩家运动。激光的轨迹不是沿着自己的轨迹,而是在玩家移动的基础上有一个偏移坐标。即子弹跟着玩家移动。
需要一个属性:dx,dy
public dx:number;
public dy:number; //玩家坐标基础上的偏移值
public static fi:number = 0 ; //激光的动画帧
//激光类型
case 10://用动画帧构造图片this.im = Main.createBitmapByName("pzd4"+ZD.fi+"_png");//每发射一颗子弹 就加一张ZD.fi++; if(ZD.fi >= 10) ZD.fi = 0;this.addChild(this.im);//每次主循环发射一颗,每颗间距离是80this.vy = -80; //-80为向上this.vx = 0 ;this.dx = this.dy = 0 ;this.n = 0;this.gj = 10;break;
更新update():
//特殊的更新需要放在前面,进去直接更新,更新完return跳出结束更新
if(this.id == 10){//移动的是它和飞机之间的差值this.dx +=this.vx;this.dy +=this.vy;//偏移值:基础值+偏移//激光的坐标是在玩家坐标基础上加上改变值,移动的是改变值。这样就实现激光跟随玩家移动this.x = this.game.player.x + this.dx;this.y = this.game.player.y + this.dy;//出屏检测 if(this.y < -100 ){this.vis = false;}return;
}
什么叫偏移?
对激光来说移动的不是自己的坐标,而是移动和飞机之间的距离,是偏移值,而不是实际坐标
二.跟踪子弹的实现
实现效果
跟朝向型子弹不同。朝向子弹是NPC发的,发射时已经算好了子弹位置和玩家的位置,直接朝向玩家发射,子弹是直线型。
跟踪子弹是玩家发射的,找到NPC,根据NPC角度和坐标和自身的角度算出一个玩家该朝向的角度,而算出角度后,根据目前的角度和该朝向角度的差值进行移动。比如玩家是90度,实际要0度才能达到,并不是直接从90度变为0度,而是90.80,70,。。一个弧形,依次递减到需要朝向的角度。
1)NPC的选取:
需要选择屏幕当中的一个NPC,如果有就跟踪,如果没有就是竖直向上.
在NPCManager中
//获取NPC
public getNPC():NPC{//仓库长度>0说明有NPC,如果没有跳出if(this.nm.length > 0 ){//有npc 随机取一个npc。let npc = this.nm[Math.floor(Math.random()* this.nm.length)]//判断npc是否在屏幕内,满足条件在屏幕内if(npc.x > 0 && npc.x < 480 && npc.y > 0 && npc.y < 800){return npc;}}//没找到 为空return null;
}
2)计算打到NPC的角度
3)更新角度的改变打到NPC
申请
public npc:NPC; //追踪的目标
//跟踪导弹case 20:this.im = Main.createBitmapByName("pzd1_3_png");this.npc = null; break;
更新update()
//特殊的更新需要放在前面,进去直接更新,更新完return跳出结束更新
if(this.id == 20){let bn = 0 ; //目标角度 向上if(this.npc == null){this.npc = this.game.nm.getNPC();}else{bn = Math.atan2(this.npc.x -this.x,this.y-this.npc.y);//这个角度是弧度制,转换成角度值bn = bn * 180/ Math.PI;}
//N角度限制在 -180°~180°
while(this.n <= -180)this.n += 360;
while(this.n > 180)this.n -= 360;
//若角度差值小于5度,两个角度变为等值
if(Math.abs(this.n - bn) < ZD.VN){this.n = bn;}else{//if(this.n < bn){if(this.n < bn - 180)this.n -= ZD.VN;elsethis.n += ZD.VN;}else{if(this.n > bn + 180)this.n += ZD.VN;else this.n -= ZD.VN;}
}
//sin用的是弧度制 n是角度制,所以 n* Math.PI / 180 转换为弧度制。
//重新计算速度与角度
this.vx = this.v * Math.sin(this.n * Math.PI / 180);
this.vy= -this.v * Math.cos(this.n * Math.PI / 180);
this.im.rotation = this.n;this.x +=this.vx;
this.y +=this.vy;
//出屏检测
if(this.x < -100 || this.x > 580 || this.y < -100 || this.y > 900){this.vis = false;
}
return;
}
注意:反三角函数求出的角度是 -180°180°,不是0°360°
将n角度从0°~360°转换为 -180°~ 180°
while(this.n <= -180)this.n += 360;
while(this.n > 180)this.n -=360;
在Player类中 fire方法
//追踪导弹
this.t++;
if(this.t >= 10){this.game.zm.create(20,this.x,this.y,15,135,this.game);this.game.zm.create(20,this.x,this.y,15,-135,this.game);this.game.zm.create(20,this.x,this.y,15,45,this.game);this.game.zm.create(20,this.x,this.y,15,-45,this.game);this.t = 0 ;
}
53
三.玩家多状态
0 下方飞出
1 正常游戏
10 胜利等待
11 胜利飞出
在Player的更新update方法中
switch(this.m){case 0 :this.y -=this.v;if(this.y <= 400){this.m =1;this.t = 0 ;}break;case 1 :this.fire();this.movePlayer();break;case 10:this.t++;if(this.t >= 20){this.t = 0;this.m = 11;}break;case 11:this.y -=this.vy;this.vy +=3;if(this.y < -200){//游戏胜利的切换}break;}
整合movePlayer方法
将update方法中这段代码变为movePlayer方法
public movePlayer(){if(this.isDown == true ){let a = this.ny - this.oy;let b = this.nx - this.ox;let c = Math.sqrt(a*a + b*b);if( c > this.v){this.vx = this.v*b/c;this.vy = this.v*a/c;this.ox += this.vx;this.oy += this.vy;}else{this.vx = b;this.vy = a;this.ox = this.nx;this.oy = this.ny;}//飞机跟着速度一起移动this.x +=this.vx ;this.y +=this.vy ;//边界检测if(this.x < 0)this.x = 0;else if(this.x > 480)this.x = 480;if(this.y < 0)this.y = 0;else if(this.y > 800)this.y = 800;}else{this.vx = 0;}if(this.vx < 0 ){//向左飞:if(this.fi > -2)this.fi --;}else if(this.vx > 0){if(this.fi < 2)this.fi++;}else{this.fi = 0 ;}this.resetFI();}
在update方法中增加状态机
四.玩家的死亡处理
玩家中增加public isHit(x:number , y:number):boolean{}
public isHit(x:number , y:number):boolean{// this.x this.y是圆心, 60是半径 勾股定理 ,进入圆算碰撞。//两点间距离公式。横坐标差的平方+纵坐标差的平方再开方 if(this.bhT > 0 ){if((this.x -x )*(this.x -x ) + (this.y -y )*(this.y - y ) < 60*60){return true;}return false;}if(this.m !=1)return false;if(Math.abs(this.x - x) < 20 && Math.abs(this.y -y )<20){//玩家死亡return true; }return false;
}
增加
public dead(){for(let i = 0 ; i < 10 ; i++){ //环数let dn =Math.random()*Math.PI * 2;for(let j = 0 ; j < 15 ; j ++) //每个环爆炸个数 {this.game.tm.create(0,this.x + (i+1)*30* Math.sin(dn+Math.PI*2*j/15),this.y + (i+1)*30* Math.cos(dn+Math.PI*2*j/15),i,Math.random() * 10 +5,this.game);}}this.x = 240;this.y = 1000;this.m = 0 ;this.t = 0; }
五.增加玩家保护
申请public bh:egret.Bitmap; // 保护罩图片
public bhT:number; //保护罩倒计时 持续3秒
构造 this.bh.anchorOffsetX = this.bh.width/2;
this.bh.anchorOffsetY =this.bh.height/2;
this.addChild(this.bh);
this.bh.scaleX = this.bh.scaleY = 0.5;
this.bhT = 60; //60次主循环是3秒
更新;
//保护罩时间>0。减到0 消失,图片可见性为false
if(this.bhT > 0 ){this.bhT--;if(this.bhT <=0){this.bh.visible = false;}
}
在NZDManager类中的更新方法中修改
if(this.game.player.isHit(one.x , one.y) ==true ){one.vis = false;if(this.game.player.m == 1 && this.game.player.bhT <= 0 ){this.game.player.dead();} }
在玩家死亡方法最后添加
this.bhT = 60;
this.bh.visible = true;
六.玩家过关 与 关卡切换
BOSS0中添加死亡爆炸方法
public dead(){for(let i = 0 ; i < 10 ; i++){ //环数let dn =Math.random()*Math.PI * 2;for(let j = 0 ; j < 15 ; j ++) //每个环爆炸个数 {this.nm.game.tm.create(0,this.x + (i+1)*30* Math.sin(dn+Math.PI*2*j/15),this.y + (i+1)*30* Math.cos(dn+Math.PI*2*j/15),i,Math.random() * 10 +5,this.nm.game);}} this.nm.game.player.win();}
在Player中添加win方法
//通过关卡
public win(){this.t = 0 ; this.m = 10; //胜利 玩家飞出屏幕
}
2)关卡切换
Maingame中申请 public level:number; //判断当前关卡序号
构造:this.level = 0;
NPCManager中,不同的关卡生成不同的阵列。
对生成的switch进行状态机嵌套
在Maingame中添加
reset方法
public reset(level:number){this.level = level;this.player.reset();this.bg.reset();this.nm.reset();}
BG类中
public reset(){switch(this.game.level){case 0:for(let i = 0 ; i < 2; i ++){this.bg[i].texture = RES.getRes("bg11_jpg");}break;case 1:for(let i = 0 ; i < 2; i ++){this.bg[i].texture = RES.getRes("bg31_jpg");}break;}
}
NPCManager类中
//仓库中所有东西 移除
public reset(){//整个仓库长度 ,利用循环可以循环出所有子弹for(let i = 0 ; i < this.nm.length ; i++){//找到每颗子弹let one = this.nm[i];this.removeChild(one);this.nm.splice(i ,1);i--;}this.t =0;this.cID = 0;}
Player类中
public dead(){for(let i = 0 ; i < 10 ; i++){ //环数let dn =Math.random()*Math.PI * 2;for(let j = 0 ; j < 15 ; j ++) //每个环爆炸个数 {this.game.tm.create(0,this.x + (i+1)*30* Math.sin(dn+Math.PI*2*j/15),this.y + (i+1)*30* Math.cos(dn+Math.PI*2*j/15),i,Math.random() * 10 +5,this.game);}}this.x = 240;this.y = 700;this.m = 0 ;this.t = 0; this.bhT = 60;this.bh.visible = true;}
public reset(){this.isDown = false;this.x = 240;this.y = 1000;this.m = this.t = 0;this.bhT = 60; //60次主循环是3秒}
至此,第五天的开发笔记已经完成,学习需要坚持,坚持到最后一定会有结果,每天写下笔记来记录自己的学习内容, 以后有需要也可以查看,大家可以一起学习。
想要我一起学习的可以关注我的公众号 知言不尽 找到我,交流学习,获取图片素材和源代码。
Egret实战开发笔记,飞行射击游戏(六)相关推荐
- Egret实战开发笔记,飞行射击游戏(二)
简介 Egret实战开发,记录每天的学习进度,欢迎和我一起学习交流~ 目录 简介 实现目标 一.实现子弹类 二.工厂设计模式 三.子弹管理类ZDManager 实现目标 今天是开发飞行射击游戏第二天, ...
- html5 画飞机,飞行射击游戏像素画开发教程:怎么画飞机?
作者:Slynyrd 编译 | 三二 (转载请注明出处) 关注网易号:教你画像素画 想开发一个飞行射击游戏,怎么画飞机呢?飞行射击游戏大多有历史背景,我们选择德国在第一次世界大战中投入的飞机Fokke ...
- [air for ios] 三小时开发一个iOS飞行射击游戏
[air for ios] 三小时开发一个iOS飞行射击游戏 http://www.badyoo.com/index.php/2012/07/04/158/index.html 2012-07-04 ...
- 手把手教你开发一款IOS飞行射击游戏(完)
下面我们开始最后一篇文章,完成我们的飞行射击游戏. 有了前面的基础,相信现在你对Cocos2d的基本元素和编写技巧有了一定的了解,这回我们要接触的是场景切换,我们这回只列出部分代码,说明原理,给读者一 ...
- Android游戏开发之飞行射击类游戏原理实现(二十)
Android游戏开发之飞行射击类游戏原理实现 雨松MOMO原创文章如转载,请注明:转载至我的独立域名博客雨松MOMO程序研究院,原文地址:http://www.xuanyusong.com/arch ...
- 用javascript实现的纵版飞行射击游戏—《天机》
花了一个半月的时间用javascript完成了这款web版飞行射击游戏,游戏效果接近一般的客户端游戏,不过对机器的要求稍微高点点,主要是CPU,最好在1.5GHZ以上,不然可能会比较卡,支持IE.FF ...
- 飞行射击游戏的C++实现:一次课程作业
目录 目录 程序简介 程序亮点 程序结构 逻辑层fsObjecth 自定义数据类型 fsPoint Class 一些枚举类型 异常类型 fsInvalidInitializePointValExcep ...
- Android开发笔记(八十六)几个特殊的类
接口interface interface是一些功能的集合,但它只定义了对象必须实现的成员,而不包含成员的实现代码,成员的具体代码由实现接口的类提供.Android对接口的使用场景主要有三类:事件监听 ...
- 太空射击unity工程素材文件 飞机大战 飞行射击游戏源码(C#,Unity2019.2.4f1)素材+源码 最新写的,demo简单版本
飞机大战素材 太空大战unity工程文件 飞行射击游戏源码(C#,Unity2019.2.4f1)素材+源码 最新写的,demo简单版本 希望能对初学者提供帮助,代码根据教材以及out了的代码更新了, ...
最新文章
- 当老板说要把公司当家时,他在说...
- OpenCV学习(19) 细化算法(7)
- 查看源代码不方便?我有利器
- Codeforces Beta Round #12 (Div 2 Only)【未完结】
- 怎么在idea中找实现类
- 洛谷P4463:calc(dp、拉格朗日插值)
- 为什么Facebook的API以一个循环作为开头?
- 大学计算机规划教材数据与计算,大学计算机应用基础教程高等院校计算机科学与技术规划教材.ppt...
- wechat-app-mall — 微信小程序商城,微信小程序微店
- linux 自动运行.out,linux系统定时自动重启springboot项目
- 松下抛却Jungle掌机研发项目
- vue.js的学习中的简单案例
- 吴恩达深度学习笔记(十一)—— dropout正则化
- LFS6.3安装全过程(一)
- 如何用微观数据分析玩家流失
- 《应用时间序列分析:R软件陪同》——1.4 本书的内容
- PHP课程设计《PHP网上购物系统的设计与实现》
- Ocr答题辅助神器 OcrAnswerer4.x,通过百度OCR识别手机文字,支持屏幕窗口截图和ADB安卓截图,支持四十个直播App,可保存题库...
- 高三数学辅导:不等式、推理与证明
- 深度学习头像定位头像分割
热门文章
- WIN电脑,固定到任务栏的快捷方式 实际存储在电脑的位置
- 字体设计的概念、意义与原则
- 推荐软件7 taskbar numberer,结果get了WIN相关的快捷键
- 最强 OSERDES IP核使用详解;FPGA 结构分析 —— IO 并串转换资源 OSERDES
- 魔百和M401A刷入Armbian系统EMMC开启wifi
- data类型的Url格式:把小数据直接嵌入到Url中
- 2011考研数学二第(9)题——求极限
- 四大“瓶颈”制约石油石化电子商务
- 欢迎hua@XUST加入XU安全组!
- 数字 IC 技能拓展(26)浅谈可编程逻辑器件