NodeJS Game: browser based Single shard MMO Game + Ethereum based economy
This is going to be an attempt to be build a simple space based MMO JS game in the browser with NodeJS on the backend, and an ingame Ethereum based economy.
The idea I have is: A simple 2D version of Eve in the browser, with Ethereum.
To this I am going to develop the following:
A browser based client
A clustered NodeJS backend using sockets.io to communicate with the clients
A custom built Ethereum based ER20 token which is used in game
To begin with I am going to keep the functionality simple.
Each player will have a ship. They can fly about, shoot at each other. Upon death they will respawn at a base of some kind from which they can undock.
They will be able to mine asteroids. Haul it back to the base and sell the minerals and in return recieve the Ethereum based token.
My first step is going to be building a client which draws a ship, in space and is controllable by the user.
I am going to begin with building a basic React application, with a Component SpaceNode
This places a 640 x 480 canvas on the screen and on load will setup our update method to redraw the canvas.
The update method to begin with just clears the canvas with a black fill and then draws a rectangle representing the players ship
Creating the ship and the camera
Next I am going to move the ship class out into a seperate class, implement the concept of a camera point, and have our players ship move to wherever the user clicks on the screen.
It is possible I will change how this is done but for now I will have a SpaceObject class which the worlds various objects will extend
In SpaceNode.js I will expand our state to include our camera settings, the x,y we are looking at in the world and the width and height of our screen. I will then add a ships array, a destination object to store where the user has clicked and also a reference to the players ship.
I will implement a basic click method which work out the position in the world the user has clicked, and also the angle from the players current position
I’ll then update the draw method so that it repositions the camera based on any user movements and then iterates over the ship collection, drawing them.
I’ll then create Ship.js, drawing it on the screen and (temporily), if it is the players ship I will move towards the click point and also rotate in the direction of the click
Finally in componentDidMount I will create our ship, a second ship, and then add them into the ships array and set the state and bind the width and height of our canvas to the camera width and height
Clicking on the screen we should now see our ship moving in the world relative to the static ship
The game world
To begin with the game world is going to be around 10,000 pixels by 10,000 pixels. I’ll now quickly make sure the camera point will stay within the bounds of the world.
Adding in the width and height of the current world to the state
I’ll then refactor things slightly, creating an updateCamera method which keeps the camera within the bounds of the world. I’ll then create an updateObjects method for handling actions of the objects.
Then within the Ship class I’ll seperate the movement into an update method
The camera should now stay within the confines of the world. This breaks the code which points the ship in the direction of the mouse click, but that is okay as soon that functionality will be changed.
I’ll now refactor the code so that instead of a ships array, we have a worldObjects array and change the references accordingly
Now I will create an asteroid class. There is probably a better way to do this, but for now I will randomly build a number of vertices, at a random angle around a point at a random distance. The update method will handle the movement and the rotation and the draw method will then draw the vertices.
To test this, In componentDidMount in SpaceNode I will create 4 asteroid objects and add them to the worldObjects array
Next up is to create a simple space station which consists of a few shapes, and in the centre of the station, a beacon, which is an animation drawing a circle which fades further to black on each update
That now gives enough objects to begin working on a UI. This UI will not be a finished product but instead just simple elements to enable basic functionality. To begin with it will consist of 5 elements.
Two buttons (tools) which alter the function of the mouse.
The first tool will make the mouse move the ship on a click
The 2nd tool will make the mouse click attempt to select whatever object has been picked.
Then there will be a panel/window which displays the current selected item
I’ll have a ‘targeting’ element, which makes it visible what object is currently selected
Finally there will be a panel which lists actions which can be carried out on the selected object.
To make the buttons I will add two button html tags using zIndex to overlay them on the canvas. I’ll also modify the canvas click action so that it responds to a click on the canvas instead of the window and also change the name of the method which handles the click.
The selected item panel will for now just be the title of the object (which will be added shortly).
I’ll then add two constants for the different types of click state, an action element in the state , and then our two click handlers
Then to complete this I will alter our canvas click handler as follows:
Now our ship should only move if ‘move’ is the currently selected action
I’ll now create the code for selecting the targeted element ( I’ll refactor this later )
To do this I will iterate over all the objects, if the click is within the bounds of the object, then it will be selected. Whilst iterating further, if we detect that the click is within the bounds of another object, we’ll check to see if it is closer to the centre of that object than the previous.
Later on this will be improved to check to see whether the click is within a polygon but for now this will do in order to build the UI.
Here I also add in width, height and title to SpaceObject and have it passed in to the object constructors like follows
When I currently instantiate the objects in componentDidMount I will for now just pass in the data hardcoded, although later this will come from the server
In order to store the currently selectedObject, I will add ‘selectedObject: null’ to the state and then add an else if clause to the click handler
Now that we have the selectedObject, I will add in the crosshairs which will identify the selected item on the screen