To demonstrate the usage of React for overlays and UI, we'll add a simple full screen modal that pops up every time you lose an entity or lose the game.
All components and queries from @latticexyz/mobx-ecs are deeply integrated with mobx. Therefore we can use the mobx-react package to create React components that reactively update based on ECS component values.
For this game, we'll use a defineExitQuery and reaction to set a React state variable every time the OwnedBy component value of an entity that used to be owned by the player is removed. If the player doesn't own an entity with Heart component anymore, the game is over.
|
@@ -1,12 +1,43 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
import { Context } from "../types";
|
|
3
3
|
import styled from "styled-components";
|
|
4
4
|
import { observer } from "mobx-react";
|
|
5
|
+
import { reaction } from "mobx";
|
|
6
|
+
import { defineExitQuery, defineQuery, exists, Has, HasValue } from "@latticexyz/mobx-ecs";
|
|
7
|
+
import { Modal } from "./Modal";
|
|
8
|
+
|
|
9
|
+
export const App: React.FC<{ context: Context }> = observer(({ context }) => {
|
|
10
|
+
const [modalText, setModalText] = useState("");
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const {
|
|
14
|
+
world,
|
|
15
|
+
components: { OwnedBy, Heart },
|
|
16
|
+
} = context;
|
|
17
|
+
const lostEntityQuery = defineExitQuery(world, [HasValue(OwnedBy, { value: context.signer.address })]);
|
|
18
|
+
const ownedByQuery = defineQuery([HasValue(OwnedBy, { value: context.signer.address })]);
|
|
19
|
+
return reaction(
|
|
20
|
+
() => lostEntityQuery.get(),
|
|
21
|
+
(lostEntities) => {
|
|
22
|
+
if (lostEntities.size == 0) return;
|
|
23
|
+
// If the player doesn't own a heart anymore, the game is lost
|
|
24
|
+
if (
|
|
25
|
+
ownedByQuery.get().size > 0 &&
|
|
26
|
+
!exists([Has(Heart), HasValue(OwnedBy, { value: context.signer.address })])
|
|
27
|
+
) {
|
|
28
|
+
setModalText("Game over");
|
|
29
|
+
} else {
|
|
30
|
+
// Flash a quick modal if the player lost an entity
|
|
31
|
+
setModalText("Entity lost");
|
|
32
|
+
setTimeout(() => setModalText(""), 300);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
}, []);
|
|
5
37
|
|
|
6
|
-
export const App: React.FC<{ context: Context }> = observer(() => {
|
|
7
38
|
return (
|
|
8
39
|
<Container>
|
|
9
|
-
<Inner
|
|
40
|
+
<Inner>{modalText && <Modal text={modalText} fontSize={"80px"} bgColor={"rgb(255,0,0,0.2)"} />}</Inner>
|
|
10
41
|
</Container>
|
|
11
42
|
);
|
|
12
43
|
});
|