npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

you-engine

v0.2.0

Published

A lightweight, pluggable 2D Canvas game framework

Downloads

262

Readme

You Engine

一个轻量级、可插拔的 2D Canvas 游戏框架。

English | 中文

简介

You Engine 是一个现代化的 TypeScript 游戏引擎,专为 2D Canvas 游戏设计。它采用模块化的系统架构,让你可以只引入需要的功能,保持项目精简。

特性

  • 轻量级: 核心模块仅几 KB,按需加载
  • TypeScript 原生: 完整的类型支持,智能提示
  • ECS 架构: 基于 miniplex 的轻量级实体组件系统
  • 可插拔系统: 输入、渲染、物理、音频、粒子等系统按需使用
  • 手柄支持: 支持 Xbox、PlayStation、Switch 等多种控制器
  • 物理引擎: 内置简单碰撞和 Matter.js 集成
  • 动画系统: 基于 tween.js 的缓动动画
  • 音频系统: 基于 Howler.js 的音效管理
  • 粒子系统: 内置多种预设特效
  • 等距视角系统: 2.5D 等距渲染,适用于 RTS/ARPG 游戏

安装

pnpm add you-engine

快速开始

import { Engine, InputSystem, RenderSystem, CameraSystem } from 'you-engine';

// 创建引擎
const engine = new Engine({
  canvas: '#gameCanvas',
  width: 1600,
  height: 900,
  backgroundColor: '#1a1a2e'
});

// 注册系统
engine
  .use(InputSystem)
  .use(CameraSystem)
  .use(RenderSystem);

// 创建实体
const player = engine.spawn({
  transform: { x: 400, y: 300, rotation: 0, scaleX: 1, scaleY: 1 },
  velocity: { x: 0, y: 0 },
  sprite: { width: 32, height: 32, color: '#4ecdc4', alpha: 1, visible: true },
  collider: { type: 'circle', radius: 16 }
});

// 启动游戏
engine.start();

核心概念

Engine(引擎)

引擎是游戏的核心,负责管理游戏循环、系统和场景。

const engine = new Engine({
  canvas: HTMLCanvasElement | string,  // Canvas 元素或选择器
  width?: number,           // 设计宽度,默认 1600
  height?: number,          // 设计高度,默认 900
  backgroundColor?: string, // 背景色,默认 '#000'
  autoScale?: boolean,      // 自动缩放,默认 true
  targetFPS?: number,       // 目标帧率,默认 60
  debug?: boolean           // 调试模式,默认 false
});

Entity(实体)

实体是游戏对象,由多个组件组成。

interface GameEntity {
  id?: string;              // 实体 ID
  transform?: Transform;    // 变换组件
  velocity?: Velocity;      // 速度组件
  sprite?: Sprite;          // 精灵组件
  collider?: Collider;      // 碰撞体组件
  lifecycle?: Lifecycle;    // 生命周期组件
  tags?: Tags;              // 标签组件
  onUpdate?: (dt: number) => void;    // 自定义更新
  onRender?: (ctx: CanvasRenderingContext2D) => void;  // 自定义渲染
  onDestroy?: () => void;   // 销毁回调
}

Component(组件)

组件是数据容器,定义实体的属性。

Transform(变换)

interface Transform {
  x: number;
  y: number;
  rotation: number;   // 弧度
  scaleX: number;
  scaleY: number;
}

// 辅助函数
import { createTransform } from 'you-engine';
const transform = createTransform(100, 200);  // x, y, rotation=0, scaleX=1, scaleY=1

Velocity(速度)

interface Velocity {
  x: number;
  y: number;
  angularVelocity?: number;  // 角速度
  damping?: number;          // 阻尼 (0-1)
}

// 辅助函数
import { createVelocity } from 'you-engine';
const velocity = createVelocity(5, 0);  // x, y

Sprite(精灵)

interface Sprite {
  texture?: string;         // 纹理(暂未实现)
  width: number;
  height: number;
  color?: string;           // 填充颜色
  alpha: number;            // 透明度 (0-1)
  visible: boolean;
  render?: (ctx, entity) => void;  // 自定义渲染
}

// 辅助函数
import { createSprite } from 'you-engine';
const sprite = createSprite({ width: 32, height: 32, color: '#ff0000' });

Collider(碰撞体)

interface Collider {
  type: 'circle' | 'rect';
  radius?: number;          // 圆形半径
  width?: number;           // 矩形宽度
  height?: number;          // 矩形高度
  layer?: number;           // 碰撞层(位掩码)
  mask?: number;            // 碰撞掩码
  isTrigger?: boolean;      // 是否为触发器
  offsetX?: number;         // X 偏移
  offsetY?: number;         // Y 偏移
}

// 辅助函数
import { createCollider } from 'you-engine';
const circleCollider = createCollider('circle', { radius: 16 });
const rectCollider = createCollider('rect', { width: 32, height: 32 });

Tags(标签)

标签用于对实体进行分类和查询。

interface Tags {
  values: string[];  // 标签数组
}

// 使用辅助函数
import { hasTag, addTag } from 'you-engine';

// 创建带标签的实体
const player = engine.spawn({
  transform: createTransform(100, 100),
  tags: { values: ['player', 'movable'] }
});

// 检查标签
if (hasTag(player, 'player')) {
  // ...
}

// 添加标签
addTag(player, 'invincible');

// 按标签查询实体
const players = engine.world.entities.filter(
  e => e.tags?.values.includes('player')
);

System(系统)

系统是逻辑处理器,负责更新实体和处理游戏逻辑。

import { System } from 'you-engine';

class MySystem extends System {
  static priority = 0;  // 优先级,越小越先执行

  onCreate(): void {
    // 系统初始化
  }

  onUpdate(dt: number): void {
    // 每帧更新,dt 是毫秒
    for (const entity of this.engine.world.entities) {
      // 处理实体
    }
  }

  onRender(ctx: CanvasRenderingContext2D): void {
    // 渲染
  }

  onDestroy(): void {
    // 系统销毁
  }
}

// 注册系统
engine.use(MySystem);

Scene(场景)

场景用于组织游戏关卡和状态。

import { Scene } from 'you-engine';

class GameScene extends Scene {
  onCreate(): void {
    // 场景创建时调用(只调用一次)
  }

  onEnter(): void {
    // 进入场景时调用
    const player = this.spawn({
      transform: createTransform(100, 100),
      sprite: createSprite({ width: 32, height: 32, color: '#fff' })
    });
  }

  onUpdate(dt: number): void {
    // 每帧更新
  }

  onExit(): void {
    // 离开场景时调用
  }
}

// 注册场景
engine.addScene('game', GameScene);

// 切换场景
engine.goto('game');

内置系统

InputSystem(输入系统)

处理键盘和手柄输入。

import { InputSystem, GamepadButton } from 'you-engine';

engine.use(InputSystem);

// 获取系统实例
const input = engine.system(InputSystem);

// 检查动作
if (input.isPressed('jump')) {
  // 跳跃键刚按下
}

if (input.isHeld('fire')) {
  // 开火键按住中
}

if (input.isReleased('dash')) {
  // 冲刺键刚释放
}

// 获取轴值 (-1 到 1)
const moveX = input.axisX();  // 水平移动
const moveY = input.axisY();  // 垂直移动

// 手柄震动
input.vibrate(0, { strong: 0.5, weak: 0.3, duration: 200 });

// 获取手柄类型
const type = input.getGamepadType(0);  // 'xbox' | 'playstation' | 'switch' | 'generic'

// 获取按钮显示名称
const buttonName = input.getButtonName(GamepadButton.A, 0);  // Xbox: 'A', PS: '✕', Switch: 'B'

// 自定义输入映射
input.setMapping('attack', {
  keyboard: ['KeyJ', 'Space'],
  gamepadButton: [0, 2]
});

RenderSystem(渲染系统)

渲染带有 sprite 组件的实体。

import { RenderSystem } from 'you-engine';

engine.use(RenderSystem);

const render = engine.system(RenderSystem);

// 显示碰撞体调试
render.showColliders = true;
render.showDebug = true;

// 静态绘图方法
RenderSystem.drawCircle(ctx, x, y, radius, { fill: '#fff', stroke: '#000' });
RenderSystem.drawRect(ctx, x, y, w, h, { fill: '#fff', centered: true });
RenderSystem.drawLine(ctx, x1, y1, x2, y2, { color: '#fff', lineWidth: 2 });
RenderSystem.drawText(ctx, 'Hello', x, y, { font: '24px Arial', color: '#fff' });

CameraSystem(摄像机系统)

摄像机控制,支持跟随、震屏、缩放等效果。

import { CameraSystem } from 'you-engine';

engine.use(CameraSystem);

const camera = engine.system(CameraSystem);

// 设置位置
camera.setPosition(400, 300);

// 平滑移动
camera.moveTo(800, 600);

// 跟随实体
camera.follow(player, { smoothing: 0.1, offsetX: 0, offsetY: -50 });

// 停止跟随
camera.unfollow();

// 震屏效果
camera.shake({ intensity: 20, decay: 0.9 });

// 闪屏效果
camera.flash({ color: '#fff', duration: 100, alpha: 0.8 });

// 缩放
camera.zoomTo(1.5);

// 设置边界
camera.setBounds(0, 0, 3200, 1800);

// 坐标转换
const worldPos = camera.screenToWorld(mouseX, mouseY);
const screenPos = camera.worldToScreen(entity.transform.x, entity.transform.y);

// 检查是否在视口内
if (camera.isInView(x, y, margin)) {
  // 在视口内
}

PhysicsSystem(物理系统)

简单的碰撞检测和物理模拟。

import { PhysicsSystem } from 'you-engine';

engine.use(PhysicsSystem);

const physics = engine.system(PhysicsSystem);

// 设置重力
physics.gravity = { x: 0, y: 980 };

// 碰撞检测
physics.onCollision((pair) => {
  console.log('碰撞:', pair.a, pair.b);
  // pair.normalX, pair.normalY - 碰撞法线
  // pair.depth - 穿透深度
});

// 分离碰撞体
physics.separate(pair, 0.5);  // 各分离 50%

// 弹性碰撞响应
physics.bounce(pair, 0.8);  // 弹性系数

// 射线检测
const hit = physics.raycast(startX, startY, dirX, dirY, maxDistance);
if (hit) {
  console.log('击中:', hit.entity, hit.point, hit.distance);
}

// 点检测
if (physics.pointInEntity(mouseX, mouseY, entity)) {
  // 点在实体内
}

MatterPhysicsSystem(Matter.js 物理)

完整的 2D 物理模拟,基于 Matter.js。

import { MatterPhysicsSystem } from 'you-engine';

engine.use(MatterPhysicsSystem);

const matter = engine.system(MatterPhysicsSystem);

// 为实体添加物理体
matter.addBody(entity, {
  type: 'dynamic',      // 'dynamic' | 'static' | 'kinematic'
  shape: 'circle',      // 'circle' | 'rect' | 'polygon'
  radius: 20,
  mass: 1,
  friction: 0.1,
  restitution: 0.8,     // 弹性
  fixedRotation: false
});

// 设置重力
matter.gravity = { x: 0, y: 1 };

// 施加力
matter.applyForce(entity, { x: 100, y: 0 });

// 施加冲量
matter.applyImpulse(entity, { x: 50, y: -100 });

// 设置速度
matter.setVelocity(entity, { x: 10, y: 0 });

// 创建约束(连接两个物体)
const constraint = matter.createConstraint(entityA, entityB, {
  stiffness: 0.9,
  damping: 0.1
});

// 碰撞事件
engine.on('matter:collisionStart', ({ a, b }) => {
  console.log('开始碰撞:', a, b);
});

engine.on('matter:collisionEnd', ({ a, b }) => {
  console.log('结束碰撞:', a, b);
});

AudioSystem(音频系统)

音效和背景音乐管理,基于 Howler.js。

import { AudioSystem } from 'you-engine';

engine.use(AudioSystem);

const audio = engine.system(AudioSystem);

// 加载音效
await audio.loadSound('explosion', { src: '/sounds/explosion.mp3' });
await audio.loadSound('coin', { src: ['/sounds/coin.mp3', '/sounds/coin.ogg'] });

// 加载音乐
await audio.loadMusic('bgm', { src: '/music/bgm.mp3', loop: true });

// 批量加载
await audio.loadAll({
  sounds: {
    jump: { src: '/sounds/jump.mp3' },
    hit: { src: '/sounds/hit.mp3' }
  },
  music: {
    menu: { src: '/music/menu.mp3' },
    game: { src: '/music/game.mp3' }
  }
});

// 播放音效
audio.playSound('explosion', { volume: 0.8, rate: 1.2 });

// 播放音乐
audio.playMusic('bgm', { fadeIn: 1000 });

// 停止音乐
audio.stopMusic({ fadeOut: 500 });

// 暂停/恢复
audio.pauseMusic();
audio.resumeMusic();

// 音量控制
audio.masterVolume = 0.8;   // 主音量
audio.sfxVolume = 1.0;      // 音效音量
audio.musicVolume = 0.5;    // 音乐音量

// 静音
audio.muted = true;

// 解锁音频(移动端需要用户交互)
await audio.unlock();

TweenSystem(缓动系统)

动画和缓动效果,基于 @tweenjs/tween.js。

import { TweenSystem, Easing } from 'you-engine';

engine.use(TweenSystem);

const tween = engine.system(TweenSystem);

// 基本动画
tween.to(entity.transform, { x: 500, y: 300 }, {
  duration: 1000,
  easing: Easing.QuadOut,
  onUpdate: () => console.log('更新中'),
  onComplete: () => console.log('完成')
});

// 便捷方法
tween.moveTo(entity.transform, 500, 300, 1000);
tween.scaleTo(entity.transform, 2, 2, 500);
tween.rotateTo(entity.transform, Math.PI, 800);

// 精灵动画
tween.fadeIn(entity.sprite, 500);
tween.fadeOut(entity.sprite, 500);

// 特效
tween.bounce(entity.transform, 0.2, 300);  // 弹跳
tween.shake(entity.transform, 10, 500);    // 抖动
tween.pulse(entity.transform, 1.2, 300);   // 脉冲

// 链式动画
tween.chain(entity.transform, [
  { target: { x: 100 }, options: { duration: 500 } },
  { target: { y: 200 }, options: { duration: 500 } },
  { target: { x: 0, y: 0 }, options: { duration: 1000, easing: Easing.BounceOut } }
]);

// 延迟执行
await tween.delay(1000);

// 数值动画
tween.animate(0, 100, 1000, (value) => {
  healthBar.width = value;
});

// 可用的缓动函数
// Linear, QuadIn/Out/InOut, CubicIn/Out/InOut, QuartIn/Out/InOut
// QuintIn/Out/InOut, SineIn/Out/InOut, ExpoIn/Out/InOut, CircIn/Out/InOut
// ElasticIn/Out/InOut, BackIn/Out/InOut, BounceIn/Out/InOut

ParticleSystem(粒子系统)

粒子效果,内置多种预设。

import { ParticleSystem } from 'you-engine';

engine.use(ParticleSystem);

const particles = engine.system(ParticleSystem);

// 创建发射器
const emitter = particles.createEmitter({
  x: 400,
  y: 300,
  rate: 20,              // 每秒发射数
  maxParticles: 100,
  life: [500, 1000],     // 生命周期(毫秒)
  speed: [50, 150],      // 速度范围
  angle: [0, Math.PI * 2],  // 发射角度范围
  startSize: [5, 10],    // 初始大小
  endSize: [0, 2],       // 结束大小
  startColor: ['#ff0', '#f80'],  // 初始颜色(随机选择)
  endColor: '#f00',      // 结束颜色
  gravity: 200,          // 重力
  drag: 0.1,             // 阻力
  blendMode: 'lighter'   // 混合模式
});

// 更新发射器位置
emitter.config.x = player.transform.x;
emitter.config.y = player.transform.y;

// 停止发射器
particles.stopEmitter(emitter);
particles.stopEmitter(emitter, true);  // 立即清除所有粒子

// 预设特效
particles.explode(x, y);                // 爆炸
particles.smoke(x, y);                  // 烟雾
particles.fire(x, y);                   // 火焰
particles.sparkle(x, y);                // 闪光
particles.trail(x, y);                  // 轨迹

// 自定义预设参数
particles.explode(x, y, {
  burst: 50,
  startColor: ['#00f', '#0ff'],
  gravity: 100
});

// 全局重力
particles.gravity = { x: 0, y: 100 };

// 统计
console.log('粒子数:', particles.getParticleCount());
console.log('发射器数:', particles.getEmitterCount());

IsometricSystem(等距视角系统)

2.5D 等距渲染,适用于 RTS、ARPG、模拟经营等游戏(如红警、暗黑、帝国时代)。

import {
  IsometricSystem,
  IsometricRenderSystem,
  createIsometricTransform,
  createIsometricSprite
} from 'you-engine';

engine.use(IsometricSystem);
engine.use(IsometricRenderSystem);

const iso = engine.system(IsometricSystem);
const isoRender = engine.system(IsometricRenderSystem);

// 配置等距参数
iso.setConfig({
  tileWidth: 64,          // 地块宽度
  tileHeight: 32,         // 地块高度(通常是宽度的一半)
  heightScale: 32,        // 高度单位像素值
  depthSortEnabled: true, // 启用深度排序
  shadow: {
    enabled: true,
    color: 'rgba(0, 0, 0, 0.3)',
    heightFade: 0.02      // 阴影随高度淡化
  }
});

// 创建等距实体
const unit = engine.spawn({
  transform: createIsometricTransform(5, 3, 0),  // x, y, z(高度)
  sprite: createIsometricSprite({
    width: 64,
    height: 96,
    color: '#4ecdc4',
    anchorX: 0.5,    // 锚点 X(中心)
    anchorY: 1,      // 锚点 Y(底部)- 等距游戏通常锚点在脚底
    castShadow: true
  })
});

// 坐标转换
const screen = iso.worldToScreen(5, 3, 0);      // 世界坐标 -> 屏幕坐标
const world = iso.screenToWorld(mouseX, mouseY); // 屏幕坐标 -> 世界坐标
const tile = iso.screenToTile(mouseX, mouseY);   // 屏幕坐标 -> 格子坐标

// 摄像机控制
iso.setCameraPosition(10, 10);           // 设置摄像机位置(世界坐标)
iso.followEntity(player, 0.1);           // 跟随实体
iso.cameraZoom = 1.5;                    // 缩放
iso.moveCamera(dx, dy);                  // 移动摄像机

// 绘制等距方块
iso.drawIsometricBox(ctx, x, y, z, width, depth, height, {
  topColor: '#888',
  leftColor: '#666',
  rightColor: '#555'
});

// 绘制等距圆柱体(适合角色)
iso.drawIsometricCylinder(ctx, x, y, z, radius, height, {
  topColor: '#888',
  bodyColor: '#666',
  bodyGradient: true
});

// 绘制地面网格
iso.drawGrid(ctx, 0, 0, 10, 10, {
  lineColor: 'rgba(255, 255, 255, 0.2)',
  highlightTile: { x: 5, y: 3 },
  highlightColor: 'rgba(255, 255, 0, 0.3)'
});

// 绘制阴影
iso.drawShadow(ctx, x, y, z, radius);

// 检查是否在屏幕内
if (iso.isOnScreen(screenX, screenY, margin)) {
  // 渲染实体
}

// 渲染系统设置
isoRender.showGrid = true;   // 显示网格
isoRender.showDebug = true;  // 显示调试信息(坐标、深度值)

// 便捷渲染方法
isoRender.drawBox(ctx, x, y, z, size, height, '#ff6600');
isoRender.drawCharacter(ctx, x, y, z, radius, height, '#4ecdc4');

数学工具

Vec2(2D 向量)

import { Vec2 } from 'you-engine';

const v1 = new Vec2(10, 20);
const v2 = Vec2.from({ x: 5, y: 5 });

// 运算
v1.add(v2);           // 加法
v1.sub(v2);           // 减法
v1.scale(2);          // 缩放
v1.normalize();       // 归一化
v1.rotate(Math.PI/4); // 旋转

// 属性
v1.length;            // 长度
v1.lengthSq;          // 长度平方
v1.angle;             // 角度

// 静态方法
Vec2.distance(v1, v2);
Vec2.dot(v1, v2);
Vec2.cross(v1, v2);
Vec2.lerp(v1, v2, 0.5);
Vec2.reflect(v1, normal);

MathUtils(数学工具)

import { clamp, lerp, smoothstep, degToRad, radToDeg, randomFloat, randomInt, randomChoice } from 'you-engine';

// 范围限制
clamp(value, min, max);

// 线性插值
lerp(a, b, t);

// 平滑插值
smoothstep(a, b, t);

// 角度转换
degToRad(90);   // 1.5707...
radToDeg(Math.PI);  // 180

// 随机数
randomFloat(0, 100);
randomInt(1, 10);
randomChoice(['a', 'b', 'c']);

// 阻尼
damp(current, target, smoothing, dt);

// 循环
wrap(value, min, max);

// 来回
pingPong(t, length);

事件系统

// 发送事件
engine.emit('player:death', { playerId: 0 });

// 监听事件
const subscription = engine.on('player:death', (data) => {
  console.log('玩家死亡:', data.playerId);
});

// 取消监听
subscription.unsubscribe();

// 一次性监听
engine.once('game:start', () => {
  console.log('游戏开始');
});

对象池

用于优化频繁创建/销毁的对象。

import { ObjectPool } from 'you-engine';

// 创建对象池
const bulletPool = new ObjectPool({
  create: () => ({ x: 0, y: 0, vx: 0, vy: 0, active: false }),
  reset: (bullet) => { bullet.x = 0; bullet.y = 0; },
  initialSize: 100,
  maxSize: 500
});

// 或简单用法
const pool = new ObjectPool(() => ({ value: 0 }));

// 获取对象
const bullet = bulletPool.acquire();
bullet.x = player.x;
bullet.y = player.y;

// 归还对象
bulletPool.release(bullet);

// 统计
console.log('活跃:', bulletPool.activeCount);
console.log('可用:', bulletPool.availableCount);

完整示例

import {
  Engine, Scene,
  InputSystem, RenderSystem, CameraSystem, PhysicsSystem,
  ParticleSystem, AudioSystem, TweenSystem,
  createTransform, createVelocity, createSprite, createCollider,
  Vec2, Easing
} from 'you-engine';

// 创建引擎
const engine = new Engine({
  canvas: '#game',
  width: 1280,
  height: 720,
  backgroundColor: '#1a1a2e'
});

// 注册系统
engine
  .use(InputSystem)
  .use(PhysicsSystem)
  .use(CameraSystem)
  .use(TweenSystem)
  .use(ParticleSystem)
  .use(AudioSystem)
  .use(RenderSystem);

// 定义游戏场景
class GameScene extends Scene {
  player: any;

  async onEnter() {
    const audio = this.getSystem(AudioSystem);
    await audio.loadAll({
      sounds: { jump: { src: '/sounds/jump.mp3' } }
    });

    // 创建玩家
    this.player = this.spawn({
      transform: createTransform(640, 360),
      velocity: createVelocity(),
      sprite: createSprite({ width: 48, height: 48, color: '#4ecdc4' }),
      collider: createCollider('circle', { radius: 24 })
    });

    // 摄像机跟随
    const camera = this.getSystem(CameraSystem);
    camera.follow(this.player, { smoothing: 0.08 });
  }

  onUpdate(dt: number) {
    const input = this.getSystem(InputSystem);
    const { transform, velocity } = this.player;

    // 移动
    velocity.x = input.axisX() * 300;
    velocity.y = input.axisY() * 300;

    // 跳跃/动作
    if (input.isPressed('jump')) {
      const audio = this.getSystem(AudioSystem);
      audio.playSound('jump');

      const particles = this.getSystem(ParticleSystem);
      particles.explode(transform.x, transform.y + 24);
    }
  }
}

// 注册并启动
engine.addScene('game', GameScene);
engine.start('game');

构建

# 开发
pnpm dev

# 构建
pnpm build

# 预览
pnpm preview

许可证

MIT License