8⃣ Video games and React state
There is a lot we can learn from video games.
Modern games render hi-def graphics based on heavy calculations and still run smoothly. One of the ways they do this is by using smart rendering techniques.
One of the techniques revolves around optimising paint
.
Just like browsers, game engines spend a lot of time painting pixels on screen. They have to run a render task
every 16 milliseconds to get 60 FPS.
That's an expensive process! The way to optimise paint tasks is to paint less. Here's what happens in the render cycle:
- The engine keeps the current screen in cache
- Calculates the new screen
- Figures out the difference between the two screens
- Paints only the pixels that are different
Does this sound familiar? This is exactly what happens in React!
Javascript calculations are easy for the browser to make but changing the DOM is expensive.
React maintains a representation of your application's DOM (they call it virtual DOM
) and uses it to figure out the least amount of DOM changes required to reach the next state of the application.
That's not the only similarity between game dev and React applications, they are similar in the way state is handled too.
Let me try to define state first: the particular condition that something is in at a specific time.
Games usually maintain the state of all the elements like characters, items, etc. in a common store. Pieces of this information are passed to elements that they can use.
If you have the state of the game at any point, you can paint what the game looked like. This is super useful when you need to save your game, you can restart from that state later!
It's easier to think about this with an example. Let's take the example of a 2-D game where Mario runs around to collect coins.
First of all, we need a global World
context. There are 2 elements in this game, Mario
and Coin
. The position of each of them is stored in World
along with the score.
This is what the state would look like if represented in javascript:
var state = {
mario: { x: 200, y: 300 },
coin: { x: 400, y: 500 },
score: 4
}
You can use this object to paint a snapshot of the game.
If you want to represent this in terms of React, you can put that in a class component which has an internal state
of their own:
class World extends React.Component {
state = { x: 200, y: 300, score: 4 }
render() {
return <div>
<Mario x={this.state.mario.x} y={this.state.mario.y} />
<Coin x={this.state.coin.x} y={this.state.coin.y} />
</div>
}
}
Notice how we are taking parts of the state and passing them to our characters Mario and Coin as props
. This is something I talked about in a past issue. (Read it here)
If you're curious, this is what the code for Mario looks like:
const Mario = props => {
const styles = {
position: 'absolute',
left: props.x,
top: props.y
}
return <img src="mario.png" style={styles} />
}
Now, when Mario takes a step right, we need to update the internal state
of World. This will in turn update the props
passed to Mario making him move.
Check out the move
function here:
class World extends React.Component {
state = { x: 200, y: 300, score: 4 }
move(newX, newY) {
// update state
this.setState({ x: newX, y: newY })
}
render() {
return <div>
<Mario x={this.state.mario.x} y={this.state.mario.y} />
<Coin x={this.state.coin.x} y={this.state.coin.y} />
</div>
}
}
Sounds good?
If you liked this way of thinking about React and would like to continue to learn, I'm building a course where we start from the very basics of React and build an entire game!
Here's a video preview if you're interested:
Hope this was helpful for you on your journey!
👋
Sid
You should follow me on twitter.