Next-generation Entity Component System (ECS) game framework built with TypeScript, supporting multi-platform deployment. 下一代Entity Component System (ECS) 游戏框架,使用TypeScript构建,支持多平台运行。
npm install @esengine/nova-ecs
For complete API documentation, visit: https://esengine.github.io/NovaECS/ 完整的API文档请访问:https://esengine.github.io/NovaECS/
import { World, Entity, Component, System } from '@esengine/nova-ecs';
// Define components | 定义组件
class PositionComponent extends Component {
constructor(public x: number = 0, public y: number = 0) {
super();
}
}
class VelocityComponent extends Component {
constructor(public dx: number = 0, public dy: number = 0) {
super();
}
}
// Define systems | 定义系统
class MovementSystem extends System {
constructor() {
super([PositionComponent, VelocityComponent]);
}
update(entities: Entity[], deltaTime: number): void {
for (const entity of entities) {
const position = entity.getComponent(PositionComponent)!;
const velocity = entity.getComponent(VelocityComponent)!;
position.x += velocity.dx * deltaTime;
position.y += velocity.dy * deltaTime;
}
}
}
// Create world and systems | 创建世界和系统
const world = new World();
world.addSystem(new MovementSystem());
// Create entities | 创建实体
const entity = world.createEntity();
entity.addComponent(new PositionComponent(0, 0));
entity.addComponent(new VelocityComponent(1, 1));
// Game loop | 游戏循环
function gameLoop(deltaTime: number) {
world.update(deltaTime);
}
// Start game loop | 启动游戏循环
setInterval(() => gameLoop(16), 16);
NovaECS provides a powerful event system that supports loose coupling communication between systems. NovaECS 提供了强大的事件系统,支持系统间的松耦合通信。
import { Event, EventPriority } from '@esengine/nova-ecs';
// Define custom events | 定义自定义事件
class PlayerDeathEvent extends Event {
constructor(
public readonly playerId: number,
public readonly cause: string
) {
super('PlayerDeath', EventPriority.High);
}
}
// Use events in systems | 在系统中使用事件
class HealthSystem extends System {
onAddedToWorld(world: World): void {
super.onAddedToWorld(world);
// Subscribe to events | 订阅事件
this.subscribeToEventType(PlayerDeathEvent, (event) => {
console.log(`Player ${event.playerId} died: ${event.cause}`);
});
}
update(entities: Entity[], deltaTime: number): void {
for (const entity of entities) {
const health = entity.getComponent(HealthComponent)!;
if (health.current <= 0) {
// Dispatch events | 分发事件
this.dispatchEvent(new PlayerDeathEvent(entity.id, 'health depleted'));
}
}
}
}
Use component pools to optimize memory management: 使用组件对象池来优化内存管理:
import { ComponentPool } from '@esengine/nova-ecs';
// Create component pool | 创建组件池
const bulletPool = new ComponentPool(
() => new BulletComponent(),
{ initialSize: 50, maxSize: 200 }
);
// Acquire component from pool | 从池中获取组件
const bullet = bulletPool.acquire();
bullet.damage = 10;
bullet.speed = 100;
// Release component back to pool | 使用完毕后释放回池
bulletPool.release(bullet);
Query entities with specific component combinations: 查询具有特定组件组合的实体:
// Query entities with specific components | 查询具有特定组件的实体
const movableEntities = world.query({
all: [PositionComponent, VelocityComponent]
});
// Query entities with any of the components | 查询具有任一组件的实体
const renderableEntities = world.query({
any: [SpriteComponent, MeshComponent]
});
// Query entities excluding specific components | 查询排除特定组件的实体
const aliveEntities = world.query({
all: [HealthComponent],
none: [DeadComponent]
});
NovaECS provides a powerful query system that supports complex entity filtering, cache optimization, and performance monitoring. NovaECS 提供了强大的查询系统,支持复杂的实体筛选、缓存优化和性能监控。
// Fluent chaining query API | 流畅的链式查询API
const entities = world.query()
.with(PositionComponent, VelocityComponent) // Must contain components | 必须包含的组件
.without(DeadComponent) // Must not contain components | 必须不包含的组件
.execute();
// Using aliases | 使用别名
const entities2 = world.query()
.all(PositionComponent) // Equivalent to with() | 等同于 with()
.none(DeadComponent) // Equivalent to without() | 等同于 without()
.execute();
// Any component query (OR logic) | 任意组件查询(OR逻辑)
const combatants = world.query()
.any(PlayerComponent, EnemyComponent) // Contains any component | 包含任一组件
.without(DeadComponent)
.execute();
// Custom filters | 自定义过滤器
const lowHealthEntities = world.query()
.with(HealthComponent)
.filter(entity => {
const health = entity.getComponent(HealthComponent);
return health.current < health.max * 0.5;
})
.execute();
// Sorting and pagination | 排序和分页
const nearestEnemies = world.query()
.with(EnemyComponent, PositionComponent)
.sort((a, b) => {
// Sort by distance | 按距离排序
const posA = a.getComponent(PositionComponent);
const posB = b.getComponent(PositionComponent);
return calculateDistance(posA) - calculateDistance(posB);
})
.limit(5) // Take only first 5 | 只取前5个
.execute();
// Check if matching entities exist | 检查是否存在匹配的实体
const hasPlayer = world.query().with(PlayerComponent).exists();
// Get first matching entity | 获取第一个匹配的实体
const player = world.query().with(PlayerComponent).first();
// Count matching entities | 计算匹配的实体数量
const enemyCount = world.query().with(EnemyComponent).count();
// Get detailed query results | 获取详细的查询结果
const result = world.query()
.with(PositionComponent)
.executeWithMetadata();
console.log(`Found ${result.entities.length} entities`); // 找到 ${result.entities.length} 个实体
console.log(`Query time: ${result.executionTime}ms`); // 查询耗时: ${result.executionTime}ms
console.log(`From cache: ${result.fromCache}`); // 来自缓存: ${result.fromCache}
// Create base query | 创建基础查询
const baseQuery = world.query()
.with(EnemyComponent)
.without(DeadComponent);
// Clone and add additional conditions | 克隆并添加额外条件
const movingEnemies = baseQuery.clone()
.with(VelocityComponent)
.execute();
const stationaryEnemies = baseQuery.clone()
.without(VelocityComponent)
.execute();
// Configure query cache | 配置查询缓存
world.configureQueryCache({
maxSize: 100, // Maximum cache entries | 最大缓存条目数
ttl: 5000, // Cache time-to-live (milliseconds) | 缓存生存时间(毫秒)
evictionStrategy: 'lru' // Eviction strategy: lru, lfu, ttl | 淘汰策略:lru, lfu, ttl
});
// Get query statistics | 获取查询统计信息
const stats = world.getQueryStatistics();
console.log(`Total queries: ${stats.totalQueries}`); // 总查询次数: ${stats.totalQueries}
console.log(`Cache hit rate: ${stats.cacheHits / (stats.cacheHits + stats.cacheMisses)}`); // 缓存命中率: ${stats.cacheHits / (stats.cacheHits + stats.cacheMisses)}
console.log(`Average execution time: ${stats.averageExecutionTime}ms`); // 平均执行时间: ${stats.averageExecutionTime}ms
// Clear query cache | 清除查询缓存
world.clearQueryCache();
// Enable/disable performance monitoring | 启用/禁用性能监控
world.setQueryPerformanceMonitoring(true);
NovaECS provides a powerful plugin system that allows you to extend functionality in a modular way. NovaECS 提供了强大的插件系统,允许您以模块化的方式扩展功能。
import { BasePlugin, PluginPriority, World } from '@esengine/nova-ecs';
// Define a custom plugin | 定义自定义插件
class MyPlugin extends BasePlugin {
constructor() {
super({
name: 'MyPlugin',
version: '1.0.0',
description: 'My custom plugin',
priority: PluginPriority.Normal
});
}
async install(world: World): Promise<void> {
this.log('Plugin installed');
// Plugin installation logic | 插件安装逻辑
}
async uninstall(world: World): Promise<void> {
this.log('Plugin uninstalled');
// Plugin cleanup logic | 插件清理逻辑
}
update(deltaTime: number): void {
// Plugin update logic | 插件更新逻辑
}
}
// Install plugin | 安装插件
const world = new World();
const plugin = new MyPlugin();
const result = await world.plugins.install(plugin);
if (result.success) {
console.log('Plugin installed successfully');
} else {
console.error('Plugin installation failed:', result.error);
}
// Get plugin instance | 获取插件实例
const myPlugin = world.plugins.get<MyPlugin>('MyPlugin');
// Uninstall plugin | 卸载插件
await world.plugins.uninstall('MyPlugin');
class DependentPlugin extends BasePlugin {
constructor() {
super({
name: 'DependentPlugin',
version: '1.0.0',
description: 'Plugin with dependencies',
dependencies: ['MyPlugin'], // Required dependencies | 必需依赖
optionalDependencies: ['OptionalPlugin'], // Optional dependencies | 可选依赖
conflicts: ['ConflictingPlugin'] // Conflicting plugins | 冲突插件
});
}
async install(world: World): Promise<void> {
// Installation logic | 安装逻辑
}
async uninstall(world: World): Promise<void> {
// Uninstallation logic | 卸载逻辑
}
}
class LifecyclePlugin extends BasePlugin {
constructor() {
super({
name: 'LifecyclePlugin',
version: '1.0.0'
});
}
async install(world: World): Promise<void> {
// Plugin installation | 插件安装
}
async uninstall(world: World): Promise<void> {
// Plugin uninstallation | 插件卸载
}
// World lifecycle | 世界生命周期
onWorldCreate(world: World): void {
this.log('World created');
}
onWorldDestroy(world: World): void {
this.log('World destroyed');
}
// Entity lifecycle | 实体生命周期
onEntityCreate(entity: Entity): void {
this.log(`Entity ${entity.id} created`);
}
onEntityDestroy(entity: Entity): void {
this.log(`Entity ${entity.id} destroyed`);
}
// Component lifecycle | 组件生命周期
onComponentAdd(entity: Entity, component: Component): void {
this.log(`Component added to entity ${entity.id}`);
}
onComponentRemove(entity: Entity, component: Component): void {
this.log(`Component removed from entity ${entity.id}`);
}
// System lifecycle | 系统生命周期
onSystemAdd(system: System): void {
this.log(`System ${system.constructor.name} added`);
}
onSystemRemove(system: System): void {
this.log(`System ${system.constructor.name} removed`);
}
}
class ConfigurablePlugin extends BasePlugin {
constructor() {
super({
name: 'ConfigurablePlugin',
version: '1.0.0'
});
}
async install(world: World, options?: PluginInstallOptions): Promise<void> {
// Use configuration | 使用配置
const enabled = this.getConfigValue('enabled', true);
const maxItems = this.getConfigValue('maxItems', 100);
this.log(`Plugin enabled: ${enabled}, maxItems: ${maxItems}`);
}
validateConfig(config: Record<string, unknown>): boolean {
// Validate configuration | 验证配置
return typeof config.enabled === 'boolean' &&
typeof config.maxItems === 'number';
}
async uninstall(world: World): Promise<void> {
// Cleanup logic | 清理逻辑
}
}
// Install with configuration | 带配置安装
await world.plugins.install(new ConfigurablePlugin(), {
config: {
enabled: true,
maxItems: 200
}
});
import { PluginUtils } from '@esengine/nova-ecs';
// Create metadata with defaults | 创建带默认值的元数据
const metadata = PluginUtils.createMetadata({
name: 'MyPlugin',
version: '1.0.0'
});
// Validate metadata | 验证元数据
const validation = PluginUtils.validateMetadata(metadata);
if (!validation.valid) {
console.error('Invalid metadata:', validation.errors);
}
// Check version compatibility | 检查版本兼容性
const isCompatible = PluginUtils.isCompatible(plugin, '1.0.0');
// Create configuration validator | 创建配置验证器
const validator = PluginUtils.createConfigValidator({
enabled: { type: 'boolean', required: true },
count: { type: 'number', required: false }
});
// Install multiple plugins | 安装多个插件
const helper = PluginUtils.createInstallationHelper(world);
const result = await helper.installMany([plugin1, plugin2, plugin3]);
NovaECS provides a powerful serialization system that supports game save/load, network synchronization and other features. NovaECS 提供了强大的序列化系统,支持游戏保存/加载、网络同步等功能。
import { Serializer, SerializationUtils, SerializationFormat } from '@esengine/nova-ecs';
// Create serializer | 创建序列化器
const serializer = new Serializer();
// Register component types | 注册组件类型
serializer.registerComponentType('PositionComponent', PositionComponent);
serializer.registerComponentType('VelocityComponent', VelocityComponent);
// JSON serialization (human readable) | JSON 序列化(人类可读)
const jsonData = await SerializationUtils.toJSON(gameData, true);
const restored = await SerializationUtils.fromJSON(jsonData);
// Binary serialization (high performance, small size) | 二进制序列化(高性能,小体积)
const binaryData = await SerializationUtils.toBinary(gameData);
const restored2 = await SerializationUtils.fromBinary(binaryData);
// Deep clone objects | 深拷贝对象
const clone = SerializationUtils.clone(originalObject);
MIT License - See LICENSE file for details. MIT License - 详见 LICENSE 文件。
Issues and Pull Requests are welcome! 欢迎提交 Issue 和 Pull Request!
If you encounter problems during use, please: 如果您在使用过程中遇到问题,请: