添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
幸福的草稿本  ·  读取 Provider | Riverpod·  6 小时前    · 
卖萌的枇杷  ·  json-schema-to-ts - npm·  8 小时前    · 
暴躁的四季豆  ·  Best practices for ...·  2 天前    · 
打盹的桔子  ·  html5 PHP ...·  3 周前    · 
咆哮的勺子  ·  根治气管癌 ...·  1 月前    · 

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

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

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

CocosCreator中的关键代码如下:

BaseFormation.ts

/** 编队的基类 */
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;

BoxFormation.ts

/** 方形编队组件脚本代码 */
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;

RadialFormation.ts

/** 放射编队组件脚本代码 */
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]);

在下本着受人于鱼,不如授人于驴的原则,先行发一篇帖子和视频,后续会将核心代码放置在Store中,欢迎购买 ╮(╯▽╰)╭