开源!! Creator3.8+ 游戏框架(涉及UI(FGUI)、实体组件、Http、行为树、四叉树、全局定时器、全局事件、资源管理、红点解决方案等内容)

四叉树

四叉树是一种通过空间划分来进行高效碰撞查询的数据结构。

基本概念

  1. 形状类型

    import { QuadTree, Box, Circle, Polygon } from 'kunpocc';
    
    // 1. 矩形
    const box = new Box(x, y, width, height, tag);
    
    // 2. 圆形
    const circle = new Circle(x, y, radius, tag);
    
    // 3. 多边形
    const points = [v2(x1, y1), v2(x2, y2), v2(x3, y3)];
    const polygon = new Polygon(points, tag);
    
  2. 配置参数

    // 四叉树配置
    const QTConfig = {
        MAX_SHAPES: 12,  // 每个节点最大形状数量
        MAX_LEVELS: 5,   // 最大深度
    }
    

使用示例

  1. 创建和初始化

    import { QuadTree, Box, rect } from 'kunpocc';
    
    // 创建四叉树(参数:区域范围,层级,绘制组件)
    const bounds = rect(0, 0, 800, 600);  // x, y, width, height
    const quadTree = new QuadTree(bounds);
    
    // 添加形状
    const player = new Box(100, 100, 50, 50, 1);  // 玩家碰撞体,tag=1
    const enemy = new Circle(200, 200, 25, 2);    // 敌人碰撞体,tag=2
    quadTree.insert(player);
    quadTree.insert(enemy);
    
  2. 碰撞检测

    // 检测指定形状与特定标签的碰撞
    const collisions = quadTree.collide(player, 2);  // 检测玩家与 tag=2 的形状碰撞
    if (collisions.length > 0) {
        console.log('发生碰撞!');
        for (const target of collisions) {
            // 处理碰撞逻辑
        }
    }
    
  3. 动态更新

    // 在游戏循环中更新四叉树
    function update() {
        // 更新形状位置
        player.position = v2(newX, newY);
        enemy.position = v2(newX, newY);
        
        // 更新四叉树
        quadTree.update();
        
        // 检测碰撞
        const collisions = quadTree.collide(player, 2);
    }
    
  4. 清理

    // 清理四叉树
    quadTree.clear();
    

形状操作

  1. 位置和缩放

    // 设置位置
    shape.position = v2(x, y);
    
    // 设置缩放
    shape.scale = 1.5;
    
    // 获取包围盒
    const boundingBox = shape.getBoundingBox();
    
  2. 特定形状操作

    // 矩形重置
    box.resetPoints(x, y, width, height);
    
    // 圆形半径
    circle.radius = newRadius;
    
    // 多边形顶点
    polygon.points = newPoints;
    

性能优化建议

  1. 合理设置配置参数:

    • MAX_SHAPES:较小的值会导致更频繁的分裂,较大的值会降低查询效率
    • MAX_LEVELS:控制树的最大深度,防止过度分割
  2. 碰撞检测优化:

    • 使用合适的标签系统,只检测需要的碰撞
    • 根据游戏需求选择合适的形状(圆形计算最快)
    • 避免使用过于复杂的多边形
  3. 更新策略:

    • 仅在必要时更新四叉树
    • 对于静态物体,可以使用单独的四叉树
    • 动态物体频繁更新时,考虑使用更大的边界范围

行为树

行为树是一种强大的 AI 决策系统,用于实现复杂的游戏 AI 行为。

基本概念

  1. 节点状态
enum Status {
    SUCCESS,  // 成功
    FAILURE,  // 失败
    RUNNING   // 运行中
}
  1. 节点类型
  • 动作节点 (Action):执行具体行为的叶子节点
  • 组合节点 (Composite):控制子节点执行顺序的节点
  • 条件节点 (Condition):判断条件的节点
  • 装饰节点 (Decorator):修饰其他节点行为的节点

使用示例

import { 
    BehaviorTree, 
    Sequence, 
    Selector, 
    Parallel,
    Success,
    Failure,
    WaitTime,
    Agent,
    Blackboard
} from 'kunpocc';

// 1. 创建行为树
const tree = new BehaviorTree(
    new Sequence(  // 顺序节点:按顺序执行所有子节点
        new WaitTime(2),  // 等待2秒
        new Selector(  // 选择节点:选择一个可执行的子节点
            new Success(() => {
                console.log("执行成功动作");
            }),
            new Failure(() => {
                console.log("执行失败动作");
            })
        )
    )
);

// 2. 创建代理和黑板
const agent = new Agent();  // AI代理
const blackboard = new Blackboard();  // 共享数据黑板

// 3. 执行行为树
tree.tick(agent, blackboard);

常用节点

  1. 组合节点

    // 顺序节点:按顺序执行所有子节点,直到遇到失败或运行中的节点
    new Sequence(childNode1, childNode2, childNode3);
    
    // 选择节点:选择第一个成功或运行中的子节点
    new Selector(childNode1, childNode2, childNode3);
    
    // 并行节点:同时执行所有子节点
    new Parallel(childNode1, childNode2, childNode3);
    
    // 记忆顺序节点:记住上次执行的位置
    new MemSequence(childNode1, childNode2, childNode3);
    
    // 记忆选择节点:记住上次执行的位置
    new MemSelector(childNode1, childNode2, childNode3);
    
    // 随机选择节点:随机选择一个子节点执行
    new RandomSelector(childNode1, childNode2, childNode3);
    
  2. 动作节点

    // 成功节点
    new Success(() => {
        // 执行动作
    });
    
    // 失败节点
    new Failure(() => {
        // 执行动作
    });
    
    // 运行中节点
    new Running(() => {
        // 持续执行的动作
    });
    
    // 等待节点
    new WaitTime(2);  // 等待2秒
    new WaitTicks(5);  // 等待5个tick
    
  3. 使用黑板共享数据

    // 在节点中使用黑板
    class CustomAction extends Action {
        tick(ticker: Ticker): Status {
            // 获取数据
            const data = ticker.blackboard.get("key");
            
            // 设置数据
            ticker.blackboard.set("key", "value");
            
            return Status.SUCCESS;
        }
    }
    

注意事项

  1. 节点状态说明:
    • SUCCESS:节点执行成功
    • FAILURE:节点执行失败
    • RUNNING:节点正在执行中
  2. 组合节点特性:
    • Sequence:所有子节点返回 SUCCESS 才返回 SUCCESS
    • Selector:任一子节点返回 SUCCESS 就返回 SUCCESS
    • Parallel:并行执行所有子节点
    • MemSequence/MemSelector:会记住上次执行位置
  3. 性能优化:
    • 使用黑板共享数据,避免重复计算
    • 合理使用记忆节点,减少重复执行
    • 控制行为树的深度,避免过于复杂

资源加载

!!! 注意:资源加载多次和一次效果一样

特点

  • 可通过路径或者uuid获取资源
  • 只适合手动管理资源,单无论加载多少次,卸载一次后删除

使用

    let paths: kunpo.IAssetConfig[] = [
        { path: "ui/manual", type: cc.Asset },
        { path: "prefab", type: cc.Prefab },
        { path: "icon", type: cc.SpriteFrame },
        { path: "texture/6101/spriteFrame", type: cc.SpriteFrame, isFile: true },
        { path: "pet", type: cc.SpriteFrame, bundle: "bundle_res" },
    ];
    let loader = new kunpo.AssetLoader("load");
    loader.start({
        configs: paths,
        complete: () => {
            console.log("加载完成");
        },
        fail: (msg: string, err: Error) => {
            console.log("加载失败", msg, err);
        },
        progress: (percent: number) => {
            console.log("加载进度", percent);
        }
    });

接口

资源加载器

interface IAssetConfig {
    /** 资源类型 */
    type: typeof Asset;
    /** 资源路径 */
    path: string;
    /** 是否是单个文件 默认是文件夹 */
    isFile?: boolean;
    /** 资源包名 默认 resources */
    bundle?: string;
}

/**
 * 开始加载资源
 * @param {IAssetConfig[]} res.configs 资源配置
 * @param {number} res.parallel 并行加载数量 默认 10
 * @param {number} res.retry 失败重试次数 默认 3
 * @param {Function} res.complete 加载完成回调
 * @param {Function} res.progress 加载进度回调
 * @param {Function} res.fail 加载失败回调
 */
public start(res: { configs: IAssetConfig[], parallel?: number, retry?: number, complete: () => void, fail: (msg: string, err: Error) => void, progress?: (percent: number) => void }): void

/** 重试 重新加载失败的资源 */
public retry(): void

资源池

/** 资源是否已加载 */
public static has(path: string, bundlename: string = "resources"): boolean

/** 获取资源 */
public static get<T extends Asset>(path: string, bundlename: string = "resources"): T

/** 按 uuid 判断资源是否已加载 */
public static hasUUID(uuid: string): boolean

/** 按 uuid 获取资源 */
public static getByUUID<T extends Asset>(uuid: string): T

/** 按资源路径释放资源 */
public static releasePath(path: string, bundlename: string = "resources"): void

/** 按 bundle 和 文件夹释放资源 */
public static async releaseDir(dir: string, bundlename: string = "resources", asset: typeof Asset): Promise<void>

/** 按 uuid 释放资源 */
public static releaseUUID(uuid: string): void

/** 释放所有加载的资源 */
public static releaseAll(): void

条件显示节点

特点

  • 用于在游戏中显示或隐藏特定UI元素。
  • 一般用于红点提示
  • 主要是解耦用,条件单独实现,节点关联单条件或者多个条件

使用

定义条件

// 定义条件类型枚举
enum ConditionType {
  condition1,
  condition2,
  condition3,
}

// 定义条件
@conditionClass(ConditionType.condition1)
export class Condition1 extends kunpo.ConditionBase {
    protected onInit(): void {
      // 监听条件发生变化, 则调用一次 this.tryUpdate();
        kunpo.GlobalEvent.add("condition1", () => {
            this.tryUpdate();
        }, this);
    }

    protected evaluate(): boolean {
      	//TODO:: 根据条件数据,返回true or false
        return true;
    }
}

节点关联条件

/** 任意一个满足 显示节点 */
new kunpo.ConditionAnyNode(fgui.GObject, ConditionType.condition1, ConditionType.condition2);

/** 所有条件都满足 显示节点 */
new kunpo.ConditionAllNode(fgui.GObject, ConditionType.Condition1, ConditionType.Condition2, ConditionType.Condition3);

全局事件系统

使用


import { GlobalEvent } from 'kunpocc';

// 添加事件监听

GlobalEvent.add('eventName', (arg1, arg2) => {

console.log('事件触发:', arg1, arg2);

}, this);

// 添加一次性事件监听

GlobalEvent.addOnce('oneTimeEvent', (data) => {

console.log('一次性事件触发:', data);

}, this);

// 发送事件

GlobalEvent.send('eventName', 'arg1', 'arg2');

// 发送事件到指定目标

GlobalEvent.sendToTarget('eventName', target, 'arg1', 'arg2');

// 移除事件监听

GlobalEvent.remove('eventName', callback, this);

// 移除指定目标的所有事件监听

GlobalEvent.removeByTarget(this);

// 移除指定事件名和目标的事件监听

GlobalEvent.removeByNameAndTarget('eventName', this);

计时器

使用


import { GlobalTimer } from 'kunpocc';

// 启动一次性定时器(2秒后执行)

const timerId1 = GlobalTimer.startTimer(() => {

console.log('2秒后执行一次');

}, 2);

// 启动循环定时器(每3秒执行一次,执行5次)

const timerId2 = GlobalTimer.startTimer(() => {

console.log('每3秒执行一次,总共执行5次');

}, 3, 5);

// 启动无限循环定时器(每1秒执行一次)

const timerId3 = GlobalTimer.startTimer(() => {

console.log('每1秒执行一次,无限循环');

}, 1, -1);

// 停止定时器

GlobalTimer.stopTimer(timerId1);

GlobalTimer.stopTimer(timerId2);

GlobalTimer.stopTimer(timerId3);

注意事项:

  • 定时器的时间间隔单位为秒

  • loop 参数说明:

  • 0:执行一次

  • 正整数 n:执行 n 次

  • -1:无限循环

平台

Platform 类提供了游戏运行平台的相关信息和判断方法。

平台类型

import { Platform, PlatformType } from 'kunpocc';

// 平台类型枚举
enum PlatformType {
    Android = 1,    // 安卓
    IOS,            // iOS
    HarmonyOS,      // 鸿蒙
    WX,             // 微信小游戏
    Alipay,         // 支付宝小游戏
    Bytedance,      // 字节小游戏
    HuaweiQuick,    // 华为快游戏
    Browser         // 浏览器
}

// 获取当前平台类型
const currentPlatform = Platform.platform;

平台判断

import { Platform } from 'kunpocc';

// 原生平台判断
if (Platform.isNative) {
    console.log('当前是原生平台');
}

// 移动平台判断
if (Platform.isMobile) {
    console.log('当前是移动平台');
}

// 原生移动平台判断
if (Platform.isNativeMobile) {
    console.log('当前是原生移动平台');
}

// 具体平台判断
if (Platform.isAndroid) {
    console.log('当前是安卓平台');
}

if (Platform.isIOS) {
    console.log('当前是iOS平台');
}

if (Platform.isHarmonyOS) {
    console.log('当前是鸿蒙系统');
}

// 小游戏平台判断
if (Platform.isWX) {
    console.log('当前是微信小游戏');
}

if (Platform.isAlipay) {
    console.log('当前是支付宝小游戏');
}

if (Platform.isBytedance) {
    console.log('当前是字节小游戏');
}

if (Platform.isHuaweiQuick) {
    console.log('当前是华为快游戏');
}

// 浏览器判断
if (Platform.isBrowser) {
    console.log('当前是浏览器环境');
}

使用示例

import { Platform, PlatformType } from 'kunpocc';

// 根据平台类型执行不同逻辑
switch (Platform.platform) {
    case PlatformType.Android:
        // 安卓平台特定逻辑
        break;
    case PlatformType.IOS:
        // iOS平台特定逻辑
        break;
    case PlatformType.WX:
        // 微信小游戏特定逻辑
        break;
    default:
        // 其他平台逻辑
        break;
}

// 针对不同平台进行适配
if (Platform.isNativeMobile) {
    // 原生移动平台的处理
    if (Platform.isAndroid) {
        // 安卓特有功能
    } else if (Platform.isIOS) {
        // iOS特有功能
    }
} else if (Platform.isWX || Platform.isAlipay || Platform.isBytedance) {
    // 小游戏平台的处理
} else {
    // 浏览器平台的处理
}

屏幕


/** 屏幕宽度 */

public static ScreenWidth: number;

/** 屏幕高度 */

public static ScreenHeight: number;

/** 设计分辨率宽 */

public static DesignWidth: number;

/** 设计分辨率高 */

public static DesignHeight: number;

/** 安全区外一侧的高度 或 宽度 */

public static SafeAreaHeight: number;

/** 安全区的宽度 */

public static SafeWidth: number;

/** 安全区的高度 */

public static SafeHeight: number;

工具

一、数学工具 (MathTool)

import { MathTool } from 'kunpocc';

// 1. 数值限制
// 将数值限制在指定范围内
const value = MathTool.clampf(75, 0, 100);  // 返回75,因为在0-100范围内
const value2 = MathTool.clampf(150, 0, 100); // 返回100,因为超出上限
const value3 = MathTool.clampf(-50, 0, 100); // 返回0,因为低于下限

// 2. 随机数生成
// 生成指定范围内的整数(包含边界值)
const randomInt = MathTool.rand(1, 10);      // 返回1到10之间的整数

// 生成指定范围内的浮点数(包含最小值,不包含最大值)
const randomFloat = MathTool.randRange(0, 1); // 返回0到1之间的浮点数

// 3. 角度与弧度转换
// 角度转弧度
const radian = MathTool.rad(90);  // 90度转换为弧度:约1.57

// 弧度转角度
const degree = MathTool.deg(Math.PI); // π弧度转换为角度:180

// 4. 平滑过渡
// 用于实现数值的平滑变化,常用于相机跟随、UI动画等
const smoothValue = MathTool.smooth(
    0,    // 起始值
    100,  // 目标值
    0.16, // 已经过时间(秒)
    0.3   // 响应时间(秒)
);  // 返回一个平滑过渡的中间值

使用说明:

  1. clampf(value: number, min: number, max: number): number

    • 将数值限制在指定范围内
    • 如果小于最小值,返回最小值
    • 如果大于最大值,返回最大值
    • 否则返回原值
  2. rand(min: number, max: number): number

    • 生成指定范围内的随机整数
    • 包含最小值和最大值
    • 常用于随机选择、随机掉落等场景
  3. randRange(min: number, max: number): number

    • 生成指定范围内的随机浮点数
    • 包含最小值,不包含最大值
    • 常用于需要精确浮点随机数的场景
  4. rad(angle: number): number

    • 将角度转换为弧度
    • 计算公式:angle * Math.PI / 180
  5. deg(radian: number): number

    • 将弧度转换为角度
    • 计算公式:radian * 180 / Math.PI
  6. smooth(current: number, target: number, elapsedTime: number, responseTime: number): number

    • 计算平滑过渡的值
    • current: 当前值
    • target: 目标值
    • elapsedTime: 已经过时间(秒)
    • responseTime: 响应时间(秒)
    • 常用于实现平滑的相机移动、UI动画等

二、MD5

import { md5 } from 'kunpocc';

// 字符串 MD5 加密
const hash = md5('Hello, World!');
console.log(hash); // 输出32位MD5哈希值

// 注意:
// 1. 输入必须是字符串类型
// 2. 不能传入 undefined 或 null
try {
    md5(null);
} catch (error) {
    console.error('MD5输入不能为null或undefined');
}

三、数据结构

  • 二叉堆(BinaryHeap 最大、最小堆)
  • 单向(LinkedList)、双向链表 (DoublyLinkedList
  • 栈(Stack

四、适配相关 Adapter (不需要关心)

马住马住马住马住

:+1::+1::+1:

大喊666!

git给个星吧,感谢~

star了

爱你哟 :+1:

马克波罗!

mark,老哥2.4.x的版本的分支有么 :smiley:

2.4的没有

2.4是插件的形式用的 跟这个不一样

适合新人学习吗