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 

  • 相关阅读:
    PAT (Advanced Level) Practice 1054 The Dominant Color (20 分)
    PAT (Advanced Level) Practice 1005 Spell It Right (20 分) (switch)
    PAT (Advanced Level) Practice 1006 Sign In and Sign Out (25 分) (排序)
    hdu 5114 Collision
    hdu4365 Palindrome graph
    单链表查找最大值、两个递增的链表合并并且去重
    蓝桥杯-最短路 (SPFA算法学习)
    蓝桥杯-最大最小公倍数
    Codeforces-470 div2 C题
    蓝桥杯-地宫取宝
  • 原文地址:https://www.cnblogs.com/nowpaper/p/15389589.html
Copyright © 2011-2022 走看看