zoukankan      html  css  js  c++  java
  • B站视频:【Creator3】好玩的编队代码 魔性排列停不下来 附源码及出处

    这次带来一个有趣的编队代码,简单的算法得到令人惊叹的编队队形,叹为观止,前几天刷视频的时候看到一个有趣的展示,来自youtube大神:Tarodev的队形计算展示《 Fun with Formations - Game Dev Adventure

    他的是Unity实现的,我用最新发布的Creator 3.3版本制作了一个,视频如下:

    参考资料:https://www.youtube.com/watch?v=NEFxWkTRVCc 

    开发工具 CocosCreator 3.3.0

    BGM: Jazzy Frenchy form bensound

     Creator3以后的引擎,对于3D方面的计算基本上和Unity很像了,转译C#代码并不难,原版代码在这里:GitHub - Matthew-J-Spencer/Formations: Some simple scripts to create formations in Unity 

    CocosCreator中的关键代码如下:

    /** 编队的基类 */
    import { _decorator, Component, Node, Vec3, v3 } from 'cc';
    const { ccclass, property } = _decorator;
    @ccclass('BaseFormation')
    export class BaseFormation extends Component {
        @property
        noise: number = 0;
        @property
        Spread: number = 1;
        offsetPos:Vec3 = v3();
        EvaluatePoints(): Vec3[] {
            return null;
        }
        GetNoise(pos: Vec3): Vec3 {
            const noise = this.noise;
            const x = pos.x + Math.random() * noise - noise / 2;
            const z = pos.z + Math.random() * noise - noise / 2;
            pos.x = x;
            pos.z = z;
            return pos;
        }
    }
    /** 方形编队组件脚本代码 */
    import { _decorator, Component, Node, Vec3, v3 } from 'cc';
    import { BaseFormation } from './BaseFormation';
    const { ccclass, property } = _decorator;
    @ccclass('BoxFormation')
    export class BoxFormation extends BaseFormation {
        @property
        unitWidth: number = 5;
        @property
        unitDepth: number = 5;
        @property
        hollow: boolean = false;
        @property
        nthOffset: number = 0;
        EvaluatePoints(): Vec3[] {
            const ret: Vec3[] = [];
            const middleOffset = v3((this.unitWidth - 1) * 0.5, 0, (this.unitDepth - 1) * 0.5);
            for (let x = 0; x < this.unitWidth; x++) {
                for (let z = 0; z < this.unitDepth; z++) {
                    if (this.hollow && x != 0 && x != this.unitWidth - 1 && z != 0 && z != this.unitDepth - 1) continue;
                    let pos = v3(x + (z % 2 == 0 ? 0 : this.nthOffset), 0, z);
    
                    pos = pos.subtract(middleOffset);
    
                    pos = this.GetNoise(pos);
    
                    pos = pos.multiplyScalar(this.Spread);
                    pos.add(this.offsetPos);
                    ret.push(pos);
                }
            }
            return ret;
        }
    }
    /** 放射编队组件脚本代码 */
    import { _decorator, Component, Node, Vec3, v3 } from 'cc';
    import { BaseFormation } from './BaseFormation';
    const { ccclass, property } = _decorator;
    @ccclass('RadialFormation')
    export class RadialFormation extends BaseFormation {
        @property
        amount: number = 10;
        @property
        radius: number = 1;
        @property
        radiusGrowthMultiplier: number = 0;
        @property
        rotations: number = 1;
        @property
        rings: number = 1;
        @property
        ringOffset: number = 1;
        @property
        nthOffset: number = 1;
        EvaluatePoints(): Vec3[] {
            const ret: Vec3[] = [];
            let amountPerRing = this.amount / this.rings;
            let ringOffset = 0;
            for (var i = 0; i < this.rings; i++) {
                for (var j = 0; j < amountPerRing; j++) {
                    let angle = j * Math.PI * (2 * this.rotations) / amountPerRing + (i % 2 != 0 ? this.nthOffset : 0);
    
                    let radius = this.radius + ringOffset + j * this.radiusGrowthMultiplier;
                    let x = Math.cos(angle) * radius;
                    let z = Math.sin(angle) * radius;
    
                    let pos = new Vec3(x, 0, z);
    
                    pos = this.GetNoise(pos);
    
                    pos = pos.multiplyScalar(this.Spread);
    
                    pos.add(this.offsetPos);
                    ret.push(pos);
                }
                ringOffset += this.ringOffset;
            }
            return ret;
        }
    }

    以上便是CocosCreator3版本的核心计算代码了,可以自行贴在编队节点上,人物控制应该是由特定的渲染代码完成。

    编队展示处理代码

    /**
     * 编队渲染展示的代码,挂在到你想展示的节点容器上,配合对应的Formation组件
     * 请自行构建Actor角色组件用于处理人物逻辑,实现removeSelf和moveTo
     * 在合适的时机处理编队的刷新,比如编队参数变化、队伍移动的时候
     */
    import { _decorator, Component, Node, Prefab, instantiate, director } from 'cc';
    import { Actor } from '../actors/Actor';
    import { BaseFormation } from '../formations/BaseFormation';
    const { ccclass, property } = _decorator;
     
    @ccclass('FormationShow')
    export class FormationShow extends Component {
        @property(Prefab)
        actor: Prefab = null;
        start() {
            this.FormationUpdate();
        }
        FormationUpdate(prop?: string, value?: number) {
            const formation = this.getComponent(BaseFormation);
            if (formation) {
                if (prop) {
                    const old = formation[prop];
                    formation[prop] = value;
                    if (old == formation[prop]) {
                        return;
                    }
                }
                const points = formation.EvaluatePoints();
                for (let i = this.node.children.length - 1; i >= points.length; i--) {
                    this.node.children[i].getComponent(Actor).removeSelf();
                }
                const len = this.node.children.length;
                for (let i = 0; i < points.length; i++) {
                    if (i < points.length && i >= len) {
                        let actor = null;
                        if (len > 0) {
                            actor = this.node.children[len - 1];
                        } else {
                            actor = this.actor;
                        }
                        const a = instantiate(actor);
                        this.node.addChild(a);
                    }
                    this.node.children[i].getComponent(Actor).moveTo(points[i]);
                }
            }
        }
    }

    结语

    视频中的源码工程已经发布到Cocos的官方商店,有需要的自取
    https://store.cocos.com/app/detail/3210 

  • 相关阅读:
    Module build failed: Error: Cannot find module 'node-sass'报错问题
    vue element upload
    vue-element-table 分页选中
    两种倒计时
    【LOJ #6076】「2017 山东一轮集训 Day6」三元组(莫比乌斯反演 / 三元环计数)
    【LOJ #6075】「2017 山东一轮集训 Day6」重建(DP)
    【2020省选模拟】题解
    【LOJ #6074】「2017 山东一轮集训 Day6」子序列(矩阵乘法)
    【LOJ #6073】「2017 山东一轮集训 Day5」距离(主席树 / 树链剖分)
    【LOJ #6072】 「2017 山东一轮集训 Day5」苹果树(容斥 / 搜索 / 矩阵树定理)
  • 原文地址:https://www.cnblogs.com/nowpaper/p/15389589.html
Copyright © 2011-2022 走看看