美术素材请自行在网络上找资源或者自己绘制,我就是自己绘制的
下面部分代码与你使用的美术资源的图片大小是有关的,比如画面大小,请注意

调整canvas屏幕大小
拖入背景图片两张,方便上下拼接,将背景1调好位置后在背景1下创建空节点,再把空节点改名为bj拖出来把背景1背景2放在空节点的下面(这样校准点都在图片中央)。
背景1坐标为(0,0),将背景2的y坐标调成图片高度值
控制背景的脚本挂载到空节点上,记得删掉update前的注释符号
背景控制脚本:
update (dt) {
for(let bjNode of this.node.children){
bjNode.y -= 50 * dt;
if(bjNode.y < -850){
bjNode.y += 852 * 2;
}
//每帧移动50像素x时间间隔dt→每秒移动50像素
//当图片移动出屏幕时,使用代码把背景图移动到屏幕外的上方,做出无限循环效果,防止背景图播完显示黑色
}
}
拖入玩家角色,挂载脚本
玩家角色控制脚本:
const {ccclass, property} = cc._decorator;
@ccclass
export default class PlayerControl extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = 'hello';
@property(cc.Prefab)//创建预设体面板
bulletPre: cc.Prefab = null;
// LIFE-CYCLE CALLBACKS:
// onLoad () {}
start () {
//开启碰撞检测
cc.director.getCollisionManager().enabled = true;
this.node.on(cc.Node.EventType.TOUCH_MOVE,(event)=>{
this.node.setPosition(event.getLocation());
});
this.schedule(()=>{
//创建子弹,在这之前要先在玩家控制脚本上面写预设体面板并关联好子弹的预设体
//将子弹的父物体设置为当前的场景
let bullet = cc.instantiate(this.bulletPre);
bullet.setParent(cc.director.getScene());
bullet.x = this.node.x;
bullet.y = this.node.y + 140 ;
},0.5)
}
//使用箭头函数调用this.node
/*攻击,使用计时器(括号内共有四个参数,第一个 参数为函数,第二个参数为多长时间来一次,
第三个参数为当前重复几次,不给参数就是一直重复,第四个参数为多长时间开始第一次攻击)
例如后三个参数分别写0.5,100,0表示每隔0.5秒产生一个敌人,产生一百次,第一次从0开始调用(瞬间调用)*/
update (dt) {
cc.director.getCollisionManager().enabled = true;
}
}
//自制玩家死亡时的方法,玩家节点开启碰撞组件并把tag值设置为2
//注意!主角死亡的方法名的大小写应在敌人脚本和主角脚本中保持一致!
Yukadie(){
//获取主角节点中的精灵组件,加载主角受到攻击的图片
cc.loader.loadRes("youxiang2",cc.SpriteFrame,(err,res)=>{
this.node.getComponent(cc.Sprite).spriteFrame = res;
});
//4000毫秒后销毁,第一个空为销毁方法,第二个空为销毁时间,由于这是JavaScript提供的方法因此单位为毫秒
setTimeout(()=>{
this.node.destroy();
},4000);
//加载玩家死亡时的音效
let player:cc.AudioSource = this.getComponent(cc.AudioSource);
cc.loader.loadRes("yukajiao",cc.AudioClip,(res,clip)=>{
player.clip = clip;
player.play();
})
}
}
子弹控制脚本:
import DirenControl from "./DirenControl";
const {ccclass, property} = cc._decorator;
@ccclass
export default class ZidanControl extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = 'hello';
@property
speed:number = 800;
//创建速度面板
// LIFE-CYCLE CALLBACKS:
// onLoad () {}
start () {
}
update (dt) {
//设置子弹速度
this.node.y += this.speed * dt;
//销毁射出屏幕的子弹
if(this.node.y>820){
this.node.destroy();
}
}
//onCollisionEnter:开始碰撞,括号内为碰撞到的物体
//思路:子弹碰到敌人,先让敌人死亡,再销毁自己
//先把敌人碰撞体的tag值设置为1,方便判断
onCollisionEnter(other){
if(other.tag == 1){
//先销毁敌人,从敌人处获得敌人脚本中的die方法
other.getComponent(DirenControl).die();
//再销毁自己
this.node.destroy();
}
}
}
先给敌人设置碰撞,再给敌人挂载脚本
敌人控制脚本:
import PlayerControl from "./PlayerControl";
const {ccclass, property} = cc._decorator;
@ccclass
export default class DirenControl extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = 'hello';
//变量:是否死亡
isDie: boolean = false;
// LIFE-CYCLE CALLBACKS:
// onLoad () {}
start () {
}
update (dt) {
//确认敌人是否死亡,未死亡时敌人移动,出了屏幕就销毁,记得是两个等于号
if(this.isDie == false){
this.node.y -= 300*dt;
}
if(this.node.y < -850){
this.node.destroy();
}
cc.director.getCollisionManager().enabled = true;
}
onCollisionEnter(other){
if(other.tag == 2){
//先销毁玩家,从玩家处获得玩家脚本中的Yukadie方法
other.getComponent(PlayerControl).Yukadie();
//再销毁自己
this.node.destroy();
}
}
//自制敌人死亡的方法
die(){
this.isDie = true;
//获取敌人节点中的精灵组件,加载敌人受到攻击的图片
cc.loader.loadRes("siyecao2",cc.SpriteFrame,(err,res)=>{
this.node.getComponent(cc.Sprite).spriteFrame = res;
});
//300毫秒后销毁,第一个空为销毁方法,第二个空为销毁时间,由于这是JavaScript提供的方法因此单位为毫秒
setTimeout(()=>{
this.node.destroy();
},300);
//加载敌人死亡时的音效
let player:cc.AudioSource = this.getComponent(cc.AudioSource);
cc.loader.loadRes("xioaxuejiao",cc.AudioClip,(res,clip)=>{
player.clip = clip;
player.play();
})
}
}
为了生成更多敌人,先在敌人的层级下新建一个空节点,保证空节点和敌人的位置一致,然后把敌人往下方层级管理器中拖动变成预设体,再把敌人从层级管理器中删除(敌人默认不存在),新建一个控制敌人生成的脚本
控制敌人生成的脚本:
const {ccclass, property} = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = 'hello';
@property(cc.Prefab)
//在敌人控制节点的面板中与敌人的预设体相关联
enemyPre: cc.Prefab = null;
// LIFE-CYCLE CALLBACKS:
// onLoad () {}
start () {
/*每隔两秒创建一个敌机,2的单位是秒,如果2后面加上“,1”,则从循环调用变为只调用一次
和java提供的延时计时器setTimeout效果一致(但setTimeout单位为毫秒) */
this.schedule(()=>{
//创建敌人并把父物体设置为当前场景
let enemy = cc.instantiate(this.enemyPre);
enemy.setParent(cc.director.getScene());
enemy.y = this.node.y;
/*敌人的x轴位置要给一个随机数,random本身取值为0到1,因此要乘以400变为0-400像素
又比如要20-420的随机数,那就在400后加上一个“+20”*/
enemy.x= Math.random()*400;
},2);
}
// update (dt) {}
}
背景音乐:
将资源管理器中的背景音乐直接拖入层级管理器中,添加组件——其他组件——audiosource,将音乐拖入到clip中,并勾选loop以循环播放
前面提到的添加音效也需要在各自节点中添加audiosource组件并将音效拖入到clip中
按顺序做完后界面如下:

Resources文件夹下方的文件:

最后,构建并发布到windows环节:
1.先在cocos creator编辑器上方的菜单栏中选择项目——构建发布——windows
0.5输出的文件夹路径中不能包含空格
1.5在成功构建后,我选择编译按钮时报错,在日志栏给出了错误信息的地址
根据地址,记事本记录了如下信息:
Building mode: release
Building...
Required VS version : [2017]
Can't find correct Visual Studio's path in the registry.
原来是我没有安装visual studio2017,在这之前我编辑脚本使用的是vs codium
成功安装vs2017(在安装界面需要勾选c++桌面开发和c++游戏开发组件和windows 8.1SDK)后,成功编译
*在安装vs2017时遇到安装引导程序没有提示缺少对应的.NETFrame,但是在“稍等几分钟,正在下载”的进度条一直显示为0并且最终显示“无法下载应用程序,请检查Internet连接”时,可以参考我的另一篇文章《对于Visual studio社区版2017在线安装报错“无法下载应用程序,请检查Internet连接”的一种可能的解决办法》
2.编译成功后,在你选定的输出文件夹可以看到许多文件
注意:这里查看文件夹不是使用菜单栏中文件地址旁的“...”,那个是确定输出的文件夹,里面只能看到文件夹,很多生成的文件都看不到,需要在windows自己的资源浏览器中找到你选择的输出文件夹
并且从中找到Jsb-default——frameworks——runtime-src——proj.win32
里面有一个exe程序,那就是你生成的游戏
如果需要分享的话,只保留proj.win32文件夹即可运行游戏
但是每个人电脑情况千差万别,还是需要自己多研究
本文是一篇关于使用COCOS Creator2.4.9开发飞机大战游戏的学习笔记,详细介绍了从美术资源的准备,到背景、角色、敌人、音效的设置,再到游戏的构建和发布到Windows平台的全过程。在发布过程中遇到了Visual Studio 2017的安装问题,并提供了解决方案。

954

被折叠的 条评论
为什么被折叠?



