原创

Cocos Creator零基础游戏实战《左右跳》JS教程05-动态生成石头

本章简介

本章介绍使用Cocos Creator动态生成节点。我们来分析一下石头的生成逻辑。石头是左右随机生成,之间是连着的,机器人每次跳跃,会消失一块石头,同时生成一块石头,这些石头都是动态创建的。

创建存放石头的集合节点

我们动态生成的很多石头节点,需要添加在石头集合节点下面,所以要先创建石头集合节点boxList

file

因为石头不能超过屏幕,所以我们用Widget组件。

file

制作石头预制体

我们需要动态生成很多个石头,不可能手动去创建那么多石头,我们可以通过预制体来动态生成石头。制作预制体分四步。第一步把box图片拖放到Canvas下,会自动根据图片名称生成一个box节点

file

第二步绑定脚本,我们创建一个名为box的脚本

file

第三步把box脚本box节点绑定。

file

第四步把box节点拖放到textures下面,textures下面会生成一个名为box的预制体,然后删除box节点

file

声明石头集合和石头预制体

打开控制游戏逻辑的start脚本,添加声明。

properties: {
        l1: cc.Node, //左侧背景1
        l2: cc.Node, //左侧背景2
        r1: cc.Node, //右侧背景1
        r2: cc.Node, //右侧背景2
        speed: 50, //背景移动速度
        player: cc.Node, //机器人节点
        jump: true, //是否可以跳
        box: cc.Prefab,  //石头预制体
        boxList: cc.Node, //石头集合节点
},

引用石头集合和石头预制体

file

编写生成石头的方法

打开start脚本,创建一个生成石头的方法newBox。我们先生成一个石头。

newBox () {
        // 通过预制体复制出一个石头节点
        var newBox = cc.instantiate(this.box);
        // 把石头节点添加在石头集合节点
        this.boxList.addChild(newBox);
},

file

我们希望石头在机器人脚下,修改石头的坐标。

newBox () {
        // 通过预制体复制出一个石头节点
        var newBox = cc.instantiate(this.box);
        // 把石头节点添加在石头集合节点
        this.boxList.addChild(newBox);
        // 设置石头的坐标
        var x = this.player.x+0;
        var y = this.player.y-120;
        var position = cc.Vec2(x,y);
        newBox.setPosition(position);
},

file

生成第二个石头,我们的目标是想让石头在第一个石头的左侧或者右侧随机生成。我们先实现第二个石头在第一个石头左侧生成,因为要判断是第几个石头,所以在start脚本添加一个统计石头个数的属性boxCount

properties: {
        l1: cc.Node, //左侧背景1
        l2: cc.Node, //左侧背景2
        r1: cc.Node, //右侧背景1
        r2: cc.Node, //右侧背景2
        speed: 50, //背景移动速度
        player: cc.Node, //机器人节点
        jump: true, //是否可以跳
        box: cc.Prefab,  //石头预制体
        boxList: cc.Node, //石头集合节点
        boxCount:0, //石头个数
 },

如果是第二个石头,就是在上一个石头坐标的基础上微调,所以我们需要记住上一个石头的坐标。

 properties: {
        l1: cc.Node, //左侧背景1
        l2: cc.Node, //左侧背景2
        r1: cc.Node, //右侧背景1
        r2: cc.Node, //右侧背景2
        speed: 50, //背景移动速度
        player: cc.Node, //机器人节点
        jump: true, //是否可以跳
        box: cc.Prefab,  //石头预制体
        boxList: cc.Node, //石头集合节点
        boxCount:0, //石头个数
        boxWidth:121, //石头的宽
        boxHeight:117, //石头的高
        preBoxX: 0, //上一个石头的X坐标
        preBoxY: 0, //上一个石头的Y坐标
 },
newBox () {
        // 通过预制体复制出一个石头节点
        var newBox = cc.instantiate(this.box);
        // 把石头节点添加在石头集合节点
        this.boxList.addChild(newBox);
        // 设置石头的坐标
        var x = this.player.x+0;
        var y = this.player.y-120;
        var position = cc.Vec2(x,y);

        this.boxCount++;
        if(this.boxCount == 2){
            // 如果是第二个石头
            x = this.preBoxX - this.boxWidth/2;
            y = this.preBoxY + 100;
            var position = cc.Vec2(x,y);
        }

        // 记住上一个石头的坐标
        this.preBoxX = x;
        this.preBoxY = y;

        newBox.setPosition(position);
 },

初始化生成两个石头。

onLoad () {
        this.node.on(cc.Node.EventType.TOUCH_START,this.onTouchStart,this)
        // 获取重置触发坐标点
        this.triggerLY = -this.l1.height;
        this.triggerRY = -this.r1.height;
        for(var i=0;i<2;i++){
            this.newBox();
        }
},

file

同理在右侧生成。

newBox () {
        // 通过预制体复制出一个石头节点
        var newBox = cc.instantiate(this.box);
        // 把石头节点添加在石头集合节点
        this.boxList.addChild(newBox);
        // 设置石头的坐标
        var x = this.player.x+0;
        var y = this.player.y-120;
        var position = cc.Vec2(x,y);

        this.boxCount++;
        if(this.boxCount == 2){
            // 如果是第二个石头
            x = this.preBoxX + this.boxWidth/2;
            y = this.preBoxY + 100;
            var position = cc.Vec2(x,y);
        }

        // 记住上一个石头的坐标
        this.preBoxX = x;
        this.preBoxY = y;

        newBox.setPosition(position);

},

file

左边生成和右边生成都实现了,现在我们可以完成最终目标了,随机在两侧生成,我们可以用随机数Math.random(),随机选取大于等于 0.0 且小于 1.0 的值,小于等于0.5我们让在左侧生成,大于0.5我们让在右侧生成。初始化12个石头。

newBox () {
        // 通过预制体复制出一个石头节点
        var newBox = cc.instantiate(this.box);
        // 把石头节点添加在石头集合节点
        this.boxList.addChild(newBox);
        // 设置石头的坐标
        var x = this.player.x+0;
        var y = this.player.y-120;
        var position = cc.Vec2(x,y);

        this.boxCount++;
        var randD = Math.random();
        if(this.boxCount >= 2){
            // 如果是第二个石头
            if(randD <= 0.5){
                // 在左侧生成
                x = this.preBoxX - this.boxWidth/2;
            }else{
                // 在右侧生成
                x = this.preBoxX + this.boxWidth/2;
            }            
            y = this.preBoxY + 100;
            var position = cc.Vec2(x,y);
        }

        // 记住上一个石头的坐标
        this.preBoxX = x;
        this.preBoxY = y;

        newBox.setPosition(position);

},

file

我们发现有点小问题,机器人默认向左边,如果第二个石头在右边,我们正常应该机器人向右。

newBox () {
        // 通过预制体复制出一个石头节点
        var newBox = cc.instantiate(this.box);
        // 把石头节点添加在石头集合节点
        this.boxList.addChild(newBox);
        // 设置石头的坐标
        var x = this.player.x+0;
        var y = this.player.y-120;
        var position = cc.Vec2(x,y);

        this.boxCount++;
        var randD = Math.random();
        if(this.boxCount >= 2){
            // 后面随机生成的石头
            if(randD <= 0.5){
                // 在左侧生成
                x = this.preBoxX - this.boxWidth/2;
            }else{
                // 在右侧生成
                x = this.preBoxX + this.boxWidth/2;

                // 第二个石头
                if(this.boxCount == 2){
                    this.player.scaleX = -1;
                }
            }            
            y = this.preBoxY + 100;
            var position = cc.Vec2(x,y);
        }

        // 记住上一个石头的坐标
        this.preBoxX = x;
        this.preBoxY = y;

        newBox.setPosition(position);

},

file

让石头集合移动

机器人每次跳上一个台阶,看似是机器人在动,实际上是石头在动,我们让机器人每次跳动,石头就在之前的基础上移动,我们这里用到cc.moveBy函数。
cc.moveBy: 在设定时间,相对于之前点再移动。
向左跳

playerMoveLeft () {
        console.log('向左跳跃');
        // 用0.1秒的时间,向上移动100px
        var up = cc.moveTo(0.1,cc.Vec2(this.player.x,this.player.y+100));
        // 用0.1秒的时间, 向下移动100px
        var down = cc.moveTo(0.1,cc.Vec2(this.player.x,this.player.y));
        // 执行回调
        var callback = cc.callFunc(this.jumpIsOver, this); 
        // 先向上移动,再向下移动
        var jump = cc.sequence(up,down,callback);
        // 执行动作
        this.player.runAction(jump);
        // X轴翻转,1表示正向,-1表示反向
        this.player.scaleX = 1;

        // 石头向左移动
        var goAction = cc.moveBy(0.2,cc.Vec2(60,-100));
        this.boxList.runAction(goAction);
},

向右跳

playerMoveRight () {
        console.log('向右跳跃');
        // 用0.1秒的时间,向上移动100px
        var up = cc.moveTo(0.1,cc.Vec2(this.player.x,this.player.y+100));
        // 用0.1秒的时间, 向下移动100px
        var down = cc.moveTo(0.1,cc.Vec2(this.player.x,this.player.y));
        // 执行回调
        var callback = cc.callFunc(this.jumpIsOver, this); 
        // 先向上移动,再向下移动
        var jump = cc.sequence(up,down,callback);
        // 执行动作
        this.player.runAction(jump);
        // X轴翻转,1表示正向,-1表示反向
        this.player.scaleX = -1;

        // 石头向右移动
        var goAction = cc.moveBy(0.2,cc.Vec2(-60,-100));
        this.boxList.runAction(goAction);
 },

每次点击生成一个新的石头。

onTouchStart (event) {
        console.log('点击屏幕');
        if(!this.jump){
            return;
        }
        // 点击后就不让点击,直到动作执行完成
        this.jump = false;

        var touchLoc = event.getLocation();
        if (touchLoc.x >= cc.winSize.width/2) {
            // 向右
            this.playerMoveRight();
        } else {
            // 向左
            this.playerMoveLeft();
        }    

        // 生成一个石头
        this.newBox();
        this.bgMove();
},

本章源码地址

码云地址:https://gitee.com/cbb123/LR05

本章内容到此结束,觉得对你有帮助的记得收藏本站,谢谢老铁们的支持!

正文到此结束
本文目录