0
\$\begingroup\$

I'm thinking of the flashing effect many games have when a character gets hit and takes damage. Something like overlaying a lighter color on visible sprite pixels for a second.

\$\endgroup\$
5
\$\begingroup\$

The simplest way to get such an effect is to literally blink the sprite: Just don't draw it half the time.

var frequency = 200;
if (! blinking || Math.floor(Date.now() / frequency) % 2) {
    ctx.drawImage(...);
}

The idea is that when blinking is set to true, the sprite will flash at the given frequency.

\$\endgroup\$
  • \$\begingroup\$ @Anko thanks a lot for your edit! Your rephrase just makes amazing difference and ease of reading. I need to get to that level as well (I am russian...) :) \$\endgroup\$ – Maksims Mihejevs Feb 23 '14 at 13:41
  • \$\begingroup\$ how do you "blink" it? a new sprite? \$\endgroup\$ – user3065579 Mar 1 '14 at 12:08
  • \$\begingroup\$ Sorry, could you show first what have you tried and what did not worked? As it looks like you are asking the question on answer that is already is given to you. \$\endgroup\$ – Maksims Mihejevs Mar 3 '14 at 17:06
  • \$\begingroup\$ i didnt try anything because i dont know how to approach this problem... lets say a have a sprite of the hero, there are pixels that define his shape and transparent pixels around him inside the sprite. i want to overlay/change the color or whatever of the non-transparent pixels of the sprite how it is known from games when characters are hit/take damage, they flash often in a white color or something. this is the effect i want to achieve. i cant use another sprite of the exact shape as my hero character can equip items which change his shape and also a whole set of sprites would be overkill \$\endgroup\$ – user3065579 Mar 15 '14 at 10:04
  • \$\begingroup\$ I see your needs, but without another premade sprites (can be dynamically generated rather than downloaded), there are no many options you can go.. <canvas> 2d is simplified thing by intention. \$\endgroup\$ – Maksims Mihejevs Mar 17 '14 at 10:51
0
\$\begingroup\$

As Maksim said about canvas pixels. You can draw your sprites in unusual way. I can share what I have been working on last week.

function drawImageBlended(src, sx, sy, dest, dx, dy, w, h, blendMode) {
    var srcCont = src.getContext("2d");
    var srcData = srcCont.getImageData(sx,sy,w,h);
    var sPixels = srcData.data;
    var destCont = dest.getContext("2d");
    var destData = destCont.getData(dx,dy,w,h);
    var dPixels = destData;
    var a = 0;
    for (var i = 0, il = sPixels.length; i < il; i += 4) {
        a = sPixels[i+3];
        if (a!==0) {//Skipif alpha is 0
            dPixels[i] = blend(dPixels[i], sPixels[i], blendMode, a);
            dPixels[i+1] = blend(dPixels[i+1], sPixels[i+1], blendMode, a);
            dPixels[i+2] = blend(dPixels[i+2], sPixels[i+2], blendMode, a);
        }
    }
    destCont.putImageData(destData,dx,dy);
}

function drawImageBlendedWithColor(src, sx, sy, dest, dx, dy, w, h, rgb, blendColorMode, blendMode) {//rgb = {r,g,b} each [0..255]
    var srcCont = src.getContext("2d");
    var srcData = srcCont.getImageData(sx,sy,w,h);
    var sPixels = srcData.data;
    var destCont = dest.getContext("2d");
    var destData = destCont.getData(dx,dy,w,h);
    var dPixels = destData;
    var a = 0;
    for (var i = 0, il = sPixels.length; i < il; i += 4) {
        a = sPixels[i+3];
        if (a!==0) {//Skipif alpha is 0
            dPixels[i] = blend(blend(rgb[0], dPixels[i], blendColorMode,a), sPixels[i], blendMode, a);
            dPixels[i+1] = blend(blend(rgb[1], dPixels[i+1], blendColorMode,a), sPixels[i+1], blendMode, a);
            dPixels[i+2] = blend(blend(rgb[2], dPixels[i+2], blendColorMode,a), sPixels[i+2], blendMode, a);
        }
    }
    destCont.putImageData(destData,dx,dy);
}

function overlay(a, b) { // a, b = [0..256]
    return (a < 128) ? (a*b) >> 7 : 255 - ((255-a) * (255-b) >> 7);
}

function multiply(a, b) { // a, b = [0..256]
    return a * b >> 8;
}

function screen(a, b) { // a, b = [0..256]
    return 255 - ((255 - a) * (255 - b) >> 8);
}

function blend( a, b, mode, o) { // a, b, o = [0..256]
    return a + ((mode(a, b) - a) * o >> 8);
}

drawImageBlended takes your sprite canvas (hope its on canvas) and destination canvas, reads every pixel in drawing boundaries and blends in your sprite canvas. If your hero is not a canvas but many sprites, think of doing its own small canvas to pre draw it on, and feed to this function. For other Blend modes visit pegtop site There you will find effective delphi code and mathematical formulas. Pretty and comfy.

I hope my untested code will work, because I just piled it up from my scratches. Yeagh, I could do something like

CanvasRenderingContext2DPrototype.prototype.drawImageBlended= function (src, sx, sy, dx, dy, w, h, blendMode) { var dest = this; ...}

But I'm not going to test it. Good luck with that.

\$\endgroup\$
  • 1
    \$\begingroup\$ Instead of implementing your own alpha blending algorithm in Javascript it might be better to use context.globalAlpha. It seems to do the same as what you suggested but it is usually hardware-accelerated and thus much faster. Multiply, screen and some other blending modes are also supported out-of-the-box with context.globalCompositeOperation \$\endgroup\$ – Philipp Apr 17 '15 at 11:28
  • \$\begingroup\$ Not in IE. IE does not know about adobes blending modes. Or at least that version I tested on. I also found that topic on adobes blogs. I was so happy until I realized... It doesn't work on everybody's browsers. \$\endgroup\$ – zORg Alex Apr 18 '15 at 0:03
  • \$\begingroup\$ My life as a HTML5 game developer became a lot more enjoyable the day I decided to deny the existence of Microsoft Internet Explorer. \$\endgroup\$ – Philipp Apr 19 '15 at 19:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.