【recast-navigation-js】使用three.js辅助绘制Agent

说在前面

  • 操作系统:windows 11
  • 浏览器:edge版本 124.0.2478.97
  • recast-navigation-js版本:0.29.0
  • golang版本:1.21.5

使用Tweakpane

  • fps面板
    interface FPSGraph extends BladeApi<BladeController<View>> {
        begin(): void
        end(): void
    }
    
    export interface BindingItem {
        refresh(): void
    }
    
    // Debug
    export const gui = new Pane()
    gui.registerPlugin(EssentialsPlugin)
    
    export const fpsGraph = gui.addBlade({
        view: 'fpsgraph',
        label: 'fpsgraph',
    
    }) as FPSGraph
    
  • 鼠标点击位置
    const controlFolder = gui.addFolder({
            title: "SceneControl",
        })
        this._sceneCtlBinding = controlFolder.addBinding(this._control, 'target', {
            format: (x) => x,
        }) as BindingItem
    
    在这里插入图片描述
  • 手动刷新值
    按理说绑定之后应该要自动刷新界面上的值,但是不知道为啥没有刷新
    private refreshBinding() {
        if (this._sceneCtlBinding) {
            this._sceneCtlBinding.refresh()
        }
    }
    
  • 监听事件
     public onPointerDown(e: PointerEvent) {
        var pointer = new Vector2()
        pointer.set((e.clientX / window.innerWidth) * 2 - 1, - (e.clientY / window.innerHeight) * 2 + 1);
    
        this._raycaster.setFromCamera(pointer, this._camera);
        console.log(pointer)
        const intersects = this._raycaster.intersectObject(this._navMeshObj);
    
        if (intersects.length > 0) {
            switch (e.button) {
                case 0:
                    // "Left button clicked.";
                    break;
                case 1:
                    // "Middle button clicked.";
                    this._control.target = intersects[0].point
                    break;
                case 2:
                    // "Right button clicked.";
                    this._agent.teleport(intersects[0].point)
                    break;
                default:
                    // `Unknown button code: ${e.button}`;
            }
        }
    }
    
  • 结果
    在这里插入图片描述

添加CrowAgent

  • agent.ts
    import { CrowdHelper } from "@recast-navigation/three";
    import { Crowd, CrowdAgent, NavMesh, NavMeshQuery } from "recast-navigation";
    import { MeshStandardMaterial, Vector3 } from "three";
    
    export class RecastAgent {
        private _meshQuery: NavMeshQuery
        private _crowd: Crowd
        private _agent: CrowdAgent
        private _agentTarget: null | Vector3
    
        public crowdHelper: CrowdHelper
    
        constructor(mesh: NavMesh) {
            this._meshQuery = new NavMeshQuery(mesh)
            this._crowd = new Crowd(mesh, {
                maxAgents: 1,
                maxAgentRadius: 0.5,
            })
    
            const { point: agentPosition } = this._meshQuery.findClosestPoint({ x: 0, y: 0, z: 0 })
    
            this._agent = this._crowd.addAgent(
                agentPosition,
                {
                    radius: 0.5,
                    height: 1,
                    maxAcceleration: 1,
                    maxSpeed: 1,
                }
            )
            this.crowdHelper = new CrowdHelper({
                crowd: this._crowd,
                agentMaterial: new MeshStandardMaterial({ color: 'red' }),
            })
            this._agentTarget = null
        }
    
        public update(delta: number) {
            this._crowd.update(delta)
            this.crowdHelper.update()
        }
    
        public teleport(pos: Vector3) {
            const { point: target, success: ok } = this._meshQuery.findClosestPoint(pos);
            this._agent.teleport(target);
            console.log(ok ,pos, target)
    
            this._agentTarget = null
        }
    
        public setAgentTarget(pos: Vector3) {
            const { point: target } = this._meshQuery.findClosestPoint(pos);
            this._agent.requestMoveTarget(target);
    
            this._agentTarget = new Vector3().copy(target as Vector3)
        }
    }
    
  • 右键点击事件调用teleport函数
    // ...
    case 2:
    	// "Right button clicked.";
        this._agent.teleport(intersects[0].point)
        break;
    // ...
    
  • 结果
    在这里插入图片描述

其他

  • 完整代码再等等
  • findClosestPoint有时候会失败,有时候感觉位置不对,得再看看是啥问题
手动编写TypeScript类型定义(.d.ts 文件),也称为“声明文件”,是为了给现有的JavaScript库或模块添加类型注解,使得TypeScript能够在编译期间检测出潜在的问题。以下是编写基本类型定义的基本步骤: 1. 创建.d.ts 文件:在项目目录下创建一个新的文件,通常命名为库名加上`.d.ts` 的后缀,例如 `myLibrary.d.ts`。 2. 导入或导出模块:在文件顶部,首先使用 `export` 关键字导入你想要类型化的模块,如果是全局变量,则不需要导入。例如: ```typescript export interface MyLibrary { // ... } ``` 3. 定义接口、类或类型:对于模块中的函数、对象或枚举,创建相应的类型声明。例如,如果`Recast`是一个对象,可以这样定义: ```typescript declare class Recast { analyze(code: string): any; // 这里只是一个示例,实际应有详细的类型 } ``` 4. 添加属性和方法:为每个函数或对象添加详细的参数类型和返回类型。如果你知道它们的具体类型,尽可能精确。 5. 提供必要的类型约束:使用 TypeScript 的类型关键字如 `number`, `string`, 或自定义类型约束 (`extends` 和 `implements`) 来限制参数和返回值的类型。 6. 异常和静态成员:若有必要,声明可能出现的异常类型,以及静态成员的类型。 7. 使用 `any` 或 `unknown`:对于未知或不可信的部分,你可以标记为 `any` 或 `unknown`,但这会影响TypeScript的类型检查。 完成上述步骤后,TypeScript将能够识别并使用你在.d.ts文件中定义的类型。记得在项目中引入这个定义文件,让TypeScript在编译时使用它。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值