【自己搭建小游戏(JS)】----CocosCreator -飞机大战(详细教程)
程序员文章站
2022-03-21 13:11:53
helloworld 练习...
前言
helloworld 练习
一、CocosCreator
Cocos是由触控科技推出的游戏开发一站式解决方案,包含了从新建立项、游戏制作、到 打包上线的全套流程。开发者可以通过cocos快速生成代码、编辑资源和动画,最终输出适合于多个平台的游戏产品。
下载地址
- 安装
- 登录
Demo练习
-测试
二、飞机大战
- 经典布局
- 更改画布尺寸
- 创建文件夹,专门放图片
- 然后打开我们新建文件夹的路径,然后把我们需要的文件添加到里面去:
- 创建精灵
【选择渲染节点】-创建精灵
- 修改名称
- 运行效果图:
图片素材地址
https://download.csdn.net/download/qq_32370913/12628907
图片合成工具
https://www.codeandweb.com/texturepacker
- 然后把生成文件,放到我们的编辑器里面
- 拖入
- 拖入
- 添加飞机小精灵
1.飞机屏幕骚动起来—添加游戏轮播背景
- 创建文件夹,添加脚本
- 关联脚本工具
https://code.visualstudio.com/
- 然后双击我们的脚本
- 项目使用我们的脚本
-如果实现不了上面的步骤,可以这样操作:
选择【用户脚本组件】-【我们想添加的脚本组件的名称】
- 开始浏览,然后通过F12查看内容
- 声明组件
在js脚本中声明我们的组件,使我们背景图进行骚动起来
- js里面的内容,xy,相当于
拷贝背景图
cc.Class({
extends: cc.Component,
properties: {
bg_1:cc.Node,
bg_2:cc.Node,
},
onLoad(){
this.bg_1.y = 0
this.bg_2.y = this.bg_1.y + this.bg_1.height
},
start () {
cc.log("开始")
},
//项目启动以后每秒进行运行
update(dt){
this.bg_1.y=this.bg_1.y-1
this.bg_2.y= this.bg_2.y-1
if(this.bg_1.y <= -this.bg_1.height/2){
this.bg_1.y = this.bg_2.y + this.bg_1.height
}
if(this.bg_2.y <= -this.bg_2.height/2){
this.bg_2.y = this.bg_1.y + this.bg_1.height
}
}
});
2.添加游戏Logo
- 添加文件夹,单独存放不同节点内容
- 创建文字渲染节点 label
- 修改颜色
- 添加动画
- 然后添加组件
选择其他组件
3.添加触摸事件
- 控制游戏背景图,开始进入时不动
cc.Class({
extends: cc.Component,
properties: {
bg_1:cc.Node,
bg_2:cc.Node,
},
onLoad(){
//控制游戏界面不动
this.isBgMove=false
this.bg_1.y = 0
this.bg_2.y = this.bg_1.y + this.bg_1.height
},
start () {
cc.log("开始")
},
setBg:function(){
this.bg_1.y=this.bg_1.y-1
this.bg_2.y= this.bg_2.y-1
if(this.bg_1.y <-this.bg_1.height){
this.bg_1.y = this.bg_2.y + this.bg_1.height
}
if(this.bg_2.y < -this.bg_2.height){
this.bg_2.y = this.bg_1.y + this.bg_1.height
}
},
//项目启动以后每秒进行运行
update(dt){
if(this.isBgMove){
this.setBg()
}
}
});
- 实现点击屏幕,隐藏logo与“点击游戏几个字”
- 编辑器添加node节点关联
4.添加暂停按钮
- 添加空节点
- 添加按钮 --添加UI节点–按钮
- 效果图:
- 填写参数
5.添加暂停界面
- 创建新的空节点
- 创建渲染节点-单色节点
- 创建UI节点 --按钮节点
- 添加按钮图片
- 修改尺寸
- 给每个按钮添加事件:
- 为背景图添加,组件,控制图层
6.各界面之间的切换
-单词写错
7.添加飞机和飞机的动画
- 创建精灵
- 创建飞机动画
- 添加组件
8.创建预制资源字段
- 添加精灵
- 创建子弹脚本:
在game中生成子弹,必须保持子弹始终在飞机的上面。
然后把子弹精灵,当成预制的资源。
然后在我们的gam里面声明我们的子弹:
9.用对象池创建子弹
- 修改子弹、飞机、背景图的层级关系
10.声明游戏的不同状态
11.移除子弹
12.添加广告
- 创建精灵
- 创建文件夹
- 创建按钮,进行关闭广告
- 设置九空格
- 编写脚本,挂到我们的广告图上面
- 点击广告关闭,跳转到我们的游戏界面
cc.Class({
extends: cc.Component,
properties: {
label_num:cc.Label,
},
onLoad () {
this.timeNum=5
this.label_num.string = this.timeNum
this.schedule(function(){
this.timeNum--
this.label_num.string = this.timeNum
if(this.timeNum == 0 ){
this.goToGame()
}
},1)
},
goToGame:function(){
cc.director.loadScene("plane")
},
update (dt) {},
});
13.创建敌机
- 创建精灵
- 把脚本挂载到精灵上面
- 在game里面声明,敌机,声明对象池
14.子弹与敌机碰撞
- 添加飞机碰撞组件
- 添加子弹碰撞组件
- 在项目设置中添加分组,实现组件碰撞
cc.Class({
extends: cc.Component,
properties: {
bg_1:cc.Node,
bg_2:cc.Node,
gameReady:cc.Node,
gamePlaying:cc.Node,
gamePause:cc.Node,
gameOver:cc.Node,
hero:cc.Node,
pre_bullet:cc.Prefab,
pre_enemy_1:cc.Prefab,
pre_enemy_2:cc.Prefab,
pre_enemy_3:cc.Prefab,
lab_score:cc.Label,
lab_bestScore:cc.Label,
bgm:cc.AudioClip,
soundDieEnemy:cc.AudioClip,
soundDieHero:cc.AudioClip,
},
onLoad () {
window.game = this
// 开启碰撞检测系统,未开启时无法检测
cc.director.getCollisionManager().enabled = true;
//cc.director.getCollisionManager().enabledDebugDraw = true;
this.isBgMove = false
this.bg_1.y = 0
this.bg_2.y = this.bg_1.y + this.bg_1.height
this.setTouch()
this.gameReady.active = true
this.gamePlaying.active = false
this.gamePause.active = false
this.gameOver.active = false
this.gamePause.zIndex = 2
this.gameOver.zIndex = 2
this.bulletTime = 0
this.enemyTime = 0
this.bulletPool = new cc.NodePool()
this.enemyPool_1 = new cc.NodePool()
this.enemyPool_2 = new cc.NodePool()
this.enemyPool_3 = new cc.NodePool()
this.gameType = 0//(0:ready,1:playing,2:pause,3:over)
this.randomNUm = [60,90,100]
this.scoreNum = 0
this.bestScoreNum = cc.sys.localStorage.getItem('bestScore_1')
if(this.bestScoreNum == null){
this.bestScoreNum = 0
}
this.addScore(0)
this.gameTime = 0
cc.audioEngine.play(this.bgm, true, 1);
},
setTouch:function(){
this.node.on('touchstart', function (event) {
console.log('touchstart')
if(this.gameType == 0){
this.gameType = 1
}
this.gameReady.active = false
this.gamePlaying.active = true
this.isBgMove = true
}, this)
this.node.on('touchmove', function (event) {
//console.log('touchmove')
var pos_hero = this.hero.getPosition()
var pos_move = event.getDelta()
var pos_end = cc.v2(pos_hero.x + pos_move.x,pos_hero.y + pos_move.y)
if(pos_end.x < -290){
pos_end.x = -290
}else if(pos_end.x > 290){
pos_end.x = 290
}
if(pos_end.y < -533){
pos_end.y = -533
}else if(pos_end.y > 533){
pos_end.y = 533
}
this.hero.setPosition(pos_end)
}, this)
this.node.on('touchend', function (event) {
console.log('touchend')
}, this)
},
addScore:function(score){
this.scoreNum = this.scoreNum + score
this.lab_score.string = this.scoreNum
if(this.bestScoreNum < this.scoreNum){
this.bestScoreNum = this.scoreNum
cc.sys.localStorage.setItem('bestScore_1', this.bestScoreNum)
}
this.lab_bestScore.string = this.bestScoreNum
},
playSoundEnemyDie:function(){
cc.audioEngine.play(this.soundDieEnemy, false, 1);
},
playSoundHeroDie:function(){
cc.audioEngine.play(this.soundDieHero, false, 1);
},
gameOverOver:function(){
this.gameOver.active = true
this.gamePause.active = false
},
clickBtn:function(sender,str){
if(str == 'pause'){
cc.log('点击了暂停按钮')
this.gameType = 2
this.gamePause.active = true
}else if(str == 'continue'){
cc.log('点击了继续按钮')
this.gameType = 1
this.gamePause.active = false
}else if(str == 'reStart'){
cc.log('点击了重新开始按钮')
this.gameTime = 0
this.scoreNum = 0
this.addScore(0)
this.gameType = 1
this.gameOver.active = false
this.gamePause.active = false
this.removeAllBullet()
this.removeAllEnemy()
this.hero.setPosition(cc.v2(0,-350))
var js = this.hero.getComponent('hero')
if(js){
js.init()
}
}else if(str == 'backHome'){
cc.log('点击了返回主页按钮')
this.gameTime = 0
this.scoreNum = 0
this.addScore(0)
this.gameType = 0
this.gameOver.active = false
this.gamePause.active = false
this.gamePlaying.active = false
this.gameReady.active = true
this.isBgMove = false
this.removeAllBullet()
this.removeAllEnemy()
this.hero.setPosition(cc.v2(0,-350))
var js = this.hero.getComponent('hero')
if(js){
js.init()
}
}
},
setBg:function(){
this.bg_1.y = this.bg_1.y - 2
this.bg_2.y = this.bg_2.y - 2
if(this.bg_1.y <= -this.bg_1.height){
this.bg_1.y = this.bg_2.y + this.bg_1.height
}
if(this.bg_2.y <= -this.bg_1.height){
this.bg_2.y = this.bg_1.y + this.bg_1.height
}
},
creatBullet:function(){
let bullet = null;
if (this.bulletPool.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
bullet = this.bulletPool.get();
} else { // 如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建
bullet = cc.instantiate(this.pre_bullet)
}
bullet.parent = this.node
var pos = this.hero.getPosition()
bullet.setPosition(cc.v2(pos.x,pos.y + this.hero.height / 2 + 5))
},
createnemy:function(enemyType){
let enemy = null
var str = ''
var pos_enemy = cc.v2(0,0)
if(enemyType == 1){//创建敌机1
if (this.enemyPool_1.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
enemy = this.enemyPool_1.get();
} else { // 如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建
enemy = cc.instantiate(this.pre_enemy_1)
}
str = 'enemy_1'
pos_enemy.x = -320 + Math.random() * 640
pos_enemy.y = 666 + Math.random() * 200
}else if(enemyType == 2){//创建敌机2
if (this.enemyPool_2.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
enemy = this.enemyPool_2.get();
} else { // 如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建
enemy = cc.instantiate(this.pre_enemy_2)
}
str = 'enemy_2'
pos_enemy.x = -320 + Math.random() * 640
pos_enemy.y = 666 + Math.random() * 200
}else if(enemyType == 3){//创建敌机3
if (this.enemyPool_3.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
enemy = this.enemyPool_3.get();
} else { // 如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建
enemy = cc.instantiate(this.pre_enemy_3)
}
str = 'enemy_3'
pos_enemy.x = -300 + Math.random() * 600
pos_enemy.y = 740 + Math.random() * 200
}
enemy.parent = this.node
var js = enemy.getComponent(str)
if(js){
js.init()
}
enemy.setPosition(pos_enemy)
},
onBulletKilled: function (bullet) {
// enemy 应该是一个 cc.Node
this.bulletPool.put(bullet); // 和初始化时的方法一样,将节点放进对象池,这个方法会同时调用节点的 removeFromParent
},
onEnemyKilled: function (enemy,enemyType) {
if(enemyType == 1){
this.enemyPool_1.put(enemy)
}else if(enemyType == 2){
this.enemyPool_2.put(enemy)
}else if(enemyType == 3){
this.enemyPool_3.put(enemy)
}
},
removeAllBullet:function(){
var children = this.node.children
for (let i = children.length - 1; i >= 0; i--) {
var js = children[i].getComponent('bullet')
if(js){
this.onBulletKilled(children[i])
}
}
},
removeAllEnemy:function(){
var children = this.node.children
for (let i = children.length - 1; i >= 0; i--) {
if(children[i].getComponent('enemy_1')){
this.onEnemyKilled(children[i],1)
}else if(children[i].getComponent('enemy_2')){
this.onEnemyKilled(children[i],2)
}else if(children[i].getComponent('enemy_3')){
this.onEnemyKilled(children[i],3)
}
}
},
update (dt) {
if(this.isBgMove){
this.setBg()
}
var randomNumEnemy = 5
if(this.gameType == 1){
this.gameTime++
if(this.gameTime % 300 == 0){
randomNumEnemy = randomNumEnemy + Math.round(this.gameTime / 300)
if(randomNumEnemy > 20){
randomNumEnemy = 20
}
this.randomNUm[0] = this.randomNUm[0] - 2
this.randomNUm[1] = this.randomNUm[1] - 1
if(this.randomNUm[0] < 40){
this.randomNUm[0] = 40
}
if(this.randomNUm[1] < 75){
this.randomNUm[1] = 75
}
}
}
this.bulletTime++
if(this.bulletTime == 8){
this.bulletTime = 0
if(this.gameType == 1){
this.creatBullet()
}
}
this.enemyTime++
if(this.enemyTime == 120){
this.enemyTime = 0
var num_random = Math.floor(Math.random() * randomNumEnemy) + 1
for (let i = 0; i < num_random; i++) {
if(this.gameType == 1 || game.gameType == 3){//playing
var num = Math.random() * 100
if(num < this.randomNUm[0]){
this.createnemy(1)
}else if(num < this.randomNUm[1]){
this.createnemy(2)
}else if(num < this.randomNUm[2]){
this.createnemy(3)
}
}
}
}
cc.log(this.node.children.length)
},
});
本文地址:https://blog.csdn.net/qq_32370913/article/details/107401037