@codehz/ecs 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +17 -17
- package/README.md +16 -16
- package/package.json +5 -3
package/README.en.md
CHANGED
|
@@ -30,25 +30,25 @@ import { World, component } from "@codehz/ecs";
|
|
|
30
30
|
type Position = { x: number; y: number };
|
|
31
31
|
type Velocity = { x: number; y: number };
|
|
32
32
|
|
|
33
|
-
// Define
|
|
34
|
-
const
|
|
35
|
-
const
|
|
33
|
+
// Define components (auto-assigned)
|
|
34
|
+
const Position = component<Position>();
|
|
35
|
+
const Velocity = component<Velocity>();
|
|
36
36
|
|
|
37
37
|
// Create world
|
|
38
38
|
const world = new World();
|
|
39
39
|
|
|
40
40
|
// Create entity and set components (all changes buffered until sync())
|
|
41
41
|
const entity = world.new();
|
|
42
|
-
world.set(entity,
|
|
43
|
-
world.set(entity,
|
|
42
|
+
world.set(entity, Position, { x: 0, y: 0 });
|
|
43
|
+
world.set(entity, Velocity, { x: 1, y: 0.5 });
|
|
44
44
|
world.sync();
|
|
45
45
|
|
|
46
46
|
// Create reusable query
|
|
47
|
-
const query = world.createQuery([
|
|
47
|
+
const query = world.createQuery([Position, Velocity]);
|
|
48
48
|
|
|
49
49
|
// Update loop
|
|
50
50
|
const deltaTime = 1.0 / 60.0;
|
|
51
|
-
query.forEach([
|
|
51
|
+
query.forEach([Position, Velocity], (entity, position, velocity) => {
|
|
52
52
|
position.x += velocity.x * deltaTime;
|
|
53
53
|
position.y += velocity.y * deltaTime;
|
|
54
54
|
});
|
|
@@ -87,7 +87,7 @@ const ChildOf = component({ exclusive: true, name: "ChildOf" });
|
|
|
87
87
|
|
|
88
88
|
```typescript
|
|
89
89
|
// Returns an unlisten function
|
|
90
|
-
const unhook = world.hook([
|
|
90
|
+
const unhook = world.hook([Position, Velocity], {
|
|
91
91
|
on_init: (entityId, position, velocity) => {
|
|
92
92
|
// Called for every entity that already matches when the hook is registered
|
|
93
93
|
},
|
|
@@ -105,7 +105,7 @@ unhook();
|
|
|
105
105
|
A shorthand callback form is also supported:
|
|
106
106
|
|
|
107
107
|
```typescript
|
|
108
|
-
const unhook = world.hook([
|
|
108
|
+
const unhook = world.hook([Position, Velocity], (type, entityId, position, velocity) => {
|
|
109
109
|
if (type === "init") console.log("init");
|
|
110
110
|
if (type === "set") console.log("set");
|
|
111
111
|
if (type === "remove") console.log("remove");
|
|
@@ -116,7 +116,7 @@ Optional components and filters:
|
|
|
116
116
|
|
|
117
117
|
```typescript
|
|
118
118
|
// Optional component: the hook fires even if Velocity is absent
|
|
119
|
-
world.hook([
|
|
119
|
+
world.hook([Position, { optional: Velocity }], {
|
|
120
120
|
on_set: (entityId, position, velocity) => {
|
|
121
121
|
if (velocity !== undefined) {
|
|
122
122
|
console.log("has velocity and position");
|
|
@@ -127,14 +127,14 @@ world.hook([PositionId, { optional: VelocityId }], {
|
|
|
127
127
|
});
|
|
128
128
|
|
|
129
129
|
// Filter: exclude entities with specified negative components
|
|
130
|
-
const
|
|
130
|
+
const Disabled = component<void>();
|
|
131
131
|
world.hook(
|
|
132
|
-
[
|
|
132
|
+
[Position, Velocity],
|
|
133
133
|
{
|
|
134
134
|
on_set: (entityId, position, velocity) => console.log("entered matching set"),
|
|
135
135
|
on_remove: (entityId, position, velocity) => console.log("exited matching set"),
|
|
136
136
|
},
|
|
137
|
-
{ negativeComponentTypes: [
|
|
137
|
+
{ negativeComponentTypes: [Disabled] },
|
|
138
138
|
);
|
|
139
139
|
```
|
|
140
140
|
|
|
@@ -164,10 +164,10 @@ console.log(world.has(child, relation(ChildOf, parent2))); // true
|
|
|
164
164
|
|
|
165
165
|
```typescript
|
|
166
166
|
import { World, component, relation } from "@codehz/ecs";
|
|
167
|
-
const
|
|
167
|
+
const Position = component<Position>();
|
|
168
168
|
|
|
169
169
|
const world = new World();
|
|
170
|
-
const wildcardPos = relation(
|
|
170
|
+
const wildcardPos = relation(Position, "*");
|
|
171
171
|
|
|
172
172
|
// Listen for changes to all relations of this type
|
|
173
173
|
world.hook([wildcardPos], {
|
|
@@ -362,11 +362,11 @@ import { pipeline } from "@codehz/pipeline";
|
|
|
362
362
|
import { World, component } from "@codehz/ecs";
|
|
363
363
|
|
|
364
364
|
const world = new World();
|
|
365
|
-
const movementQuery = world.createQuery([
|
|
365
|
+
const movementQuery = world.createQuery([Position, Velocity]);
|
|
366
366
|
|
|
367
367
|
const gameLoop = pipeline<{ deltaTime: number }>()
|
|
368
368
|
.addPass((env) => {
|
|
369
|
-
movementQuery.forEach([
|
|
369
|
+
movementQuery.forEach([Position, Velocity], (entity, position, velocity) => {
|
|
370
370
|
position.x += velocity.x * env.deltaTime;
|
|
371
371
|
position.y += velocity.y * env.deltaTime;
|
|
372
372
|
});
|
package/README.md
CHANGED
|
@@ -31,24 +31,24 @@ type Position = { x: number; y: number };
|
|
|
31
31
|
type Velocity = { x: number; y: number };
|
|
32
32
|
|
|
33
33
|
// 定义组件 ID(自动分配)
|
|
34
|
-
const
|
|
35
|
-
const
|
|
34
|
+
const Position = component<Position>();
|
|
35
|
+
const Velocity = component<Velocity>();
|
|
36
36
|
|
|
37
37
|
// 创建世界
|
|
38
38
|
const world = new World();
|
|
39
39
|
|
|
40
40
|
// 创建实体并设置组件(所有更改缓冲到 sync() 时应用)
|
|
41
41
|
const entity = world.new();
|
|
42
|
-
world.set(entity,
|
|
43
|
-
world.set(entity,
|
|
42
|
+
world.set(entity, Position, { x: 0, y: 0 });
|
|
43
|
+
world.set(entity, Velocity, { x: 1, y: 0.5 });
|
|
44
44
|
world.sync();
|
|
45
45
|
|
|
46
46
|
// 创建可重用的查询
|
|
47
|
-
const query = world.createQuery([
|
|
47
|
+
const query = world.createQuery([Position, Velocity]);
|
|
48
48
|
|
|
49
49
|
// 更新循环
|
|
50
50
|
const deltaTime = 1.0 / 60.0;
|
|
51
|
-
query.forEach([
|
|
51
|
+
query.forEach([Position, Velocity], (entity, position, velocity) => {
|
|
52
52
|
position.x += velocity.x * deltaTime;
|
|
53
53
|
position.y += velocity.y * deltaTime;
|
|
54
54
|
});
|
|
@@ -87,7 +87,7 @@ const ChildOf = component({ exclusive: true, name: "ChildOf" });
|
|
|
87
87
|
|
|
88
88
|
```typescript
|
|
89
89
|
// 返回卸载函数
|
|
90
|
-
const unhook = world.hook([
|
|
90
|
+
const unhook = world.hook([Position, Velocity], {
|
|
91
91
|
on_init: (entityId, position, velocity) => {
|
|
92
92
|
// 钩子注册时,为每个已同时满足条件的实体调用
|
|
93
93
|
},
|
|
@@ -105,7 +105,7 @@ unhook();
|
|
|
105
105
|
也支持回调简写形式:
|
|
106
106
|
|
|
107
107
|
```typescript
|
|
108
|
-
const unhook = world.hook([
|
|
108
|
+
const unhook = world.hook([Position, Velocity], (type, entityId, position, velocity) => {
|
|
109
109
|
if (type === "init") console.log("初始化");
|
|
110
110
|
if (type === "set") console.log("设置");
|
|
111
111
|
if (type === "remove") console.log("移除");
|
|
@@ -116,7 +116,7 @@ const unhook = world.hook([PositionId, VelocityId], (type, entityId, position, v
|
|
|
116
116
|
|
|
117
117
|
```typescript
|
|
118
118
|
// 可选组件:即使 Velocity 不存在也会触发钩子
|
|
119
|
-
world.hook([
|
|
119
|
+
world.hook([Position, { optional: Velocity }], {
|
|
120
120
|
on_set: (entityId, position, velocity) => {
|
|
121
121
|
if (velocity !== undefined) {
|
|
122
122
|
console.log("拥有速度和位置");
|
|
@@ -127,14 +127,14 @@ world.hook([PositionId, { optional: VelocityId }], {
|
|
|
127
127
|
});
|
|
128
128
|
|
|
129
129
|
// 过滤器:排除带有指定负面组件的实体
|
|
130
|
-
const
|
|
130
|
+
const Disabled = component<void>();
|
|
131
131
|
world.hook(
|
|
132
|
-
[
|
|
132
|
+
[Position, Velocity],
|
|
133
133
|
{
|
|
134
134
|
on_set: (entityId, position, velocity) => console.log("进入匹配集合"),
|
|
135
135
|
on_remove: (entityId, position, velocity) => console.log("退出匹配集合"),
|
|
136
136
|
},
|
|
137
|
-
{ negativeComponentTypes: [
|
|
137
|
+
{ negativeComponentTypes: [Disabled] },
|
|
138
138
|
);
|
|
139
139
|
```
|
|
140
140
|
|
|
@@ -164,10 +164,10 @@ console.log(world.has(child, relation(ChildOf, parent2))); // true
|
|
|
164
164
|
|
|
165
165
|
```typescript
|
|
166
166
|
import { World, component, relation } from "@codehz/ecs";
|
|
167
|
-
const
|
|
167
|
+
const Position = component<Position>();
|
|
168
168
|
|
|
169
169
|
const world = new World();
|
|
170
|
-
const wildcardPos = relation(
|
|
170
|
+
const wildcardPos = relation(Position, "*");
|
|
171
171
|
|
|
172
172
|
// 监听所有该类型关系的变动
|
|
173
173
|
world.hook([wildcardPos], {
|
|
@@ -362,11 +362,11 @@ import { pipeline } from "@codehz/pipeline";
|
|
|
362
362
|
import { World, component } from "@codehz/ecs";
|
|
363
363
|
|
|
364
364
|
const world = new World();
|
|
365
|
-
const movementQuery = world.createQuery([
|
|
365
|
+
const movementQuery = world.createQuery([Position, Velocity]);
|
|
366
366
|
|
|
367
367
|
const gameLoop = pipeline<{ deltaTime: number }>()
|
|
368
368
|
.addPass((env) => {
|
|
369
|
-
movementQuery.forEach([
|
|
369
|
+
movementQuery.forEach([Position, Velocity], (entity, position, velocity) => {
|
|
370
370
|
position.x += velocity.x * env.deltaTime;
|
|
371
371
|
position.y += velocity.y * env.deltaTime;
|
|
372
372
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codehz/ecs",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"module": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -9,11 +9,13 @@
|
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.mts",
|
|
12
|
-
"import": "./dist/index.mjs"
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"perry": "./src/index.ts"
|
|
13
14
|
},
|
|
14
15
|
"./testing": {
|
|
15
16
|
"types": "./dist/testing.d.mts",
|
|
16
|
-
"import": "./dist/testing.mjs"
|
|
17
|
+
"import": "./dist/testing.mjs",
|
|
18
|
+
"perry": "./src/testing/index.ts"
|
|
17
19
|
}
|
|
18
20
|
},
|
|
19
21
|
"files": [
|