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.
2 Answers
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
.
-
\$\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\$ Commented Feb 23, 2014 at 13:41
-
\$\begingroup\$ how do you "blink" it? a new sprite? \$\endgroup\$ Commented Mar 1, 2014 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\$ Commented Mar 3, 2014 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\$ Commented Mar 15, 2014 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\$ Commented Mar 17, 2014 at 10:51
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.
-
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 withcontext.globalCompositeOperation
\$\endgroup\$– PhilippCommented Apr 17, 2015 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\$ Commented Apr 18, 2015 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\$– PhilippCommented Apr 19, 2015 at 19:44