Missile Command Splosion Effect

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Davidobot
Party member
Posts: 1226
Joined: Sat Mar 31, 2012 5:18 am
Location: Oxford, UK
Contact:

Re: Missile Command Splosion Effect

Post by Davidobot »

An interesting solution to this problem, without using any shaders would be to use the wonderful stencils.
Note: You cannot pass variables to stencils and need to make all the values global for that file at least. (the following is untested psuedo code)

Code: Select all

local r, x, y = 100, 200, 200
local function circleStencil()
   love.graphics.circle("fill", x, y, r, 50)
end

function love.draw()
     r, x, y = -- Whatever the first explosion is
     love.graphics.stencil(circleStencil, "increment", 1, false) -- This increments and clears the previous frame's the shader buffer (think of it as a depth buffer) in the circle's region by 1
     r, x, y = -- Whatever the second explosion is
     love.graphics.stencil(circleStencil, "increment", 1, true) -- The true ensures that the shader buffer is retained 

    -- Only allow rendering on pixels which have a stencil value less than or equal to 1 (not in intersection).
    love.graphics.setStencilTest("lequal", 1)
    -- Draw all explosions with the yellow color

     -- Only allow rendering on pixels which have a stencil value greater than 1 (in intersection).
    love.graphics.setStencilTest("greater", 1)
    -- Draw all explosions with the green color
end
EDIT: Found and fixed a small logical error with the shader buffer clearing and added more explanations.
PM me on here or elsewhere if you'd like to discuss porting your game to Nintendo Switch via mazette!
personal page and a raycaster
User avatar
slime
Solid Snayke
Posts: 3170
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Missile Command Splosion Effect

Post by slime »

Davidobot wrote:Note: You cannot pass variables to stencils and need to make all the values global for that file at least.
You can pass a local or anonymous function which will capture local variables from the scope that the function was defined in.

For example:

Code: Select all

function love.draw()
    local x1, y1 = 100, 100
    local r1 = 100

    local x2, y2 = 200, 100
    local r2 = 200

    local function drawCircles()
        love.graphics.circle("fill", x1, y1, r1)
        love.graphics.circle("fill", x2, y2, r2)
    end

    -- Anywhere touched by any circle will have its stencil value increased by 1 (so it'll be at least 2, where they overlap).
    love.graphics.stencil(drawCircles, "increment")

    -- love.graphics.setStencilTest etc.
end
It's also a bit more efficient to batch things up into fewer love.graphics.stencil calls if possible (i.e. doing multiple draws in a single stencil).
User avatar
Davidobot
Party member
Posts: 1226
Joined: Sat Mar 31, 2012 5:18 am
Location: Oxford, UK
Contact:

Re: Missile Command Splosion Effect

Post by Davidobot »

slime wrote: You can pass a local or anonymous function which will capture local variables from the scope that the function was defined in.
Oh, that's interesting, but meant it more like can't do this:

Code: Select all

love.graphics.stencil(stencilFun(x, y, r), "increment")
slime wrote: It's also a bit more efficient to batch things up into fewer love.graphics.stencil calls if possible (i.e. doing multiple draws in a single stencil).
Ooh, alright! Will that have the exact same effect as my code? (Result in numbers of 2 and higher in intersecting areas)? EDIT: Yes it does.

I modified OP's code to implement this method, works flawlessly:
Image
Image
Attachments
MiddleCommand.love
Uses LOVE 0.10.0
(5.21 KiB) Downloaded 62 times
PM me on here or elsewhere if you'd like to discuss porting your game to Nintendo Switch via mazette!
personal page and a raycaster
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 5 guests