Search code examples
javascriptcanvasdrawingdrawparticles

Particle's code doesn't work. Error on drawing?


Hi there :) just trying to finish this little test with particles, but i'm getting some "extrange" behavior. I will let you two "versions" of the code. It works like this: -I create a particle, passing a "particle settings", it means a particle configuration for liferate, color, spawntype, etc. For now, i only have one particle type "AcidQuads". They are intended to be rects (wich its working ok) but with random initial color if "rndiColor" value is set to true. If it is, the color is generated by passing the list contained on "iRed", "iGreen" and "iBlue" (same stands for iAlpha) to a function (rndbtw). It works fine (or that's what i see). The PARTICLES_SETTINGS properties that have a "list" as a value, means that the particle value will be generated by rndbtw(), which returns a value between propertie's 1 element and 0 (a iRed: [255, 0] will return a number between 0 and 255). I've put an alert to see the values generated for each particle, and they are ok. Color values are correct (between 0 and 255) and everything looks fine... but, the only way i can get particles drawed is by settings iRed/iGreen/iBlue to [0, 255] which generates white particles always, with different alpha. The "working" code is the next:

    </head>
<body>
    <canvas ID="test" width="640" height="480"></canvas>
    <script>

var QUAD    = 1,
    GRAVITY = 0.3;  

var mouse;
    mouse = {x: 0, y: 0};
document.addEventListener('mousemove', function(e){ 
                           mouse.x = e.clientX - 12; 
                           mouse.y = e.clientY - 23 //Fix poco decente! no hagan esto en casa.
                         }, false);

function rndbtw(range)       { return (Math.random()*range[0])+range[1] }
function getRGBA(R, G, B, A) { return 'rgba('+R+','+G+','+B+','+A+')' }




var PARTICLES_SETTINGS = {
    'AcidQuads': {
        //Shape and size related
        shape: QUAD,
        rndSize: true,
        size: {width:  [10, 2],
               height: [10, 2]
              },
        //Color related
        rndiColor: true,
        iRed:   [0, 255], //Here are the color values
        iGreen: [0, 255],
        iBlue:  [0, 255],
        // Alpha
        rndiAlpha: true,
        iAlpha: [1, 0.1],
        // Velocity related
        rndVelocityX: true,
        rndVelocityY: true,
        iVelx: [10, -5],
        iVely: [10, -5],
        // Position related
        xfollowMouse: true,
        yfollowMouse: true,
        // Life related
        rndLiferate: true,
        liferate: [100, 30]
    }
}

var Particle = function(settings, spawnPosition) {
    this.settings = PARTICLES_SETTINGS[settings]
    if (this.settings.rndiColor) {
        //Get random initial color
        //If the color must be random, call rndbtw() passing the two-values list
        this.R = rndbtw(this.settings.iRed);
        this.G = rndbtw(this.settings.iGreen);
        this.B = rndbtw(this.settings.iBlue);
    } else {
        //Or get the specified initial color
        this.R = this.settings.iRed;
        this.G = this.settings.iGreen;
        this.B = this.settings.iBlue;
    }
    this.A = (this.settings.rndiAlpha) ? rndbtw(this.settings.iAlpha):this.settings.iAlpha;
    this.color = getRGBA(this.R, this.G, this.B, this.A); //rgba string for canvas.
    //
    this.velx = (this.settings.rndVelocityX) ? rndbtw(this.settings.iVelx):this.settings.iVelx;
    this.vely = (this.settings.rndVelocityY) ? rndbtw(this.settings.iVely):this.settings.iVely;
    //
    this.x = (this.settings.xfollowMouse) ? mouse.x:spawnPosition[0];
    this.y = (this.settings.yfollowMouse) ? mouse.y:spawnPosition[1];
    //
    this.maxLife = (this.settings.rndLiferate) ? rndbtw(this.settings.liferate):this.settings.liferate;
    //-
    this.shape = this.settings.shape;
    this.size = (this.settings.shape == QUAD) ? {
                                                     width:  (this.settings.rndSize) ? rndbtw(this.settings.size.width):this.settings.size.width,
                                                     height: (this.settings.rndSize) ? rndbtw(this.settings.size.height):this.settings.size.height
                                                  }:(this.settings.shape.POINT)  ? 
                                                    {radius: (this.settings.rndSize) ? rndbtw(this.settings.size.radius):this.settings.size.radius}:'Another shapetype';
    //-
    this.life = 0;
    //
    this.id = particleIndex;
    particles[particleIndex] = this;
    particleIndex++;
    test = 'Color: '+this.color+' /vel(x,y) '+this.velx+','+this.vely+' /type '+this.shape+' /size '+this.size+' /settings '+this.settings+' /id '+this.id;
    alert(test);
}
Particle.prototype.live = function() {
    //Kill?
    if (this.life == this.maxLife) {
        delete particles[this.id];
    }
    //Draw
    ctx.fillStyle = this.color;
    alert(this.color);
    switch (this.shape) {
        case QUAD:
            ctx.fillRect(this.x, this.y, this.size.width, this.size.height);
            break;
    }

    //Update
    this.x += this.velx;
    this.y += this.vely;
    this.vely += GRAVITY;
    this.life++;
    return
}


//--------------------------------------------------//
var particles,
    particleIndex,
    canvas,
    ctx;

canvas = document.getElementById('test');
ctx    = canvas.getContext('2d');
particles = [];
particleIndex = 0;

setInterval(function() {
    for (var i=0; i<=10; i++) {
        new Particle('AcidQuads');
    }
    ctx.fillStyle = '#000000';
    ctx.fillRect(0, 0, 640, 480);
    for (var i in particles) {
        particles[i].live();
    }
}, 30)

    </script>


</body>
</html>

Only white particles with random alpha are drawn. You can see in the alert, that values are only (255,255,255,random). For changing that, and generating random values between 0 and 255, the code will change this:

rndiColor: true,
iRed:   [0, 255],
iGreen: [0, 255],
iBlue:  [0, 255],

to this: rndiColor: true, iRed: [255, 0], iGreen: [255, 0], iBlue: [255, 0],

In the alert, you will se that values will be ok, R,G,B are between 0 and 255, and alpha between 0.1 and 1... But if i change this, i don't see any particle drawn. A few days ago, i made particles with random colors by setting, for example, iRed: function() {return Math.random()*255+0}, and calling "settings.iRed();" to get a random value for red color, but it's a little tedious to make new particles that way... i prefer to put only a list for a range of values. Why, if values are generated ok (between 0 and 255) are not drawn while if i put [min, max] they are but only of one color for every particle? All the other stuff are working fine (velocity, liferate, alpha, and size).

Advanced thanks for help, and please, excuse for my bad english.

By the way... i will replace the setInterval for RequestAnimation, it freeze my browser if i have another web page open xD

Thanks! :)


Solution

  • First : get your head away from any wall before reading this ;-)

    You're using ad DOM 'rgb(,,)' string to define the colors : it expects integer R,G,B in 0..255.

    So just changing rndbtw to :

    function rndbtw(range) { return  Math.floor((Math.random()*range[0])+range[1]) ; }
    

    should bring back the colors !!