Building Casual Multiplayer Game with React Native
Tags: reactnative, react, javascript, gamedev
Published: 2020-11-04 11:42:13

Have you thought about how much react native can handle? I did. 

After writing first small web project with react and having known that there is something called **React Native**, I've wondered if I can build a game with it.

# **Isn't it too slow for a game?**
I thought it would be too slow to build a game because javascript is an interpreted language.

So, I limited my expectation to performance and decided to build a simple casual game.

It will be fine, I thought so. It's a good thing that I decided so because I don't have a high level of expertise on optimization.

React Native got really slow when I tested a particle effect which is made up of custom animation engine and 20 naive View components. So I gave up on any visual effects and focused on game itself.

Yes, React Native would disappoint you if you're planning to build an app that has lots of visual effects. But, if you stick to simple interactions, it will be fine.


# **Excuse me, what game?**
{% youtube ky0-IJDBIrM %}

It's a casual puzzle game which supports multi play.

Rule is very simple. Sort all color blocks in time, without leftover.

# How did you develop?

I used typescript for client and server. If I haven't used it, it would have been quite difficult to track all the variables and parameters.

Development Cycle can be abbreviated to:
```javascript
0. Configure dev routes and production routes.
1. Make components, hooks, and utils.
2. Test each modules on dev routes.
3. Build screens with components.
4. Test screens on release build.
5. Go to 1.
```

There are more than hundred modules(including all the utils, screens, components, and hooks) but the core modules were a few:
1. **Block** react component for rendering blocks.
2. ***NativeRefBox*** react component for handling animation.
3. **NativeRefBlockBoard** react component for a board.
4. **useMultiGameSocket** hook for handling socket communication.
5. **generateMap** function for generating a map.

Other components are somewhat self-explanatory, so I want to explain about **NativeRefBox** because it's very ambiguous with its name and I belive it is the key component of this project.

# NativeRefBox? What is it?

I built it in need of higher performance when animating blocks. Initially, I used Animated api but it seemed very slow and lagging. (To look back, it could have been different if I used InteractionManager properly)

It was so slow that I thought about giving up the project because the other only alternative that I knew was re-rendering components multiple times, which is surely slower than Animated api.

Then I found there is a method called **setNativeProps** on most of React Native components. It was possible to directly manipulate a rendered component with the method.

# Hmm, is it okay to use that method?

To confess, it's a bit off the track of React recommended way because React prefers prop-based manipulation, not ref-based.

However, I needed it and I tried to build my own component which utilizes setNativeProps.

Result? setNativeProps method was faster than Animated. Maybe it's because [Animated](https://github.com/facebook/react-native/tree/master/Libraries/Animated) api supports much rich functionality.

Do you wonder how it looks like if you use NativeRefBox for animation?

Here it is.

#####**Scale up animation using Animated**
```javascript
const popAnim = React.useRef<Animted.Value>(new Animated.Value).current;

const scale = popAnim.interpolate({
  inputRange: [0, 1],
  outputRange: [1, 2],
});

const popup = (callback?: () => any) => {
  Animated.timing(popAnim, {
    toValue: 1,
    easings: Easing.elastic(7),
    duration: 1000,
    useNativeDriver: false,
  }).start(callback)
}

React.useEffect(() => {
  popup();
})

return (
  <Animated.View style={{transform: [{scale:scaleAnim}]}}>
    <Target/>
  </Animated.View>
)

```

#####**Scale up animation using NativeRefBox**
```javascript
const boxRef = React.useRef<NativeRefBox>(null);

React.useEffect(() => {
  boxRef.animate({
    style: {
      scaleX: 2,
      scaleY: 2,
    },
    duration: 1000,
    easing: "easeOutElastic",
  }).start(() => {
    console.log("Animation Finished");
  });
}, [])

return (
  <NativeRefBox>
    <Target/>
  </NativeRefBox>
)
```

# Interesting...? But...

You may think "hmm, I think Animated api is more easy to read and maintain"

Well, **I didn't say it's convenient, lol**

When there is no complicated animation, I used setNativeProps but whenever it gets complicated I used Animated api, except for animations used in game scene.

What I want to suggest is that **You can use setNativeProps for simple animation because it can improve performance**. However, you may need to build a nice component or utility for that because you will get perplexed when facing complex animation if you don't...

If you're interested in building your own animating module with setNativeProps, I hope you check about [InteractionManager](https://reactnative.dev/docs/interactionmanager) at first because it will save your app from being laggy. (I regret that I didn't care about that...)

You can see the code for NativeRefBox [here](https://gist.github.com/gippleup/904635c3f80de3a7191b23649ff159e7). (If you need easing functions, [here](https://gist.github.com/gippleup/fe499aabc42d205f129959cf3a42c8ce))

# Can I see the git?

Yes, sir, no. You can't. I want to keep it a secret.

![Laughing Spongebob](https://dev-to-uploads.s3.amazonaws.com/i/cffugpdki7xmy99w5j5t.gif)

I can show you the directory structure.

##### [Client](https://gist.github.com/gippleup/a3dddd3de46b09ad5004ab7c86e1560f) Directory Tree (depth==1)
```javascript
./src/
├── Language
├── algo
├── api
├── assets
├── components
├── hooks
├── redux
├── router
├── screens
└── types
```

##### [Server](https://gist.github.com/gippleup/8e6b4574c96466896aace4c27e447460) Directory Tree (depth==1)
```javascript
./src/
├── algo
├── asset
├── controller
├── entity
├── migration
├── route
├── utils
└── websocket
```

# If you go back to the start, What would you fix?
Maybe... I would dedicate to build a fabulous portfolio website.

Except that, I would study InteractionManager at first because I believe this api can help improving performance on interaction. After then, I would build NativeRefBox which have better readability and performance. And then, I would design more delicate models for socket communication.

# Link?

[Playstore Link](https://play.google.com/store/apps/details?id=com.sortio) for the app

...Appstore Link?

Unfortunately, I don't have a macbook.

# Is that all?
There are more things that I want to talk about but I want to keep it simple for now because.

Though it's a bit unsastisfactory to wrap up the project for now, it was quite fun to build various utils, hooks, and components for both client and server. ...for about a month and two weeks, maybe?

I want to finish this shabby article with saying, "If you're interested in building a game with react native, don't... no, is it a very simple game? Hmm... okay, but if it's the other case..."

~ Fin ~