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);
}
}
}
Comments
Post a Comment