Generate Particles with different Settings at the same time HTML5 - javascript

first of all im not only new in HTML5 or Canvas im new in the whole Coding Process. I used this Example http://rectangleworld.com/demos/DustySphere/DustySphere.html and tried to modify it in a way i can use it for my needs.
At the moment it looks like this.
code is on codepen
Now i tried to to combine different settings and generate 2 different Particle Animations at the same time. For example: the Particles on 2050 and 2070 should appear on 2090 combined. Is there any easy solution for this problem? I appreciate every help.

Draw particles with differing settings by using a function
Since you're new to coding, I'm wondering if you know about functions.
A function is a reusable block of code.
You can send arguments for a function to use.
Arguments can make the function apply different setting while executing its code.
Here's a quick example using a single function that accepts different arguments to draw your particles with different settings.
In general, you can apply different setting by creating a function that accepts parameters to draw the varied settings. That way you can call that same function multiple times with different setting.
// draw a small red circle at [x=50,y=50] with full alpha
drawParticle(50,50,10,'red',1.00);
// draw a large green circle at [x=150,y=100] with half alpha
drawParticle(150,100,50,'green',0.50);
function drawParticle(cx,cy,radius,color,alpha){
ctx.beginPath();
ctx.arc(cx,cy,radius,0,Math.PI*2);
ctx.fillStyle=color;
ctx.globalAlpha=alpha;
ctx.fill();
}
For more complex settings you can use if statements to draw the varied settings
For example, this function lets you draw a particle that "ages" from 0 to 100.
Pass in the particle's age as an argument and the function uses if statements to reduce the particle's alpha as it ages.
function drawParticle(cx,cy,radius,color,age){
ctx.beginPath();
ctx.arc(cx,cy,radius,0,Math.PI*2);
ctx.fillStyle=color;
if(age<25){
ctx.globalAlpha=1.00;
}else if(age<50){
ctx.globalAlpha=.75;
}else if(age<75){
ctx.globalAlpha=.50;
}else{
ctx.globalAlpha=.25;
}
ctx.fill();
}

Related

How to create merged shapes based upon blurred originals

I'm using easeljs and attempting to generate a simple water simulation based on this physics liquid demo. The issue I'm struggling with is the final step where the author states they "get hard edges". It is this step that merges the particles into an amorphous blob that gives the effect of cohesion and flow.
In case the link is no longer available, in summary, I've followed the simulation "steps" and created a prototype for particle liquid with the following :
Created a particle physics simulation
Added a blur filter
Apply a threshold to get "hard edges"
So I wrote some code that is using a threshold check to color red (0xFF0000) any shapes/particles that meet the criteria. In this case the criteria is any that have a color greater than RGB (0,0,200). If not, they are colored blue (0x0000FF).
var blurFilter = new createjs.BlurFilter(emitter.size, emitter.size*3, 1);
var thresholdFilter = new createjs.ThresholdFilter(0, 0, 200, 0xFF0000, 0x0000FF);
Note that only blue and red appear because of the previously mentioned threshold filter. For reference, the colors generated are RGB (0,0,0-255). The method r() simply generates a random number up to the passed in value.
graphics.beginFill(createjs.Graphics.getRGB(0,0,r(255)));
I'm using this idea of applying a threshold criteria so that I can later set some boundaries around the particle adhesion. My thought is that larger shapes would have greater "gravity".
You can see from the fountain of particles running below in the attached animated gif that I've completed Steps #1-2 above, but it is this Step #3 that I'm not certain how to apply. I haven't been able to identify a single filter that I could apply from easeljs that would transform the shapes or merge them in any way.
I was considering that I might be able to do a getBounds() and draw a new shape but they wouldn't truly be merged at that time. Nor would they exhibit the properties of liquid despite being larger and appearing to be combined.
bounds = blurFilter.getBounds(); // emitter.size+bounds.x, etc.
The issue really becomes how to define the shapes that are blurred in the image. Apart from squinting my eyes and using my imagination I haven't been able to come to a solution.
I also looked around for a solution to apply gravity between shapes so they could, perhaps, draw together and combine but maybe it's simply that easeljs is not the right tool for this.
Thanks for any thoughts on how I might approach this.

Canvas rendering once, after all actions

A little confused with one moment, appreciate any help.
I'm making an app, that uses canvas for rendering game board.
And I faced a problem that its not optimal, rendering canvas for each little change.
Here's what the structure is at the moment:
function renderCanvas() {
// calling for each row
}
function renderRow() {
// calling for each cell
}
function renderCell() {
// Here i use FillRect and StrokeRect both
}
Functions cooperate with passing context to each other.
Now it renders each cell. And using beginPath appears to deal only with stroke.
I wonder if i can startPath (like beginPath) somehow in renderCanvas function and after all operations with context are done - i could render that all once?
You can only do one styling per beginPath...
So if your cells require different colors, fonts, opacities then you must do a beginPath for each different style (but you can group same-styles together into one beginPath).

HTML5 Canvas - Scaling relative to the center of an object without translating context

I'm working on a canvas game that has several particle generators. The particles gradually scale down after being created. To scale the particles down from their center points I am using the context.translate() method:
context.save();
context.translate(particle.x, particle.y);
context.translate(-particle.width/2, -particle.height/2);
context.drawImage(particle.image, 0, 0, particle.width, particle.height);
context.restore();
I've read several sources that claim the save(), translate() and restore() methods are quite computationally expensive. Is there an alternative method I can use?
My game is targeted at mobile browsers so I am trying to optimize for performance as much as possible.
Thanks in advance!
Yes, just use setTransform() at the end instead of using save/restore:
//context.save();
context.translate(particle.x, particle.y);
context.translate(-particle.width/2, -particle.height/2);
context.drawImage(particle.image, 0, 0, particle.width, particle.height);
//context.restore();
context.setTransform(1,0,0,1,0,0); // reset matrix
Assuming there are no other accumulated transform in use (in which case you could refactor the code to set absolute transforms where needed).
The numbers given as argument are numbers representing an identity matrix, ie. a reset matrix state.
This is much faster than the save/restore approach which stores and restores not only transform state, but style settings, shadow settings, clipping area and what have you.
You could also combine the two translation calls into a single call, and use multiply instead of divide (which is much faster at CPU level):
context.translate(particle.x-particle.width*0.5, particle.y-particle.height*0.5);
or simply use the x/y coordinate directly with the particle "shader" without translating at all.

Rendering multiple objects in WebGL

I have tried following the suggestions given as answer to this questions but I still can't figure out how the "rendering flow" of a WebGL program really works.
I am simply trying to draw two triangles on a canvas, and it works in a rather non-deterministic way: sometimes both triangles are rendered, sometimes only the second one (second as in the last one drawn) is rendered.
(it appears to depend on rendering time: strangely enough, the longer it takes, the better the odds of ending up with both triangles rendered). EDIT: not true, tried refreshing over and over and the two triangles sometimes show up on very rapid renders (~55ms), sometimes on longer-running ones (~120ms). What does seem to be a recurring pattern is that on the very first time the page is rendered, the two triangles show, and on subsequent repeated refreshes the red one either shows for good or for a very short lapse of time, then flickers away.
Apparently I'm missing something here, let me explain my program's flow in pseudo-code (can include the real code if need be) to see if I'm doing something wrong:
var canvas = new Canvas(/*...*/);
var redTriangle = new Shape(/* vertex positions & colors */);
var blueTriangle = new Shape(/* vertex positions & colors */);
canvas.add(redTriangle, blueTriangle);
canvas.init(); //compiles and links shaders, calls gl.enableVertexAttribArray()
//for vertex attributes "position" and "color"
for(shape in canvas) {
for(bufferType in [PositionBuffer, ColorBuffer]) {
shape.bindBuffer(bufferType); //calls gl.bindBuffer() and gl.bufferData()
//This is equivalent to the initBuffers()
//function in the tutorial
}
}
for(shape in canvas) {
shape.draw();
//calls:
//-gl.bindBuffer() and gl.vertexAttribPointer() for each buffer (position & color),
//-setMatrixUniforms()
//-drawArrays()
//This is equivalent to the drawScene() function in the tutorial
}
Despite the fact I've wrapped the instructions inside object methods in my attempt to make the use of WebGLs slightly more OO, it seems to me I have fully complied to the instructions on this lesson (comparing the lesson's source and my own code), hence I cannot figure out what I'm doing wrong.
I've even tried to use only one for(shape in canvas) loop, as so:
for(shape in canvas) {
for(bufferType in [PositionBuffer, ColorBuffer]) {
shape.bindBuffer(bufferType); //calls gl.bindBuffer() and gl.bufferData()
//This is equivalent to the initBuffers()
//function in the tutorial
}
shape.draw();
//calls:
//-gl.bindBuffer() and gl.vertexAttribPointer() for each buffer (position & color),
//-setMatrixUniforms()
//-drawArrays()
//This is equivalent to the drawScene() function in the tutorial
}
but it doesn't seem to have any effect.
Any clues?
I'm guessing the issue is that by default WebGL canvases are cleared everytime they are composited
Try changing your WebGL context creation to
var gl = someCanvas.getContext("webgl", { preserveDrawingBuffer: true });
I'm just guessing your app is doing things asynchronously which means each triangle is drawn in response to some event? So, if both events happen to come in quick enough (between a single composite) then you get both triangles. If they come on different composites then you'll only see the second one.
preserveDrawingBuffer: true says "don't clear after each composite". Clearing is the default because it allows certain optimizations for certain devices, specifically iOS, and the majority of WebGL apps clear at the beginning of each draw operation. Those few apps that don't clear can set preserveDrawingBuffer: true
In your particular case line 21 of angulargl-canvas.js
options = {alpha: false, premultipliedAlpha: false};
try changing it to
options = {alpha: false, premultipliedAlpha: false, preserveDrawingBuffer: true};

Any insights on how to make a canvas drawing not go on top on the other? [duplicate]

This question already has answers here:
How to clear the canvas for redrawing
(25 answers)
Closed 8 years ago.
It's a preety straight up and basic question. I think that because that must be a often action there must be made function, but I can't find it? Is there one? If there isn't does anybody know how to do it?
three ways (at least) :
you can clip your canvas : only the non clipped part will be drawn.
to clip you build a path with beginPath, moveTo, lineTo, arcTo, ... arc,
(any path building function) then you call clip() : the part inside the path
is the clipped-in part.
do not forget to save the context before and to restore it after (unless you want a permanent clip).
snippet :
http://jsbin.com/oSoSugAZ/1/
var context=document.getElementById('cv').getContext('2d');
context.fillStyle='#F66';
context.fillRect(150,150, 500,500); // draw big rect in red
context.save();
context.lineWidth=0; // to have precise clip
context.beginPath();
context.moveTo(100,100);
context.lineTo(200,100);
context.lineTo(200,200);
context.lineTo(100,200);
context.closePath();
context.clip();
// here we can only draw within the rect (100,100) (200,200)
context.fillStyle='#FCE'; // pink
context.fillRect(150,150, 500,500); // will get clipped
context.beginPath();
context.fillStyle = '#AAF';
context.arc(150,150, 30, 0,6.2);
context.fill(); // won't get clipped
// do not forget to restore !
context.restore();
you might use globalCompositeOperation to choose a way the pixel you draw interact with existing ones It works for both drawing paths or images. There are too many options to discuss here, it all depend on your needs.
a full example is here :
https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
Note that darker does not work (but it's not usefull anyway, just use normal mode = source-over with low opacity (0.2) and fillRect in black).
another option is to use temporary canvas to make your draws.
It's very easy, especially if you make small helper functions.
function createCanvas(w,h){
var cv = document.createElement('canvas');
cv.width; cv.height = height;
return cv;
}
( in any case you're interested, you can have a look at my small lib to ease working with a canvas :
https://github.com/gamealchemist/CanvasLib/blob/master/canvasLib.js )
You can't. But you can simulate layers with multiple canvas elements with different z-index.
EDIT:
Check this: canvas layers

Categories