cocos creator动画编辑器编辑地图路径

思路

1、利用动画编辑器,设置一个路径,多个路径就编辑多个动画

2、用特定的代码对动画进行处理,获取到路径坐标,大佬已经写好代码, 不用自己重复造轮子了(微元法求曲线长度)

  获得动画路径的贝塞尔曲线方程

  求得每一段贝塞尔曲线的长度

  每隔一小段打一个点

  最终生成一个路径

3、编写寻路脚本,挂载到物体上,让沿着路径移动

动画编辑

脚本挂载

 

 

// gen_map_path.js 动画路径转换坐标的代码 已经升级到2.x

cc.Class({

    extends: cc.Component,

    properties: {

        // foo: {

        //    default: null,      // The default value will be used only when the component attaching

        //                           to a node for the first time

        //    url: cc.Texture2D,  // optional, default is typeof default

        //    serializable: true, // optional, default is true

        //    visible: true,      // optional, default is true

        //    displayName: 'Foo', // optional

        //    readonly: false,    // optional, default is false

        // },

        // ...

        is_debug: false,

    },

    // use this for initialization

    onLoad: function() {

        this.anim_com = this.node.getComponent(cc.Animation);

        var clips = this.anim_com.getClips();

        var clip = clips[0];

        var newNode = new cc.Node();

        this.new_draw_node = newNode.getComponent(cc.Graphics);

        if (!this.new_draw_node) {

            this.new_draw_node = this.node.addComponent(cc.Graphics);

        }

        this.node.addChild(newNode);

        // this.draw_node = new cc.DrawNode();

        // this.node._sgNode.addChild(this.draw_node);

        var paths = clip.curveData.paths;

        // console.log(paths);

        this.road_data_set = [];

        var k;

        for (k in paths) {

            var road_data = paths[k].props.position;

            this.gen_path_data(road_data);

        }

    },

    start: function() {

        /*

        // test()

        var actor = cc.find("UI_ROOT/map_root/ememy_gorilla").getComponent("actor");

        // actor.gen_at_road(this.road_data_set[0]);

 

        actor = cc.find("UI_ROOT/map_root/ememy_small2").getComponent("actor");

        // actor.gen_at_road(this.road_data_set[1]);

 

        actor = cc.find("UI_ROOT/map_root/ememy_small3").getComponent("actor");

        actor.gen_at_road(this.road_data_set[2]);

        */

        // end 

    },

    get_road_set: function() {

        return this.road_data_set;

    },

    gen_path_data: function(road_data) {

        var ctrl1 = null;

        var start_point = null;

        var end_point = null;

        var ctrl2 = null;

        var road_curve_path = []; // [start_point, ctrl1, ctrl2, end_point],

        for (var i = 0; i < road_data.length; i++) {

            var key_frame = road_data[i];

            if (ctrl1 !== null) {

                road_curve_path.push([start_point, ctrl1, ctrl1, cc.p(key_frame.value[0], key_frame.value[1])]);

            }

            start_point = cc.p(key_frame.value[0], key_frame.value[1]);

            for (var j = 0; j < key_frame.motionPath.length; j++) {

                var end_point = cc.p(key_frame.motionPath[j][0], key_frame.motionPath[j][1]);

                ctrl2 = cc.p(key_frame.motionPath[j][2], key_frame.motionPath[j][3]);

                if (ctrl1 === null) {

                    ctrl1 = ctrl2;

                }

                // 贝塞尔曲线 start_point, ctrl1, ctrl2, end_point,

                road_curve_path.push([start_point, ctrl1, ctrl2, end_point]);

                ctrl1 = cc.p(key_frame.motionPath[j][4], key_frame.motionPath[j][5]);

                start_point = end_point;

            }

        }

        console.log(road_curve_path);

        var one_road = [road_curve_path[0][0]];

        for (var index = 0; index < road_curve_path.length; index++) {

            start_point = road_curve_path[index][0];

            ctrl1 = road_curve_path[index][1];

            ctrl2 = road_curve_path[index][2];

            end_point = road_curve_path[index][3];

            var len = this.bezier_length(start_point, ctrl1, ctrl2, end_point);

            var OFFSET = 16;

            var count = len / OFFSET;

            count = Math.floor(count);

            var t_delta = 1 / count;

            var t = t_delta;

            for (var i = 0; i < count; i++) {

                var x = start_point.x * (1 - t) * (1 - t) * (1 - t) + 3 * ctrl1.x * t * (1 - t) * (1 - t) + 3 * ctrl2.x * t * t * (1 - t) + end_point.x * t * t * t;

                var y = start_point.y * (1 - t) * (1 - t) * (1 - t) + 3 * ctrl1.y * t * (1 - t) * (1 - t) + 3 * ctrl2.y * t * t * (1 - t) + end_point.y * t * t * t;

                one_road.push(cc.p(x, y));

                t += t_delta;

            }

        }

        console.log(one_road);

        if (this.is_debug) {

            this.new_draw_node.clear(); // 清除以前的

            for (var i = 0; i < one_road.length; i++) {

                this.new_draw_node.moveTo(one_road[i].x, one_road[i].y);

                this.new_draw_node.lineTo(one_road[i].x + 1, one_road[i].y + 1);

                this.new_draw_node.stroke();

                // this.draw_node.drawSegment(one_road[i],

                //     cc.p(one_road[i].x + 1, one_road[i].y + 1),

                //     1, cc.color(255, 0, 0, 255));

            }

        }

        this.road_data_set.push(one_road);

    },

    bezier_length: function(start_point, ctrl1, ctrl2, end_point) {

            // t [0, 1] t 分成20等分 1 / 20 = 0.05

            var prev_point = start_point;

            var length = 0;

            var t = 0.05;

            for (var i = 0; i < 20; i++) {

                var x = start_point.x * (1 - t) * (1 - t) * (1 - t) + 3 * ctrl1.x * t * (1 - t) * (1 - t) + 3 * ctrl2.x * t * t * (1 - t) + end_point.x * t * t * t;

                var y = start_point.y * (1 - t) * (1 - t) * (1 - t) + 3 * ctrl1.y * t * (1 - t) * (1 - t) + 3 * ctrl2.y * t * t * (1 - t) + end_point.y * t * t * t;

                var now_point = cc.p(x, y);

                var dir = now_point.sub(prev_point);

                prev_point = now_point;

                length += dir.mag();

                t += 0.05;

            }

            return length;

        }

        // called every frame, uncomment this function to activate update callback

        // update: function (dt) {

    // },

});

// actor.js 角色沿路径行走代码

var gen_map_path = require("gen_map_path");

var State = {

    Idle: 0,

    Walk: 1,

    Attack: 2,

    Dead: 3,

};

cc.Class({

    extends: cc.Component,

    properties: {

        // foo: {

        //    default: null,      // The default value will be used only when the component attaching

        //                           to a node for the first time

        //    url: cc.Texture2D,  // optional, default is typeof default

        //    serializable: true, // optional, default is true

        //    visible: true,      // optional, default is true

        //    displayName: 'Foo', // optional

        //    readonly: false,    // optional, default is false

        // },

        // ...

        map: {

            type: gen_map_path,

            default: null,

        },

        speed: 100,

    },

    // use this for initialization

    onLoad: function() {

    },

    start: function() {

        var road_set = this.map.get_road_set();

        this.cur_road = road_set[0];

        if (this.cur_road < 2) {

            return;

        }

        this.state = State.Idle;

        var pos = this.cur_road[0];

        this.node.setPosition(pos);

        this.walk_to_next = 1;

        this.start_walk();

    },

    start_walk: function() {

        if (this.walk_to_next >= this.cur_road.length) {

            // 攻击逻辑

            this.state = State.Attack;

            // 

            return;

        }

        var src = this.node.getPosition();

        var dst = this.cur_road[this.walk_to_next];

        var dir = dst.sub(src);

        var len = dir.mag();

        this.vx = this.speed * dir.x / len;

        this.vy = this.speed * dir.y / len;

        this.walk_total_time = len / this.speed;

        this.walked_time = 0;

        this.state = State.Walk;

    },

    walk_update: function(dt) {

        if (this.state != State.Walk) {

            return;

        }

        this.walked_time += dt;

        if (this.walked_time > this.walk_total_time) {

            dt -= (this.walked_time - this.walk_total_time);

        }

        var sx = this.vx * dt;

        var sy = this.vy * dt;

        this.node.x += sx;

        this.node.y += sy;

        if (this.walked_time >= this.walk_total_time) {

            this.walk_to_next++;

            this.start_walk();

        }

    },

    // called every frame, uncomment this function to activate update callback

    update: function(dt) {

        if (this.state == State.Walk) {

            this.walk_update(dt);

        }

    },

});

Cocos Creator编辑器提供了一套强大的功能,使开发者可以轻松地编写工具来增强开发流程。以下是Cocos Creator编辑器如何编写工具的步骤: 1.熟悉Cocos Creator编辑器:首先,开发者需要熟悉Cocos Creator编辑器的基本操作和功能。这包括了场景编辑、节点操作、组件配置等。 2.了解Cocos Creator的插件机制:Cocos Creator提供了插件机制,开发者可以通过插件扩展编辑器的功能。开发者可以在官方文档中找到关于插件开发的详细说明。 3.确定工具的需求:开发者需要明确工具的需求和目标。这可以是一项新功能、自动化操作、场景批量处理等。确保明确工具的功能和预期效果。 4.开发插件:根据工具的需求,开发者可以通过插件机制来实现工具。插件可以包括自定义的编辑器窗口、面板、节点操作脚本等。 5.使用API扩展功能:Cocos Creator提供了丰富的API来扩展编辑器的功能。开发者可以使用这些API来实现工具的核心功能。 6.测试和调试:在编写工具过程中,开发者需要进行反复的测试和调试以确保工具的正确性和可靠性。这可以包括单元测试、集成测试和用户界面测试等。 7.发布和分享工具:完成工具开发后,开发者可以考虑将其发布和分享。开发者可以将工具打包成插件,供其他开发者使用和安装。 总之,使用Cocos Creator编辑器编写工具可以有效地提高开发效率和质量。通过插件机制和丰富的API,开发者可以根据自己的需求自定义和扩展编辑器的功能。希望这些步骤能对您编写Cocos Creator编辑器工具有所帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值