cocos creator实战-(二)跳一跳

一、游戏的分析(之前没有接触过小游戏,制作的思维还停留在大型ARPG游戏大家共同协作的想法里,但是小游戏讲究小而全,大部分时间是一个人独立开发,所以需要迫使自己养成看到小游戏先拆分细化的思想)

二、一些必要的参数

台阶参数
1: 设置分辨率: 720x1280
2: 台阶的原点:
3: 配置好4个中心点,如果跳到就到4个中心点,否则就失败;
4: 编写代码获得中心点的位置,来初始化Player;
5: 斜率: 0.5560472, 与平行四边形相当;
6: 块开始的世界坐标的位置: (180, 350)

参数
1: 监听事件,开启蓄积能量, 2秒缩放到0.5;
2: 0.5秒内,scale变形到1;
3: 0.5秒内, 旋转一周;
4: 0.5秒内,跳跃到目的地;
5: 能量蓄积: 加速度: power: 600, 初始化: 150;
this.speed += dt * this.power;
this.jumpDistance += this.speed * dt;

6:带上拖尾:
MotionStreak组件: 配置好图片;(引擎bug,父节点移动,带有拖尾的子节点显示效果就会有问题,待解决)
7: ancher_offset: 100
8: 生成地图: 200, 400的距离随机
9: 地图滚动参数: y, 随着玩家滚动, x 取最左值和最右值(180, 580);
10:开始位置(180, 350)

 

三、实现的步骤

1 调整好player,具有旋转和压缩两个动画
2 实现跳跃,前置条件是有东西可跳,所以要先制作两个块
3 制作块,设置块的原点,中心点,前后左右点(主要是做跳跃检测,使用小色块),currBlock nextBlock
4 开始写game_scene.js脚本
  绑定player和block
  固定第一个block(坐标转换)
  添加第二个block (add_block方法)
5 调整第一个块和player的位置
6 实现player的跳跃方法player_jump,以及block的检测方法is_jump_on_block
7 实现地图滚动方法move_map
8 完善游戏代码

 

四、代码

game_scene.js
//game_scene.js

cc.Class({
    extends: cc.Component,

    properties: {
        // foo: {
        //     // ATTRIBUTES:
        //     default: null,        // The default value will be used only when the component attaching
        //                           // to a node for the first time
        //     type: cc.SpriteFrame, // optional, default is typeof default
        //     serializable: true,   // optional, default is true
        // },
        // bar: {
        //     get () {
        //         return this._bar;
        //     },
        //     set (value) {
        //         this._bar = value;
        //     }
        // },
        player: {
            type: cc.Node,
            default: null
        },
        block_prefabs: {
            type: cc.Prefab,
            default: []
        },
        block_root: {
            default: null,
            type: cc.Node
        },
        left_org: cc.v2(0, 0),
        map_root: {
            default: null,
            type: cc.Node
        },
        y_radio: 0.5560472,
        checkout: {
            type: cc.Node,
            default: null
        }
    },

    // LIFE-CYCLE CALLBACKS:

    // onLoad () {},

    start() {
        this.block_list = [];

        this.cur_block = cc.instantiate(this.block_prefabs[Math.floor(Math.random() * this.block_prefabs.length)]);
        this.block_root.addChild(this.cur_block);
        // 将第一个块的位置设置为初始位置
        this.cur_block.setPosition(this.block_root.convertToNodeSpaceAR(this.left_org));

        var w_pos = this.cur_block.getChildByName('mid').convertToWorldSpaceAR(cc.v2(0, 0));
        this.player.setPosition(this.map_root.convertToNodeSpaceAR(w_pos));
        this.next_block = this.cur_block;
        this.player_comp = this.player.getComponent("player");

        this.block_zOrder = -1;
        this.add_block();
    },
    add_block: function() {
        this.cur_block = this.next_block;

        this.next_block = cc.instantiate(this.block_prefabs[Math.floor(Math.random() * this.block_prefabs.length)]);
        this.block_root.addChild(this.next_block);

        this.next_block.zIndex = this.block_zOrder;
        this.block_zOrder--;

        var x_distance = 200 + Math.random() * 200;
        var y_distance = x_distance * this.y_radio;

        var next_pos = this.cur_block.getPosition();
        next_pos.x += x_distance * this.player_comp.direction;
        next_pos.y += y_distance;
        this.next_block.setPosition(next_pos);

        this.player_comp.set_next_block(this.next_block.getComponent("block"));

        // 删除block
        this.block_list.push(this.next_block);
        if (this.block_list.length >= 5) {
            for (var i = 0; i < 2; i++) {
                var block = this.block_list.shift();
                block.destroy();
            }
        }
    },

    // 地图滚动
    move_map(offset_x, offset_y) {
        var m1 = cc.moveBy(0.5, offset_x, offset_y);
        var end_func = cc.callFunc(function() {
            this.add_block();
        }.bind(this));

        var seq = cc.sequence([m1, end_func]);
        this.map_root.runAction(seq);
    },
    on_checkout_game: function() {
        this.checkout.active = true;
    },
    on_game_again: function() {
        cc.director.loadScene("game_scene");
    },
    // update (dt) {},
});
player.js
// player.js
var game_scene = require("game_scene");
cc.Class({
    extends: cc.Component,

    properties: {
        // foo: {
        //     // ATTRIBUTES:
        //     default: null,        // The default value will be used only when the component attaching
        //                           // to a node for the first time
        //     type: cc.SpriteFrame, // optional, default is typeof default
        //     serializable: true,   // optional, default is true
        // },
        // bar: {
        //     get () {
        //         return this._bar;
        //     },
        //     set (value) {
        //         this._bar = value;
        //     }
        // },
        init_speed: 150,
        a_power: 600,
        y_radio: 0.5560472,

        game_manager: {
            type: game_scene,
            default: null
        },
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        this.next_block = null;
        this.direction = 1;
    },

    start() {
        this.rot_node = this.node.getChildByName("rotate");
        this.anima_node = this.rot_node.getChildByName("anima");

        this.is_power_mode = false;
        this.speed = 0;
        this.x_distance = 0;

        this.anima_node.on(cc.Node.EventType.TOUCH_START, function(e) {
            this.is_power_mode = true;
            this.x_distance = 0;
            this.speed = this.init_speed;

            this.anima_node.stopAllActions();
            this.anima_node.runAction(cc.scaleTo(2, 1, 0.5));
        }.bind(this), this);

        this.anima_node.on(cc.Node.EventType.TOUCH_END, function(e) {
            this.is_power_mode = false;
            this.anima_node.stopAllActions();
            this.anima_node.runAction(cc.scaleTo(0.5, 1, 1));

            this.player_jump();
        }.bind(this), this);

        this.anima_node.on(cc.Node.EventType.TOUCH_CANCEL, function(e) {
            this.is_power_mode = false;
            this.anima_node.stopAllActions();
            this.anima_node.runAction(cc.scaleTo(0.5, 1, 1));

            this.player_jump();
        }.bind(this), this);
    },

    update(dt) {
        if (this.is_power_mode) {
            this.speed += (this.a_power * dt);
            this.x_distance += this.speed * dt;
        }
    },

    player_jump: function() {
        var x_distance = this.x_distance * this.direction;
        var y_distance = this.x_distance * this.y_radio;

        var target_pos = this.node.getPosition();
        target_pos.x += x_distance;
        target_pos.y += y_distance;

        // 跳跃时候旋转
        this.rot_node.runAction(cc.rotateBy(0.5, -360 * this.direction));

        var w_pos = this.node.parent.convertToWorldSpaceAR(target_pos);
        var is_game_over = false;
        if (this.next_block.is_jump_on_block(w_pos, this.direction)) {
            target_pos = this.node.parent.convertToNodeSpaceAR(w_pos);
        } else {
            is_game_over = true;
        }

        var j = cc.jumpTo(0.5, target_pos, 200, 1);
        this.direction = (Math.random() < 0.5) ? -1 : 1;
        var end_func = cc.callFunc(function() {
            if (is_game_over) {
                this.game_manager.on_checkout_game();
            } else {
                if (this.direction === -1) {
                    this.game_manager.move_map(580 - w_pos.x, -y_distance);
                } else {
                    this.game_manager.move_map(180 - w_pos.x, -y_distance);
                }
            }
        }.bind(this));

        var seq = cc.sequence(j, end_func);
        this.node.runAction(seq);
    },
    set_next_block(block) {
        this.next_block = block;
    },
});
block.js
// block.js
cc.Class({
    extends: cc.Component,

    properties: {
        // foo: {
        //     // ATTRIBUTES:
        //     default: null,        // The default value will be used only when the component attaching
        //                           // to a node for the first time
        //     type: cc.SpriteFrame, // optional, default is typeof default
        //     serializable: true,   // optional, default is true
        // },
        // bar: {
        //     get () {
        //         return this._bar;
        //     },
        //     set (value) {
        //         this._bar = value;
        //     }
        // },

    },
    start() {
        this.mid = this.node.getChildByName("mid");
        this.up = this.node.getChildByName("up");
        this.down = this.node.getChildByName("down");

        this.left = this.node.getChildByName("left");
        this.right = this.node.getChildByName("right");
    },

    // dir 1右跳 -1左跳
    is_jump_on_block(w_dst_pos, direction) {
        var mid_pos = this.mid.convertToWorldSpaceAR(cc.v2(0, 0));
        var dir = w_dst_pos.sub(mid_pos);
        var min_len = dir.mag();
        var min_pos = mid_pos;

        if (direction === 1) {
            var up_pos = this.up.convertToWorldSpaceAR(cc.v2(0, 0));
            dir = w_dst_pos.sub(up_pos);
            var len = dir.mag();
            if (min_len > len) {
                min_len = len;
                min_pos = up_pos;
            }
            var down_pos = this.down.convertToWorldSpaceAR(cc.v2(0, 0));
            dir = w_dst_pos.sub(down_pos);
            var len = dir.mag();
            if (min_len > len) {
                min_len = len;
                min_pos = down_pos;
            }
        } else {
            var left_pos = this.left.convertToWorldSpaceAR(cc.v2(0, 0));
            dir = w_dst_pos.sub(left_pos);
            var len = dir.mag();
            if (min_len > len) {
                min_len = len;
                min_pos = left_pos;
            }
            var right_pos = this.right.convertToWorldSpaceAR(cc.v2(0, 0));
            dir = w_dst_pos.sub(right_pos);
            var len = dir.mag();
            if (min_len > len) {
                min_len = len;
                min_pos = right_pos;
            }
        }

        // 找到跳跃位置距离参考点最近的那个点以及位置
        dir = w_dst_pos.sub(min_pos);
        if (dir.mag() < 100) {
            w_dst_pos.x = min_pos.x;
            w_dst_pos.y = min_pos.y;
            return true;
        }
        return false;
    },
});

 

posted @ 2019-04-03 15:51  orxx  阅读(3398)  评论(0编辑  收藏  举报