Let's add some more particles. Using the same explode utility as before, we can add particles every time a new entity (including mined tiles) is spawned.
Additionally we add a PendingAction component to mark an entity currently waiting for a transaction. Based on this component we can then add a particle emitter using the rangeEmitter utility from @latticexyz/phaser-middleware.
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createWorld,
|
|
3
|
+
Entity,
|
|
4
|
+
exists,
|
|
5
|
+
getComponentValue,
|
|
6
|
+
Has,
|
|
7
|
+
removeComponent,
|
|
8
|
+
setComponent,
|
|
9
|
+
} from "@latticexyz/mobx-ecs";
|
|
2
10
|
import { createMapping, loadEvents, setupContracts, setupMappings } from "../packages/lattice-eth-middleware";
|
|
3
11
|
import { setupPhaser } from "@latticexyz/phaser-middleware";
|
|
4
12
|
import {
|
|
@@ -22,6 +30,7 @@ import { Coord } from "./types";
|
|
|
22
30
|
import { createInputSystem } from "./systems/InputSystem";
|
|
23
31
|
import { Directions } from "./constants";
|
|
24
32
|
import { createLifeSystem } from "./systems/LifeSystem";
|
|
33
|
+
import { createParticleSystem } from "./systems/ParticleSystem";
|
|
25
34
|
|
|
26
35
|
export async function createGame(contractAddress: string, privateKey: string, chainId: number, personaId: number) {
|
|
27
36
|
const world = createWorld();
|
|
@@ -53,6 +62,7 @@ export async function createGame(contractAddress: string, privateKey: string, ch
|
|
|
53
62
|
const Attack = createUintComponent(world, "Attack");
|
|
54
63
|
const Life = createTupleComponent(world, "Life");
|
|
55
64
|
const Selected = createBoolComponent(world, "Selected");
|
|
65
|
+
const PendingAction = createCoordComponent(world, "PendingAction");
|
|
56
66
|
|
|
57
67
|
const components = {
|
|
58
68
|
Position,
|
|
@@ -66,6 +76,7 @@ export async function createGame(contractAddress: string, privateKey: string, ch
|
|
|
66
76
|
Attack,
|
|
67
77
|
Life,
|
|
68
78
|
Selected,
|
|
79
|
+
PendingAction,
|
|
69
80
|
};
|
|
70
81
|
|
|
71
82
|
/*****************************************
|
|
@@ -93,7 +104,21 @@ export async function createGame(contractAddress: string, privateKey: string, ch
|
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
async function action(entity: Entity, target: Coord) {
|
|
107
|
+
// Don't act if an action is pending
|
|
108
|
+
const pendingAction = exists([Has(PendingAction)]);
|
|
109
|
+
if (pendingAction != undefined) {
|
|
110
|
+
console.warn("Action in progress");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Add an action indicator
|
|
115
|
+
setComponent(PendingAction, entity, target);
|
|
116
|
+
|
|
117
|
+
// Execute the action
|
|
96
118
|
await txExecutor.sendTx((contract) => contract.action(entity, target));
|
|
119
|
+
|
|
120
|
+
// Remove the action indicator
|
|
121
|
+
removeComponent(PendingAction, entity);
|
|
97
122
|
}
|
|
98
123
|
function actionDirection(direction: keyof typeof Directions) {
|
|
99
124
|
// Get the currently selected entity
|
|
@@ -135,6 +160,7 @@ export async function createGame(contractAddress: string, privateKey: string, ch
|
|
|
135
160
|
createAppearanceSystem(context);
|
|
136
161
|
createInputSystem(context);
|
|
137
162
|
createLifeSystem(context);
|
|
163
|
+
createParticleSystem(context);
|
|
138
164
|
|
|
139
165
|
return context;
|
|
140
166
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineEnterQuery,
|
|
3
|
+
defineReactionSystem,
|
|
4
|
+
defineUpdateQuery,
|
|
5
|
+
getComponentValue,
|
|
6
|
+
getComponentValueStrict,
|
|
7
|
+
Has,
|
|
8
|
+
} from "@latticexyz/mobx-ecs";
|
|
9
|
+
import { explode, rangeEmitter, removeEmitter } from "@latticexyz/phaser-middleware";
|
|
10
|
+
import { Context } from "../types";
|
|
11
|
+
|
|
12
|
+
export function createParticleSystem(context: Context) {
|
|
13
|
+
const {
|
|
14
|
+
world,
|
|
15
|
+
components: { Position, PendingAction },
|
|
16
|
+
phaser: { map, particles },
|
|
17
|
+
} = context;
|
|
18
|
+
|
|
19
|
+
// Explosion when entities first appear
|
|
20
|
+
const positionEnterQuery = defineEnterQuery(world, [Has(Position)]);
|
|
21
|
+
defineReactionSystem(
|
|
22
|
+
world,
|
|
23
|
+
() => positionEnterQuery.get(),
|
|
24
|
+
(entities) => {
|
|
25
|
+
for (const entity of entities) {
|
|
26
|
+
const coord = getComponentValueStrict(Position, entity);
|
|
27
|
+
explode(coord, particles, map);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Emitter as action indicator
|
|
33
|
+
const pendingActionQuery = defineUpdateQuery(world, [Has(PendingAction), Has(Position)]);
|
|
34
|
+
defineReactionSystem(
|
|
35
|
+
world,
|
|
36
|
+
() => pendingActionQuery.get(),
|
|
37
|
+
(entities) => {
|
|
38
|
+
for (const entity of entities) {
|
|
39
|
+
const pendingCoord = getComponentValue(PendingAction, entity);
|
|
40
|
+
const currentCoord = getComponentValue(Position, entity);
|
|
41
|
+
|
|
42
|
+
if (!pendingCoord || !currentCoord) {
|
|
43
|
+
removeEmitter(String(entity), particles);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
rangeEmitter(currentCoord, pendingCoord, particles, map, String(entity));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
}
|