Cocos Creator游戏之FiyBird(二)

1

今天进行代码的编写。

ps:因为本人也是初学者,所以步骤会有些繁杂希望大家不要在意,旨在能够学习CocosCreaor!

------------------------------------------------------------我是一只分割线------------------------------------------------------------

1.先进行地板轮播移动

创建一个名为GameData的脚本类(本人习惯把一些常用数值写在一个全局类中,方便以后在其他脚本进行调用)

脚本中编写

//这个类类似单例
cc.GAMEDATA= cc.GAMEDATA || {};
//地板移动时间间隔
cc.GAMEDATA.GROUND_MOVE_INTERVAL = 0.05;
//地板单位时间内移动的偏移量
cc.GAMEDATA.GROUND_MOVE_SPEED = 5;

创建Main脚本,这个也会是我们之后的主脚本。

编写Main脚本

(1)

properties: {
        ground0:cc.Node,
        ground1:cc.Node,
    },

这里偷个懒没有用正规的声名格式qaq  声名两个地板。

(2)

 //地板移动
     onGroundMove:function(){
        this.ground0.x -= cc.GAMEDATA.GROUND_MOVE_SPEED; //让地板朝着x轴-=5的偏移量
        this.ground1.x -= cc.GAMEDATA.GROUND_MOVE_SPEED;//让地板朝着x轴-=5的偏移量
        //通过判断ground0和ground1的x轴和宽的一半与背景节点一半比较来赋值位置
        if(this.ground0.x+this.ground0.width/2 < -this.node.width/2){
            this.ground0.x = this.ground1.x+this.ground0.width
        }
        if(this.ground1.x+this.ground1.width/2 < -this.node.width/2){
            this.ground1.x = this.ground0.x+this.ground0.width
        }
    },

在onLoad里使用计时器进行调用

 onLoad () {
         //启动地板移动的计时器  每0.05秒执行一次this.onGroundMove方法
        this.schedule(this.onGroundMove,cc.GAMEDATA.GROUND_MOVE_INTERVAL)
    },

ps:这里用到了计时器,大家可以点击链接查看官方解释:官方计时器

最后要记得去引擎中给两个地板赋值

效果图:

2.制作小鸟的运动动画

(1)设置全局数值

//小鸟下落时间间隔

cc.GAMEDATA.BRID_DROP_INTERVAL =0.02;

//小鸟加速度

cc.GAMEDATA.BRID_DROP_ACC =0.5;

//小鸟的弹跳值

cc.GAMEDATA.BRID_JUMP_VALUE =-6.6;

(2)创建Bird脚本编写如下:

cc.Class({
    extends: cc.Component,

    properties: {
        
    },


    // onLoad () {},

    start () {
        this.speed =0;
    },
    
    startDrop(){ 
        //开启计时器 每0.02秒运行一次onDrop方法
        this.schedule(this.onDrop,cc.GAMEDATA.BRID_DROP_INTERVAL);
    },
    onDrop(){
        //赋值速度给node.y
        this.speed +=cc.GAMEDATA.BRID_DROP_ACC;
        this.node.y -=this.speed;

    },
    onJump(){
        //小鸟的移动力度
        this.speed =cc.GAMEDATA.BRID_JUMP_VALUE;
    },
    stop(){
        //关闭计时器
        this.unschedule(this.onDrop);
        this.getComponent(cc.Animation).stop("fly");//动画帧停止
    }

    // update (dt) {},
});

并添加在Bird节点身上

Main脚本中编写如下:

 properties: {
        ground0:cc.Node,
        ground1:cc.Node,
         //声明小鸟对象 
        bird:cc.Node,
        //声名当前分数
        scoreLabel : cc.Label,
        //声明最高分
        highScoreLabel:cc.Label,
        //声名开始按钮
        beginBut :cc.Button,
        //声明返回按钮
        quitBut:cc.Button,
        //声名Logo
        logo:cc.Node,
        //音效
        jumpAudio:cc.AudioSource
    },

在onLoad中编写:

 onLoad () {
        this.score =0;//辅助计分
        this.quitBut.node.active =false;
        this.scoreLabel.node.active =false;
         //启动地板移动的计时器  每0.05秒执行一次this.onGroundMove方法
        this.schedule(this.onGroundMove,cc.GAMEDATA.GROUND_MOVE_INTERVAL)
    },

添加onButtonClick开始游戏方法并进行绑定:

 //开始游戏
    onButtonClick(event,customData)
    {
        this.logo.active =false;//logo隐藏
        this.highScoreLabel.node.active =false;//最高分隐藏
        this.beginBut.node.active =false;//开始按钮隐藏
        this.scoreLabel.node.active =true;//当前分数显示
        this.scoreLabel.string =this.score;//辅助得分赋值给当前分数
        //给背景添加触摸事件 点击屏幕小鸟飞
        this.node.on("touchstart",function(){
            this.bird.getComponent("Bird").onJump();//调用bird身上脚本中的跳跃方法
            this.jumpAudio.play();//播放音效
        }.bind(this));
        //小鸟下掉
        this.bird.getComponent("Bird").startDrop(); //this.bird.startDorp();
    },

效果图:

(3)管道生成及小鸟得分

创建管道预制件:

GameData中添加如下:


//管道缝隙的最小值
cc.GAMEDATA.PIPE_MIN_GAP =100;
//管道缝隙的最大值
cc.GAMEDATA.PIPE_MAX_GAP =200;
//管道组合的最低位置
cc.GAMEDATA.PIPE_MIN_OFFSETY =-140;
//管道组合的最高位置
cc.GAMEDATA.PIPE_MAX_OFFSETY =80;
//管道生成的时间间隔
cc.GAMEDATA.PIPE_CREATE_INTERVAL = 1.5;
//返回指定范围内的随机数 m - n  
cc.GAMEDATA.getRandombyRange = function(min,max)
{
    return parseInt(Math.random() * (max - min +1) + min);
};

ps:关于随机数Math.random() * (max - min +1) 请移步我的另一篇文章

parseInt是将将字符串转换为整数

Main脚本中写管道生成方法:

先声明预制件:

 //声明管道预制件
        pipePrefab:cc.Prefab,

拖动预制件到声明处:

 

创建生成方法:

 //管道生成
    createrPipe()
    {
        //实例化一个预制件
        let pipe = cc.instantiate(this.pipePrefab);
        this.node.addChild(pipe);
        pipe.getComponent("Pipe").init(this);//把this传递过去
        this.ground1.zIndex = pipe.zIndex+1;
        this.ground2.zIndex = pipe.zIndex+1 ;
        this.goback.node.zIndex = pipe.zIndex+1;
    },

在开始按钮事件中调用生成方法:

 //开始游戏
    onButtonClick(event,customData)
    {
        this.logo.active =false;//logo隐藏
        this.highScoreLabel.node.active =false;//最高分隐藏
        this.beginBut.node.active =false;//开始按钮隐藏
        this.scoreLabel.node.active =true;//当前分数显示
        this.scoreLabel.string =this.score;//辅助得分赋值给当前分数
        //给背景添加触摸事件 点击屏幕小鸟飞
        this.node.on("touchstart",function(){
            this.bird.getComponent("Bird").onJump();//调用bird身上脚本中的跳跃方法
            this.jumpAudio.play();//播放音效
        }.bind(this));
        //小鸟下掉
        this.bird.getComponent("Bird").startDrop(); //this.bird.startDorp();
         //启动管道生成计时器
        this.schedule(this.createrPipe,cc.GAMEDATA.PIPE_CREATE_INTERVAL);
    },

创建Pipe脚本并绑定在预制件上:

编写Pipe脚本:

  properties: {
        g1:cc.Node,//两根管道
        g2:cc.Node,   
    },

 在start中设置移动、间隙、位置

start () {
        //获取小鸟节点
        this.bird =cc.find("Canvas/Background/bird");
        //生成间隙
        this.g1.y =cc.GAMEDATA.getRandombyRange(cc.GAMEDATA.PIPE_MIN_GAP,cc.GAMEDATA.PIPE_MAX_GAP);
        //生成位置
        this.node.y=cc.GAMEDATA.getRandombyRange(cc.GAMEDATA.PIPE_MIN_OFFSETY,cc.GAMEDATA.PIPE_MAX_OFFSETY);
        //管道移动
        this.schedule(this.onPipeMove,cc.GAMEDATA.GROUND_MOVE_INTERVAL);
        //防止分数一直加而设置标签
        this.ispass =false;
    },

 用于传参

init(par)
    {
        this.par = par;
    },

创建管道移动方法

 //管道移动
    onPipeMove()
    {
        if(this.par.isGameOver)
        {
            this.unschedule(this.onPipeMove);
        }
        this.node.x -= cc.GAMEDATA.GROUND_MOVE_SPEED;
    },

GameData里使用缓存来保存最高分数

//设置最高分数
cc.GAMEDATA.setHighScore= function(score){
    cc.sys.localStorage.setItem("flabby_bird23",score);//把分数保存在本地文件
}
//从本地文件夹获取最高记录
cc.GAMEDATA.getHighScore= function(){
    let highScore = cc.sys.localStorage.getItem("flabby_bird23") || 0;
    return Number(highScore);
}

 用户存储可以分为缓存和json,本文用的是缓存数据。存储官方已有很明确的案例

Main脚本中编写得分和游戏结束

//游戏结束 
gameOver(){
        this.isGameOver = true;
        this.bird.getComponent("Bird").stop();
        this.unschedule(this.onGroundMove);//关闭地板移动计时器
        this.unschedule(this.createrPipe);//关闭管道生成计时器
        //把按钮活动属性设为真
        this.goback.node.active=true;
        if(this.score>this.highScore)//如果当前分数大于最高分数
        {
            cc.GAMEDATA.setHighScore(this.score);//保存分数为最高分
        }
    },

  //得分
    addscore()
    {
        this.score +=1;
        this.scoreLab.string =this.score;
    },

在update中对底板和小鸟的检测

 update (dt) {
        if(this.isGameOver)return;
        if(this.bird.y - this.bird.height/2 <= this.ground1.y+this.ground1.height/2)
        {
            this.bird.y =this.ground1.y+this.ground1.height/2 +this.bird.height/2;
            this.gameOver();
        }
    },

返回界面按钮

 //返回界面
    gojiemian()
    {
        cc.director.loadScene("game");//返回加载场景
    },

最后最后最后是在Pipe脚本中的Update中对管道和小鸟的碰撞检测;

update (dt) {
        if(this.par.isGameOver) return;
        let pipeUpBox = this.g1.getBoundingBoxToWorld();
        let pipeDownBox = this.g2.getBoundingBoxToWorld();
        let birdBox = this.bird.getBoundingBoxToWorld();
        if(pipeUpBox.intersects(birdBox)|| pipeDownBox.intersects(birdBox))
        {
            this.par.gameOver();
        }
        if(pipeUpBox.x+pipeDownBox.width< birdBox.x &&!this.ispass)
        {
            this.par.addscore();
            this.ispass =true;
        }
    
    },

ps:flyBird物体之间的碰撞我用的是包围盒进行检测的。具体包围盒用法请参考官方api:https://docs.cocos.com/creator/api/zh/classes/Node.html#getboundingboxtoworld

intersects 是用来判断当前矩形与指定矩形是否相交。api用法

最终游戏效果:

如果有对代码更好的建议请告知谢谢!共同学习!

猜你喜欢

转载自blog.csdn.net/qq_40303068/article/details/89150513