Set your browser on Fire with P5.js



This post is made for those (like me) who like image processing, web development and maybe, for those who want to learn new programming technics...

- I will make you discover p5.js, a javascript library specialized in graphical creation for your web browser !

- I will also talk about the the Youtube channel "The Coding Train" presented by Daniel Shiffman. A lot of its videos are based on P5.js. It was for me a great source of inspiration and made me discover javascript (because I'm a newbie with JS...) So I'm pretty sure, you will learn a lot too...

- Finally I will present you my personnal example of what I did with P5.js. It's about an old retro fire effect (used in demoscene few years ago) :)


So let's begin with p5.js !


I- What is P5.js ?


a- Presentation

As I mentionned it previously, P5.js is a graphical Javascript library. With it, you will be able to make great effects in your web pages in a few minutes. 
This lib has been created by Lauren McCarthy (http://lauren-mccarthy.com/) in order to provide an educational tool used to understand graphical programmation basis.

Start here:
https://p5js.org/community/


b- And what can I do with this lib

This library is pretty simple to use. It is composed of the following main groups of functions:
- Drawing shapes and images. It includes the loading of 3D models !
- Managing colors (include saturation, brightness, contrast...)
- Functions to interact with your environment (including the listening off your hardware events like the mouse or the keyboard)
- some mathematical functions
- and other usefull tools...

You can have a look of all the API references here: https://p5js.org/reference/



c- Easy to start

If you are interested in playing with P5.js, it's super easy. You will find all you need on the website. Then you edit your code (javascript) in your prefered editor ! That's all.

You will also find additional libraries to get some sound / geolocation features / particles systems and much more ! Download only the one you need.




II- The coding train (youtube channel)

Now that you know about this tool, you are maybe wondering what you can do concretely...  The coding train is here to give you some ideas, (a lot of ideas !).

This Youtube channel is presented by Daniel Shiffman, a teacher that loves to teach :) He uses P5.js to implement a wide range of algorithms, from easy ones to complex ones like AI implentation and representation... Daniel is really clear and puts all its energy to make great tutorials. I presume you will like it too :)

If you are interested, I let you have a look to the channel:
https://www.youtube.com/user/shiffman/featured

Here are some of the tutorial video themes he made (but there is so much more !!):



Learn AI

More AI with Neural Networks
 

Make a Snake game in Javascript


Make retro effects (like a star field)


III- My sample, a retro fire effect !


For those who wonder how to implement a graphical effect, I will describe you my p5.js sample. It's a really simple sample but you will understand the key concepts of p5.js. 

I will share you the code, and for sure, you can play with it and improve performances or what you want.


a- Lib files

The first step is to download the library files. Then you should  make a new project folder with the following structure:

Your project folder

The child 'librairies' folder

b- sketch.js, draw your effect here

You will place all your code in this file. The 2 main methods needed by p5.js are the following:
- function setup ( )
- function draw ( )

The first one handle the page/effect initialization while the second is called several times per second to render the content. So here is the source code with all the steps commented:


// global parameters
var fireElemLenght  = 6;
var elemOpacity     = 255;

var fireLines   = [];
var fireWidth   = 0;
var fireHeight  = 0;

var nbColors    = 255;  // Nb Colors in the palette
var palette     = [];   // our color palette for the fire


// ======================================
// SETUP method 
// called 1 time during the page loading
// ======================================
function setup() {
  
  colorMode(RGB);
  createCanvas(800, 600);
  
  // 2D Fire: init size of fire
  fireWidth   = int(width / fireElemLenght);
  fireHeight  = int(height / fireElemLenght);
  print(fireWidth + ", " + fireHeight);
  
  // for each fire's 'lines'
  for(var i= 0; i<fireHeight; i++)
  {
    fireLines[i] = [];      // create the new line of fire pixels
    
    for(var x=0; x<fireWidth; x++)
      fireLines[i][x] = 0;  // Initialize to black
  }
  
  // generate fire colors palette
  initializePalette();
  
  // set black background
  background(0,0,0);
  noStroke();
}

// ======================================
// DRAW method
// called in the drawing process loop 
// ======================================
function draw() {
  
    // We clean the background each time
    background(0,0,0);
  
    // We generate a new base fire line (to make it 'move')
    initFireLine();
  
    // Compute the whole fire pixels
    fireGrow();
  
    // Display the result
    drawFire();
}

// ======================================
// > Initialize Palette mehtod
// You can update this process to change the fire colors
// ======================================
function initializePalette()
{
  // generate our 255 color palette
  // try to change colors composing the fire
  for(var i=0; i<nbColors; i++)
  {
    var val   = exp(i/10) - 1;

    var red   = map(val, 0, exp(7.5), 0, 255);
    var green = map(val, 0, exp(10), 0, 255);
    var blue  = random(50);
    
    if(green > 254) // check for colors range
    {
      red   = 255;
      green = 255;
      blue  = 255;
    }
    
    // check/erase for 'noisy' blue pixels
    if(red < 20 && green < 20)
    {
      red = green = blue = 0;
    }

    // add new color
    palette[i]  = color(red, green, blue, elemOpacity);
  }
}


// ======================================
// > initFireLine() method
// Make a new base fire line (randomly, to make the fire 'move' when it grows)
// Remark: Y axis is inverter on our screens ==> baseY = fireHeight-1
// ======================================
function initFireLine()
{
  // generate fire base (1st line) color ('randomly')
  for(var x=0; x<fireWidth; x++)
  {
    fireLines[fireHeight-1][x] = random(0,nbColors);
    fireLines[fireHeight-2][x] = random(0,nbColors);
    fireLines[fireHeight-3][x] = random(0,100);
  }
}


// ======================================
// > fireGrow() method
// Compute the whole fire, line by line. Start after the base line
// We compute each pixel color from its neighbors (a kind of median)
// It gives a blurry effect
// ======================================
function fireGrow(){
 
 // for each fire line
 for(var y=fireHeight-2; y>=1; y--)
 {

  // compute new fire color line 
  // based on the bottom & top lines
   for(var x=1; x<fireWidth-1; x++)
   {
       // Get neighbors colors
       var c1 = fireLines[y+1][x];
       var c2 = fireLines[y][x-1];
       var c3 = fireLines[y][x+1];
       var c4 = fireLines[y-1][x];
       var c5 = fireLines[y][x];

       // We make a 'median' color
       var newCol = int((c1 + c2 + c3 + c4 + c5) / 5) - 1;
       fireLines[y - 1][x] = newCol;
   }
 }
}


// ======================================
// > drawFire() method
// Drawing pass - to draw the fire from its computed matrix
//
// ======================================
function drawFire(){

  // foreach fire lines
  for(var y=fireHeight-1; y>0; y--)
  {
    // foreach pixel in the line
    for(var x=0; x<fireWidth-1; x++)
    {
      // get current pixel color index
      var idx = int(fireLines[y][x]);

      // check for color index limits
      if(idx<0) idx = 0;
      if(idx >= nbColors) idx = nbColors-1;
      
      // apply current pixel color
      fill(palette[idx]); 

      // Draw a square representing the current fire's pixel
      rect(int(x * fireElemLenght - (fireElemLenght / 2)),
          int(y * fireElemLenght + (fireElemLenght / 2)),
          fireElemLenght * 2 , 
          fireElemLenght * 2);
    }

  }

}


You should get something like that:












Comments

Popular posts from this blog

EMGU with Xamarin Forms guide [part 1]

Xamarin.Forms device unique ID...

[Xamarin Forms] Custom bottom bordered entry (iOS & Android)