How do they make browser games nowadays? Part 2

Alexander Saltykov
4 min readNov 10, 2021

--

The previous article described basic steps that you need to do to make your own browser game. Read it first, if you haven’t already.

This time we’ll move to more complex stuff, such as state management, higher order components and gamepad API.

Step 6. Movement

How do you actually move a character in the direction you need? A model can’t move itself by it’s own. I’ve already mentioned earlier in step 4 the pros of wrapping a collection of objects in group. Once again: you can transition group of meshes (i.e. the model) with linear speed; in conjunction with proper animation it will look like running or walking, depending on your needs.

So if you want your NPC to move in some direction, let’s say northward, you’d have to perform 2 simple operations:

  1. rotate it in the desired direction;
  2. start transitioning it’s position little by little.

The most convenient way to do so (imho) is to use composition. So create a file called /hoc/Movable.jsx with the following content:

https://codesandbox.io/s/exciting-marco-iyy6h?file=/src/hoc/Movable.jsx:0-787

Here, this component simply takes all of it’s child nodes, then slightly moves them towards heading vector in each frame. Velocity prop is responsible for how far this transition will be. Note onMove callback: we’ll talk about it later.

Additionally, it uses /helpers/getRotation.js helper which does some quaternion magic to actually rotate the group.

Ok now, if you wrap something in <Movable /> component it will, well, move. Take a look at this little demo:

Step 7. Gamepad support

I didn’t event have gamepad until quarantine; I bought one just to try. And it turned out that it’s pretty comfortable way to play games (by the way, Diablo II: Resurrected with gamepad feels like a charm. Never thought it would be so). Chrome has Gamepad API for a long time already. So why not to try?

Gamepad API is pretty straightforward; it’s not terribly hard to use, but to make things even easier we’ll use Gamepads library. By using React’s context we can write all of the callbacks somewhere in the top level and just pass the information about how player moves it’s stick (and when he presses attack button) down to Movable component we created earlier. Check out the files: /GamepadControls.jsx — callbacks for gamepad and fallback for WASD keys (link); /Player.jsx — small wrapper around player model that responds to our actions (link).

Now replace all of the NPCs in index.js with this:

<GamepadControls>  <Player /></GamepadControls>

And that’s it!

Next important question to ask is “How do you tie together all those zombies, the player and fireballs? How do enemies know where the player is?”. And the answer is — you say it — state management.

Step 8. State management

Every single front-end project in 2021 must have state management layer. This is unarguable. And our game is no exception. You can of course use your favorite one, whether it’s Redux, MobX, effector or whatever. It makes absolutely no difference. I chose Zustand.

Think of all the entities in the game as of collections. Add an entity (zombie or fireball) to corresponding collection in global store, render it, then just remove an entity when you need (fireball hits zombie or flies too far; zombie dies of spell). I bet you did this a lot of times but you rendered collection of items in e-commerce shop instead.

Let’s add some stores in /store folder:

I hope all of the methods there are self-explanatory. If not, sorry. Player store holds position (it should be available for everyone); zombies store holds id for each enemy, his position and HP. Finally, fireballs store is used to control amount of fireballs and their directions.

Ok, now things start to get complicated a little. Don’t worry, it’s not that bad.

Modify Player component as such:

Also add this code to Fireball component:

And take a look at Zombie component, especially at these lines:

Vector operations behind enemy orientation

Now all enemies will pursuit you wherever you go.

Complete code for this step is available here, except one thing: since codesandbox has some problems with parsing .fbx, I replaced all the models with colorful cubes.

In the next chapter I’ll review techniques for collision detection and UI.

Thanks for reading the article! I hope you liked it. Here are some links to stay in touch: twitter, linkedin, github.

Note

There is a chance that your gamepad won’t have the same buttons as mine, if so, please see Gamepads library docs and the standard mapping.

Standard gamepad mapping

--

--