HTML Canvas Games from Scratch #2
Tags: html, javascript, gamedev, physics
Published: 2020-04-14 07:33:56

<img src="https://c4.wallpaperflare.com/wallpaper/697/256/951/space-invaders-simple-background-minimalism-video-games-wallpaper-preview.jpg" width="1000">
Hey folks!:video_game:
So in the previous post I tried to lay a foundation to start understanding canvas. I hope that by now you are a bit comfortable with it. So in the previous post we saw:
- File structure and boilerplate:file_folder:
- Some important *javascript functions* for drawing:pencil2:
- Defining a particle and drawing it on the canvas (hope you remember *atom*:wink:)
- *requestAnimationFrame()*:arrows_counterclockwise:
- *One and two dimensional* uniform motion of the particle:runner: 
- Gaining control over the *Math.random()* function:game_die:

## Phase 2
Till now we were have worked with one particle, but that's not how games are right? At least most of them. Handling multiple particles is not as tough as you might think. Let's see how its done!
First of all, will the **object definition** of the particle change?
Well, it depends on the **properties** of these particles. 
(We will see this later on)

Let us continue with the same particle definition that we previously used:

 ```js
var particle = function(x,y,radius){
	this.x = x;
	this.y = y;
	this.radius = radius;
}
```
Now instead of defining one particle, let us define **an array of particles**:
```js
var particleArray = new Array();
```
Let us now define **50 particles** with **random positions** on the screen. But what are the dimensions of the screen?
We already have :
- window.innerWidth
- window.innerHeight

So the coordinates of the screen will be in the range:
- X : 0 - window.innerWidth
- Y : 0 - window.innerHeight

So the code goes like this :
```js
var totalParticles = 50;		 //number of particles 
var maxRadius = 30;				 //maximum value of radius	

var particle = function(x,y,radius){
	this.x = x;
	this.y = y;
	this.radius = radius;
}

var particleArray = new Array(); //array of particles		
var i;							 //loop variable	

for(i = 0 ; i < totalParticles ; i++) {
	//Defining properties of the particle
	var xcoord = Math.random()*window.innerWidth;
	var ycoord = Math.random()*window.innerHeight;
	var rad = Math.random()*maxRadius;
	
	//New particle with above properties
	var tempParticle = new particle(xcoord,ycoord,rad);	
	
	//Push tempParticle into the array
	particleArray.push(tempParticle);		 
}
```
I've tried to keep the code readable and obvious. Just read it and you should understand what is happening. 
What's left? Let us draw these particles on the canvas! 
Just add the following code :
```js
c.fillStyle = 'aqua';
//Drawing the particles
for(i = 0 ; i < totalParticles ; i++ ){
	c.beginPath();
	c.arc(particleArray[i].x,particleArray[i].y,particleArray[i].radius,0, Math.PI*2,false);
	c.closePath();
	c.fill();
}
```
Result:
<center><img src = "https://github.com/jrathod9/Making-of-Space-X-/blob/master/Phase%202/ParticleArray/arrayparticles.png?raw=true" height="400"></center>

Here's the source code : **[Code link](https://github.com/jrathod9/Making-of-Space-X-/tree/master/Phase%202/ParticleArray)**
Location in repository : **\Phase 2\ParticleArray**
>Note : On **refreshing** the page you will find a new configuration everytime.
>Also we haven't used the **requestAnimationFrame()** function as we just wanted **static** particles as of now.

What next? Let us give all the particles some **random velocities**:rocket:.
We need to add two properties for the particle object "*x velocity*" and "*y velocity*":
```js
var particle = function(x,y,vx,vy,radius){
this.x = x;
this.y = y;
this.vx = vx;				//x vel
this.vy = vy;				//y vel
this.radius = radius;
}
```
Now since we have added new properties for this object, we must also define its values for all the defined instances. 

Wait, did I just go too hard on you?:stuck_out_tongue_closed_eyes:

Ok let me reframe that:
Since we added **two new properties** to the particle object, we also need to give the value of these properties for all the particles that are stored in the array.
So inside the **for loop** in which we are defining and adding particles to the array : 
```js
{
	...
	...
	var xvel = Math.random()*6 - 3;
	var yvel = Math.random()*6 - 3;
	...
	var tempParticle = new particle(xcoord,ycoord,xvel,yvel,rad);
	...
	...
}
```    
> Try figuring out the range of (xvel, yvel). 

Now we are ready with particles and their velocities. Lets start drawing them on the canvas. This time we will use requestAnimationFrame():
```js
c.fillStyle = 'aqua';		 //define fillStyle
function draw(){
	//Clears the entire canvas
	c.clearRect(0,0,window.innerWidth,window.innerHeight);	 

	//Update the value of the coordinates (according to velocity)
	for(i = 0 ; i < totalParticles ; i++ ){
		particleArray[i].x += particleArray[i].vx;
		particleArray[i].y += particleArray[i].vy;
	}

	//Drawing the particles
	for(i = 0 ; i < totalParticles ; i++ ){
		c.beginPath();
		c.arc(particleArray[i].x,particleArray[i].y,particleArray[i].radius,0, Math.PI*2,false);
		c.closePath();
		c.fill();
	}

	requestAnimationFrame(draw);
}
draw();	
```
Result :
<center><img src = "https://github.com/jrathod9/Making-of-Space-X-/blob/master/Phase%202/ParticleArrayMoving/MovingParticlesArray.gif?raw=true" height="400"></center>

Here's the source code : **[Code link](https://github.com/jrathod9/Making-of-Space-X-/tree/master/Phase%202/ParticleArrayMoving)**
Location in repository : **\Phase 2\ParticleArrayMoving**

> It must be noted that the particles will soon **disappear** leaving a black screen. The reason being that the canvas extends **infinitely**, we just get to see a part which our window can capture.

To confine the particles to our window, we must make the window act as a **box :white_square_button:**. Particles must collide and **bounce back** inside like this:
 
<center><img src="https://github.com/jrathod9/Making-of-Space-X-/blob/master/Phase%202/ParticleArrayMovingCollisions/collisionscenarios.png?raw=true" height="400"></center>

These conditions are to be taken care of every time before drawing the particles. Let us code them:
```js
//Checking for collison with walls
for(i = 0 ; i < totalParticles ; i++ ){
		
		if(particleArray[i].x > window.innerWidth || particleArray[i].x < 0)
			particleArray[i].vx*=-1;	
		
		if(particleArray[i].y > window.innerHeight || particleArray[i].y < 0)
			particleArray[i].vy*=-1;	
	}
```
Result : 

<center><img src="https://github.com/jrathod9/Making-of-Space-X-/blob/master/Phase%202/ParticleArrayMovingCollisions/MovingParticlesArrayCollide.gif?raw=true" height="400"></center>

Here's the source code : **[Code link](https://github.com/jrathod9/Making-of-Space-X-/tree/master/Phase%202/ParticleArrayMovingCollisions)**
Location in repository : **\Phase 2\ParticleArrayMovingCollisions**

> Notice the particles bouncing off the edges.
> **Practice Sesh:computer:** : You can try giving a *different color* to all the particles. You can also try to making all the particles *twinkle/shimmer:sparkles:*, by changing its **opacity** (the  '**a**' in *rgba*).  
> Solutions to these : [Link to code](https://github.com/jrathod9/Making-of-Space-X-/tree/master/Phase%202/Practice%20Sesh)
> Location in repository : **\Phase 2\Practice Sesh**	

### Interacting with the canvas:
 Yes, chill:snowflake:. It is possible. Obviously. Who would call it a game otherwise? 
Let us talk about the **addEventListener()** method. As the name suggests, it simple listens to events. Events in this case are *keyboard inputs,* *mouse clicks* , *changes in mouse movements* etc.

**Syntax**:
```js
window.addEventListener(Event,Function,useCapture);
```
**Event** : An event is nothing but a **trigger**. It is used to execute a **coded response**. Eg : *click* , *onmousedown* , *onkeypress* , *onkeyup* etc. ([Know more..](https://www.tutorialspoint.com/javascript/javascript_events.htm))
**Function**: This is the function that is to be called when that specific event occurs. It is defined somewhere in the code.
**useCapture** : This is either **true** or **false**. It is **optional**. It is used to define whether the event should be executed in the **Bubbling** or **Capturing** phase (it is not important right now, though you can read more [here](https://javascript.info/bubbling-and-capturing)). By **default** it is **false**. 

Lets start with the most basic event and response : 
For this you will need the javascript code where we had just 1 static particle.(try to write this code yourself once)
Source code : **[Code link](https://github.com/jrathod9/Making-of-Space-X-/tree/master/Phase%201/Atom%20Particle)** 
Location in repository : **\Phase 1\Atom Particle**
*Just remove the line of code used to increment the speed. Thus getting us a static particle.*
Now let us add a simple mouse **click** event : (append this snippet at the end of the code.js file) 

```js
window.addEventListener("click", move , false);	//define event listener

function move(e)			//response function 												
{
	atom.x = e.x;			//update x coordinate of atom		
	atom.y = e.y;			//update y coordinate of atom
}
``` 
**What is 'e' ?**
**e** here represents the **event**, and the event here is **click**. It must be passed as a parameter to the function.
Every event has specific properties. For this click event, we have properties **x** and **y** which represent the coordinates of the cursor on clicking.

Coming back to the code, the function replaces coordinates of atom with the coordinates of the cursor. Thus moving it to the click position. 
 Check it out yourself.
 Source code : **[Code link](https://github.com/jrathod9/Making-of-Space-X-/tree/master/Phase%202/ParticleCanvasInteraction)** 
Location in repository : **\Phase 2\ParticleCanvasInteraction**

Similarly, let us make atom move left , right, up and down with the arrow keys.
So this is what we need :
- On **pushing down** an arrow key the particle should **move**.
- On **releasing** the key the particle should **stop** its movement.

We will use the **keydown** and **keyup** events. 
This even has a specific property called **keyCode**. Every key on the keyboard has a different keyCode. The keyCode values of arrow keys are :
- Left : 37
- Up : 38
- Right : 39
- Down : 40

Let us define a boolean array called "*keys*" which will hold true for all those keyCodes which are pressed.
Also we will need two event listeners, one that will check for keys pressed and the other that will check for keys released.
```js
var keys = [];			
window.addEventListener("keydown",keyPressed,false);	//keydown listener
window.addEventListener("keyup",keyReleased,false);		//keyup listener

function keyPressed(e){				//sets value true when key pressed 
	keys[e.keyCode] = true;
}
function keyReleased(e){			//sets value false when key released
	keys[e.keyCode] = false;
}
```
Its not done yet. We need to make required adjustments in the draw() function, the effect of key presses on the coordinates :  
```js
function draw(){
..
..
	if(keys[37])				//if left is true
		atom.x-=xspeed;			//move left by xspeed
	else if(keys[39])			//else if right is true
		atom.x+=xspeed;			//move right by xspeed

	if(keys[38])				//if up is true
		atom.y-=yspeed;			//move up by yspeed
	else if(keys[40])			//else if down is true
		atom.y+=yspeed;			//move down by yspeed
..
..
}
```
> Note : These are grouped this way because Up and Down cannot function together, and Left and Right cannot function together.
> Also don't forget to define xspeed and yspeed outside the draw function.

Result :
<img src="https://github.com/jrathod9/Making-of-Space-X-/blob/master/Phase%202/ParticleCanvasInteractionKeyboard/ParticleInteractionKeys.gif?raw=true">
Source code : **[Code link](https://github.com/jrathod9/Making-of-Space-X-/tree/master/Phase%202/ParticleCanvasInteractionKeyboard)**
Location in repository : **\Phase2\ParticleCanvasInteractionKeyboard**
Now its your turn to play around with a few more such events. 
Other things you can try :
- Bound the motion of this particle to the box
- Comment out the clearRect() function and see the output
- Use the fillRect() function with black colour but opacity less than 1, instead of clearRect(). (*Will give a nice trail effect*)

This is all for this post. Till here I have covered everything it takes to create the game that I made. Now all we have to do is combine all this logic in one file ❗   
In my opinion you may also start creating the game yourself, or try making some other game maybe ping-pong, flappy bird, snakes etc.

Do leave comments/suggestions (if any).
Cheers!:lollipop: 

*Written by* : **Jay Rathod**:computer:
*Links* : [Portfolio](https://jrathod9.github.io/) | [Github](https://github.com/jrathod9) | [Codepen](https://codepen.io/jrathod9) | [Linkedin](https://www.linkedin.com/in/jrathod9/) | [Instagram](https://www.instagram.com/they_say_j/)