Friday, 16 December 2016

Building Web Games Using p5.js

Building Web Games Using p5.js

Technical Blog 3.

p5.js - Processing but with JavaScript
Last time, we looked at how we can use Processing to visualise mathematics. The other thing I use Processing for is making web games. However, instead of the standard edition of Processing we've been using up until now, to make web games we need to write our code in a more web-friendly language. In particular we need to use JavaScript. Fortunately there is a JavaScript framework which works just like Processing. It is called p5.js.

But first of all: what is p5.js? [1]

What Is p5.js?

Now that Java web-applets are no longer used, Processing's original Java-based design is somewhat redundant if sharing our sketches online is important to us (although using Processing in Java mode still provides the best performance if we are happy to work offline - in an art installation for example).

This is were p5.js comes in.

p5.js was first created by Lauren McCarthy (with the help of the Processing Foundation) with exactly the aim of bringing Processing back to the web. p5.js is a standalone project - not a port or emulation - but is extremely similar to Processing. [2]

How To Setup p5.js

There are several options for writing p5.js code. You can download the p5.js IDE, you can write the code in a text editor and run the code in a web-browser (if you know what you're doing). Or; you can write your code in CodePen, or host it on a GitHub page, or many other methods.

Even though the p5.js editor is still in development, it works for our purposes so download the p5.js editor from here: http://p5js.org/download/ and when you open it, it should look something like this:

p5.js editor
It even gives us the setup and draw functions (notice the JavaScript function syntax)!

When you hit the play button this time, a web-browser will open up with your sketch running in it.

"Hello World!" In p5.js

As we did before, let's draw a black rectangle to the screen. Try typing the following code into the p5.js editor and click the play button to run the sketch:
function setup() {
createCanvas(400, 400);
background(255);
stroke(0);
fill(0);
rect(100, 100, 200, 200);
}
You should see a black square on a white background:
"Hello World" programming in p5.js
As expected, we see a black rectangle on a white background.

As well as the JavaScript syntax for defining functions, we also have to use createCanvas(...) rather than size(...). For the other main differences see this GitHub page.

Taking User Input In p5.js

Let's make a simple button which changes the colour of the background. We can check to see where the mouse is on the screen using the mouseX and mouseY inbuilt variables. We can check if the mouse is pressed using the mouseIsPressed inbuilt variable.

The following code demonstrates how we can use this to make a simple button:
var b = true; 
function setup() {
  createCanvas(800, 600);
}
 
function draw() {
  if (b)
    background(0, 0, 255);
  else
    background(255, 0, 0);
  noStroke();
  fill(0, 255, 0);
  rectMode(CENTER);
  rect(width/2, height/2, 200, 100);

  if (mouseX > width/2 - 100 && mouseX < width/2 + 100 && mouseY < height/2 + 50 && mouseY > height/2 - 50 && mouseIsPressed){
    b = !b;
  }
}
You will notice, if you run this code, that the button doesn't work quite the way we would expect a button to work. The background keeps changing colour every frame as long as the mouse is pressed.

We can fix this by declaring a variable var clicked = false; we can add a check clicked == false to our if statement and as well as changing the color of the background (b = !b) we will set clicked = true;. We can then add another if statement below to changed clicked back to false once the mouse is released (i.e. mouseIsPressed == false). The changes are below:
if (mouseX > width / 2 - 100 && mouseX < width / 2 + 100 && mouseY < height / 2 + 50 && mouseY > height / 2 - 50 && mouseIsPressed && change == true) {
    b = !b;
    change = false;
  }
  if (mouseIsPressed == false) {
    change = true;
  }
This will make the button work as we would expect.

We can also take keyboard input in a similar way. Let's make a rectangle move around the screen using the arrow keys. Again there is an inbuilt variable called keyIsPressed which we will use, but we will also need to check the keyCode variable to make each key do what we want it to do.
var x = 0;
var y = 0;

function setup() {
  createCanvas(800, 600);
}

function draw() {
  background(0)
  noStroke();
  fill(255);
  rect(width/2 + x, height / 2 + y, 100, 100);
  
  if (keyIsPressed){
  if (keyCode == UP_ARROW)
    y--;
  if (keyCode == DOWN_ARROW)
    y++;
  if (keyCode == RIGHT_ARROW)
    x++;
  if (keyCode == LEFT_ARROW)
    x--;
  }
}
When you run the above code you will see a white square on a black background and the arrow keys will move the square around as expected. However, the square moves quite slowly, and is not constrained to the screen. p5.js does have an inbuilt constrain function and of course we can increment x and y by more than 1 to make the square move faster. As an exercise, I recommend implementing these changes in your sketch.


Making Web Games

Before we look at some real-life web games that I have made using p5, we should just note a few aspects of making games beyond simply taking user input.

After playing around with the square moving program for a minute or so you will realise that you cannot move the square in two different directions at the same time. This is because p5 only keeps track of the most recently pressed key in the keyCode variable. This makes for an interesting feature when making action games, but does restrict your design space a little.

It is also worth remember that p5.js is simply a JavaScript framework, so you can make your p5 sketch as part of a normal website. This means you have access to the DOM, HTML, CSS and any other web technologies you wish to use in your website. p5 even has a special library to interact with the DOM.


Some Examples Of Web Games Made Using p5.js

It is time to look at some real-life web games. I have made all of the games I will show here myself and I encourage you to look into the source code to see how each was made.

Let's start with a simple game of Nought's and Crosses: https://codepen.io/LukeBurgess94/full/NRWqgE/


Naughts and Crosses game.
You can view the source-code by going to the "change view" tab in the top-right of the web-page.

This game is an example of implementing lots of buttons, but the AI (who plays randomly) does have to pick an empty space, so there is some data-structure manipulation going on in the background.

Again on CodePen I also made a version of Simon: https://codepen.io/LukeBurgess94/full/bwGwKo/

Simon game.
This game required some subtle timing trickery with p5. The trick being to loop through draw() a certain number of times before executing the next action. This stops the game from moving too quickly and being unplayable.

I have also made an action game in p5: https://callmeluke94.github.io/defend-planet-game/

Defend The Planet game.
The source-code can be seen here: https://github.com/CallMeLuke94/defend-planet-game
This game again utilises the timing trickery from before, but to control the rate of fire of the cannon. You will see the same issue described earlier with only being able to press one button at a time. The game would be much easier if we could move and shoot simultaneously.

Detecting collisions is done by checking that the distance between two objects is less than the sum of their radii, although for the non-circular tank, the radius is slightly larger than the body of the tank.


Conclusion And Next Time

That concludes this week's post, I hope you enjoyed learning about Processing's JavaScript based sister language p5.js. I should note that very similar techniques can be applied to make games in Processing. In fact, I have made a version of the retro Asteroids game in Processing, the source code for which can be found here: https://github.com/CallMeLuke94/AsteroidsGame

Unfortunately you will have to download the files and run them in Processing rather than being able to play in the browser, but it is an entertaining version of Asteroids which you can easily tinker with and adapt.

Of course, Processing is not the best language (and p5.js is not the best JavaScript framework) for making games, but given how intuitive Processing is; it is certainly very enjoyable to build games using Processing and p5.

Next time we will look at the future of Processing, p5.js and Processing's other modes and projects. There is a lot going on in the Processing community with regards to the development of Processing and it is an exciting time to be writing Processing code.

References 

[1] http://p5js.org/
[2] https://www.processing.org/overview/

No comments:

Post a Comment