Context

If you have a value in a Sprite which is also needed in a very nested Sprite, you need to add that prop to all of the intermediate Sprites.

props diagram

Context avoids this by setting up a context value which can be accessed by any nested Sprite, without having to manually pass through props.

context diagram

This can be especially useful for 'global' props you need in many Sprites in your game - e.g. player controller settings or the login state of an online game.

Context is very much inspired by React Context and works the same way, but the API is slightly different.

You can create a Context with the makeContext function:

import { makeContext } from "@replay/core";
const themeContext = makeContext();

You then return a context.Sprite where you want to set this context. Only the Sprites in the sprites prop have access to the context:

import { makeSprite } from "@replay/core";
const ThemeSprite = makeSprite({
render() {
return [
themeContext.Sprite({
context: {
theme: "red",
},
sprites: [
// Only these sprites (and any nested sprites) have access to the context
Button({ id: "Button" }),
],
}),
];
},
});

The Context value can be read in nested Sprites using the getContext Sprite method:

import { t, makeSprite } from "@replay/core";
const Button = makeSprite({
render({ getContext }) {
const { theme } = getContext(countContext);
return [
t.text({
text: "Test",
color: theme,
}),
];
},
});

You can pass any values you want into the context prop. You can even pass in state with callbacks for your nested Sprites:

const counterContext = makeContext();
const Game = makeSprite({
init() {
return { count: 0 };
},
render({ state, updateState }) {
return [
counterContext.Sprite({
context: {
count: state.count,
increaseCount: () => {
updateState((prevState) => ({
...prevState,
count: prevState.count + 1,
}));
},
},
sprites: [Button({ id: "Button" })],
}),
];
},
});
const Button = makeSprite({
loop({ getInputs, getContext }) {
if (getInputs().pointer.justPressed) {
const { increaseCount } = getContext(counterContext);
increaseCount();
}
},
render({ getContext }) {
const { count } = getContext(counterContext);
return [
t.text({
text: `Count: ${count}`,
color: "black",
}),
];
},
});