ZryaJS 是一個極簡、可擴展、類 Flame 風格的 2D 遊戲引擎,基於 Canvas2D 渲染,包含:
- 世界/相機/組件體系
- 精靈渲染 & 文本渲染
- 輸入系統(Pointer / Keyboard)
- 粒子系統
- 特效系統(抖屏、閃爍)
- 物理引擎(基礎)
- 碰撞系統(AABB)
- Overlay 層
- Layout/UI
- LayerManager
- 資源緩存(ResourceCache)
- 事件系統(EventBus)
- Timer/Vec2/Rect 等工具類
- Devtools hook
- ImageComposition 工具
- 擴展/實驗特性系統
目錄
- 初始化遊戲
- 世界 & 相機
- 組件體系 Component
- SpriteComponent 精靈
- TextComponent 文本
- 輸入系統
- 碰撞系統
- 物理系統
- Overlay 系統
- 粒子系統
- Parallax 視差背景
- 特效系統
- LayerManager 圖層
- UI / Layout
- ResourceCache 緩存
- EventBus 事件系統
- Timer 定時器
- Math / Rect
- Devtools Hook
- Image Composer
- Extensions / Experimental
- 完整 Demo
初始化遊戲
import { ZryaGame, CanvasRenderer } from "zryajs";
const canvas = document.querySelector("canvas")!;
const renderer = new CanvasRenderer(canvas);
const game = new ZryaGame(renderer);
game.start();
世界 & 相機
World2D
世界是組件樹的根。
game.world.root.add(new Player());
CameraComponent
用來平移/縮放/旋轉世界。
import { CameraComponent } from "zryajs";
const camera = new CameraComponent();
camera.x = 200;
camera.y = 150;
camera.zoom = 1.2;
game.world.camera = camera;
組件體系 Component
所有東西都是 Component。
import { Component } from "zryajs";
class MyObject extends Component {
update(dt: number) {
console.log("每幀更新", dt);
}
}
生命週期:
onLoad()onMount()onRemove()
樹結構:
const parent = new Component();
const child = new Component();
parent.add(child);
SpriteComponent 精靈
支持圖片、canvas、ImageBitmap、video。
import { SpriteComponent } from "zryajs";
const sprite = new SpriteComponent();
sprite.texture = { image: myImage };
sprite.x = 100;
sprite.y = 200;
game.world.root.add(sprite);
裁剪:
sprite.texture = {
image: sheet,
sx: 32, sy: 0, sw: 32, sh: 32
};
TextComponent 文本
import { TextComponent } from "zryajs";
const txt = new TextComponent("Hello World", {
fontSize: 20,
color: "#ff0",
align: "center"
});
txt.x = 300;
txt.y = 80;
game.world.root.add(txt);
輸入系統
Pointer(鼠標/觸摸)
import { Pointer } from "zryajs";
game.pointer.onDown = (p) => console.log("點擊", p.x, p.y);
Keyboard
game.keyboard.onKeyDown = (key) => {
if (key === "Space") console.log("Jump!");
};
碰撞系統
Hitbox(AABB)
import { Hitbox } from "zryajs";
class Block extends Hitbox {
constructor() {
super({
type: "aabb",
offsetX: 0,
offsetY: 0,
width: 40,
height: 40
});
}
onCollisionStart(other) {
console.log("撞到了:", other);
}
}
掛載後自動參與碰撞檢測。
CollisionSystem
ZryaGame 自動包含:
game.collisionSystem.step(world);
無需手動調用。
物理系統
基礎物理支持:
- 重力
- 速度/加速度
- 阻尼
- 簡易地面檢測
import { PhysicsBody } from "zryajs";
class Player extends PhysicsBody {
constructor() {
super();
this.gravity = 1000;
}
update(dt) {
if (game.keyboard.isDown("Space") && this.onGround)
this.velocityY = -400;
}
}
Overlay 系統
顯示 UI 層、暫停菜單等。
import { OverlayManager } from "zryajs";
game.overlays.show("pauseMenu");
game.overlays.hide("pauseMenu");
粒子系統
兩部分:
ParticleSystemParticleEmitterComponent
使用粒子發射器
import { ParticleEmitterComponent } from "zryajs";
const emitter = new ParticleEmitterComponent({
rate: 20,
life: [0.3, 0.6],
speed: [50, 120],
angle: [0, Math.PI * 2],
color: "orange"
});
emitter.x = 200;
emitter.y = 300;
game.world.root.add(emitter);
Parallax 視差背景
import { ParallaxComponent } from "zryajs";
const layer = new ParallaxComponent({
image: bgImage,
factorX: 0.5,
factorY: 0
});
game.world.root.add(layer);
特效系統
所有特效由 EffectManager 調用。
CameraShake
import { CameraShakeEffect } from "zryajs";
game.effects.add(new CameraShakeEffect({
duration: 0.3,
strength: 8
}));
BlinkEffect(閃爍)
import { BlinkEffect } from "zryajs";
game.effects.add(new BlinkEffect(player, {
duration: 0.2
}));
LayerManager 圖層
允許按渲染順序分層。
import { LayerManager } from "zryajs";
game.layers.add("bg");
game.layers.add("game");
game.layers.add("ui");
UI / Layout
LayoutComponent
自動對子組件定位。
import { LayoutComponent } from "zryajs";
const layout = new LayoutComponent("horizontal", 10);
layout.add(new TextComponent("A"));
layout.add(new TextComponent("B"));
game.world.root.add(layout);
UiElement
基礎 UI 元素(大小、佈局、anchor)。
ResourceCache 緩存
import { ResourceCache } from "zryajs";
const images = new ResourceCache<string, HTMLImageElement>(async (url) => {
const img = new Image();
img.src = url;
await img.decode();
return img;
});
const playerImg = await images.getOrLoad("/player.png");
EventBus 事件系統
import { EventBus } from "zryajs";
const bus = new EventBus();
bus.on("damage", (v) => console.log("Damage:", v));
bus.emit("damage", 10);
Timer 定時器
import { Timer } from "zryajs";
const timer = new Timer(1.0, () => console.log("1 秒到了"));
timer.repeat = true;
game.timers.add(timer);
Math / Rect / Vec2
import { Vec2, Rect } from "zryajs";
const v = new Vec2(10, 5).normalized();
const r = new Rect(0, 0, 100, 50);
Devtools Hook
允許外部調試器掛載遊戲狀態。
import { DevtoolsHook } from "zryajs";
DevtoolsHook.expose(game);
Image Composer
將多個 sprite 合成一張圖。
import { ImageComposer } from "zryajs";
const out = await ImageComposer.compose([
{ image: img1, x: 0, y: 0 },
{ image: img2, x: 100, y: 50 }
]);
Extensions / Experimental
import { ExperimentalFeatureFlag } from "zryajs";
ExperimentalFeatureFlag.enable("fast-collision");
完整 Demo
import {
ZryaGame, CanvasRenderer,
SpriteComponent, TextComponent,
CameraComponent, PhysicsBody,
ParticleEmitterComponent, CameraShakeEffect
} from "zryajs";
const canvas = document.querySelector("canvas")!;
const game = new ZryaGame(new CanvasRenderer(canvas));
// 玩家
class Player extends PhysicsBody {
constructor() {
super();
this.gravity = 1400;
this.width = 40;
this.height = 40;
}
update(dt) {
if (game.keyboard.isDown("ArrowLeft")) this.velocityX -= 600 * dt;
if (game.keyboard.isDown("ArrowRight")) this.velocityX += 600 * dt;
if (game.keyboard.isDown("Space") && this.onGround)
this.velocityY = -600;
if (Math.abs(this.velocityX) > 300) {
game.effects.add(new CameraShakeEffect({ duration: 0.1, strength: 4 }));
}
}
}
// 地板
class Ground extends PhysicsBody {
constructor() {
super();
this.static = true;
this.width = 600;
this.height = 30;
}
}
const camera = new CameraComponent();
game.world.camera = camera;
// 添加對象
const player = new Player();
player.x = 200;
player.y = 100;
const ground = new Ground();
ground.x = 300;
ground.y = 350;
game.world.root.add(ground);
game.world.root.add(player);
// 跟隨
camera.follow(player);
game.start();
ZyraJs版本號
import { zryaJsVersion } from "zryajs";
console.log(zryaJsVersion());