Flash a sprite

Here’s a simple program to create an image to flash a Sprite. Uncomment the saveImage() line to save the flash image for later use if you want. Try changing the sprite name in readImage() to try other sprites. You can also change the flash color for the effect you want. Tap the screen to show the flash.

function setup()

    -- this code is used only to create the flash image
    img=readImage("Tyrian Remastered:Boss B")
    iw=img.width
    ih=img.height
    img1=image(iw,ih)
    for x=1,iw do
        for y=1,ih do
            r,g,b,a=img:get(x,y)
            if a>0 then
                img1:set(x,y,255,255,255)  -- change to the color of your choice
            end
        end
    end
    -- end of create flash image
    
    -- uncomment the next line to save the flash image for later use
    -- saveImage("Dropbox:flash",img1)
end

function draw()
    background(0)
    fill(255)
    text("Tap screen to flash",WIDTH/2,HEIGHT-100)
    if flash then
        sprite(img1,WIDTH/2,HEIGHT/2)
        flash=false
    else
        sprite(img,WIDTH/2,HEIGHT/2)
    end
end

function touched(t)
    if t.state==BEGAN then
        flash=true
    end
end

@dave1707 - I found a simpler way to flash, using tint, there’s no need for a second image.

if flash then
        tint(5000,5000,5000)  --the extra line
        sprite(img1,WIDTH/2,HEIGHT/2)
        flash=false
        tint(255) --reset to normal

tint is multiplied by the Sprite colours, and while it is supposed to only use values up to 255, it accepts larger values, so large enough values will turn any sprite white.

EDIT - this method also makes it trivial to vary the flash colours.

@Ignatz That does make it easier. I’m not sure why changing the tint to 255,0,0 (red) doesn’t show the red very well, but using 5000,0,0 does.

That’s because the numbers are divided by 255, so 255 just results in multiplying colours by 1! You need to make it much larger.

@Ignatz you can’t make it flash white though with tint, as tint is a multiply operation, so tint white is the same as noTint.

@yojimbo2000 using 5000,5000,5000 looks white.

@yojimbo2000 - you can cheat by making the tint values greater than 255, so if for example you make them 5120, it effectively multiplies all the colours by 20, since the tint shader will convert them all to fractions of 255.

Wow, I did not know that, you’re right. I think I assumed it clamped the colors like all the other color commands. I’m pretty sure this didn’t come up last time we discussed this on @MajorMorgan 's thread.

Still, if you’re making a hectic arcade game, you should be using rects not sprites, and I’m pretty sure setRectColor does clamp at 255 … Though maybe I need to check that now too…

The mesh functions do clamp. In that case, I would just have a separate one rect mesh with a white image to draw over anything that needs to flash.

I still prefer the shader method from the last thread, no need to create white versions of all your sprites.

http://codea.io/talk/discussion/comment/59478/#Comment_59478

Yes, a shader is probably easiest.

But I’m not so sure about setting all the colours at a quarter of their normal value. There must be an easier way. EDIT - I guess colours don’t need to be precise when you have textures, so your approach works fine.

NB in the shader, you don’t need to clamp the final colour, OpenGL does it for you.

In fact, you can blow out the colours in the vertex shader (vColor variable not clamped).

It’s not hard to set the colours to a quarter of the value:

myMesh:setColors(64)

blowout={
vs=[[
uniform mat4 modelViewProjection;

attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;

varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    vColor = color * 4.; // blow out the colours
    vTexCoord = texCoord;
    
    gl_Position = modelViewProjection * position;
}
]],
fs=[[
precision highp float;

uniform lowp sampler2D texture;

varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    gl_FragColor = texture2D( texture, vTexCoord ) * vColor;
}
]]
}

Ah, I was thinking of the fragment shader, sorry.

No you’re right, there’s no need to clamp the values in the fragment shader