How to do lightning

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Gunroar:Cannon()
Party member
Posts: 1088
Joined: Thu Dec 10, 2020 1:57 am

Re: How to do lightning

Post by Gunroar:Cannon() »

Was skeptical to give this a try since I already had a working one but ...
darkfrei wrote: Thu Jul 14, 2022 10:30 am (not tested)

Code: Select all

local source ={x=0, y=0}
local target ={x=800, y=600}

local lightning= {
  source=source,
  target=target,
  mainLine={source, target},
}

function addPoint (lightning, index) -- index = math.random(#lightning.mainLine -1)
  local x1=lightning.mainLine[index].x
  local y1=lightning.mainLine[index].y
  local x2=lightning.mainLine[index+1].x
  local y2=lightning.mainLine[index+1].y
  local t = 0.25 + 0.5*math.random()
  local x = x1+ t*(x2 - x1)
  local y = y1+ t*(y2 - y1)
  x = x + 0.25*(y2 - y1)* (math.random()-1)
  y = y + 0.25*(x2 - x1)* (math.random()-1)
  table.insert (lightning.mainLine, index+1, {x=x,y=y})
end

But just gave it a try and...:

Code: Select all


local source ={x=0, y=0}
local target ={x=300, y=love.graphics.getHeight()}

local lightning= {
  source=source,
  target=target,
  mainLine={source, target},
}

function addPoint (lightning, index) -- 
index = math.random(#lightning.mainLine -1)
  local x1=lightning.mainLine[index].x
  local y1=lightning.mainLine[index].y
  local x2=lightning.mainLine[index+1].x
  local y2=lightning.mainLine[index+1].y
  local t = 0.25 + 0.5*math.random()
  local x = x1+ t*(x2 - x1)
  local y = y1+ t*(y2 - y1)
  x = x + 0.25*(y2 - y1)* (math.random()-1)
  y = y + 0.25*(x2 - x1)* (math.random()-1)
  table.insert (lightning.mainLine, index+1, {x=x,y=y})
end

function reload()
    lightning.mainLine = {
      lightning.mainLine[1],
      lightning.mainLine[#lightning.mainLine]
    }

    for x = 1 , math.random(30,50) do--or 10,18 or anything
        addPoint(lightning)
    end
end

local t = .1
local time = 0
function love.update(dt)
    time = time -dt
    if time <= 0 then
        time = t
        reload()
    end
end    

function love.draw()
    for xx, ii in ipairs(lightning.mainLine) do
        local o = lightning.mainLine[xx-1]
        local ox = o and o.x or ii.x
        local oy = o and o.y or ii.y
        love.graphics.line(ox,oy,ii.x,ii.y)

    end
end
It works like magic, lightning magic! My other version produces loops sometimes and kind of looks weird once in a while.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
darkfrei
Party member
Posts: 1173
Joined: Sat Feb 08, 2020 11:09 pm

Re: How to do lightning

Post by darkfrei »

Gunroar:Cannon() wrote: Fri Jul 29, 2022 6:50 pm
It works like magic, lightning magic! My other version produces loops sometimes and kind of looks weird once in a while.
Here is a good solution (in this time tested):
(press left mouse button and right mouse button to move the source and target)

Code: Select all

-- License CC0 (Creative Commons license) (c) darkfrei, 2022

local source ={x=100, y=300}
local target ={x=700, y=300}

lightning= {
  source=source,
  target=target,
  mainLine={source, target},
}

function addPoint (lightning, index) -- index = math.random(#lightning.mainLine -1)
  local x1=lightning.mainLine[index].x
  local y1=lightning.mainLine[index].y
  local x2=lightning.mainLine[index+1].x
  local y2=lightning.mainLine[index+1].y
  local t = 0.25 + 0.5*math.random()
  local x = x1+ t*(x2 - x1)
  local y = y1+ t*(y2 - y1)
  x = x + 0.25*(y2 - y1)* (math.random()-0.5)
  y = y + 0.25*(x2 - x1)* (math.random()-0.5)
  table.insert (lightning.mainLine, index+1, {x=x,y=y})
end
 
function love.update(dt)
	-- reset the line
	lightning= {
	  source=source,
	  target=target,
	  mainLine={source, target},
	}
	for i = 1, 10 do
		local index = math.random(#lightning.mainLine -1)
		addPoint (lightning, index)
	end
end

function love.draw()
	for i = 1, #lightning.mainLine-1 do
		local v1 = lightning.mainLine[i]
		local v2 = lightning.mainLine[i+1]
		love.graphics.line (v1.x, v1.y, v2.x, v2.y)
	end
end

function love.mousepressed( x, y, button, istouch, presses )
	if button == 1 then -- left mouse button
		source ={x=x, y=y}
	elseif button == 2 then -- right mouse button
		target ={x=x, y=y}
	end
end

function love.keypressed(key, scancode, isrepeat)
	if false then
	elseif key == "escape" then
		love.event.quit()
	end
end
I see some ways for optimization, but this solution is clean to read.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
Gunroar:Cannon()
Party member
Posts: 1088
Joined: Thu Dec 10, 2020 1:57 am

Re: How to do lightning

Post by Gunroar:Cannon() »

darkfrei wrote: Fri Jul 29, 2022 9:04 pm
Gunroar:Cannon() wrote: Fri Jul 29, 2022 6:50 pm
It works like magic, lightning magic! My other version produces loops sometimes and kind of looks weird once in a while.
Here is a good solution (in this time tested):
(press left mouse button and right mouse button to move the source and target)

Code: Select all

-- License CC0 (Creative Commons license) (c) darkfrei, 2022

local source ={x=100, y=300}
local target ={x=700, y=300}

lightning= {
  source=source,
  target=target,
  mainLine={source, target},
}

function addPoint (lightning, index) -- index = math.random(#lightning.mainLine -1)
  local x1=lightning.mainLine[index].x
  local y1=lightning.mainLine[index].y
  local x2=lightning.mainLine[index+1].x
  local y2=lightning.mainLine[index+1].y
  local t = 0.25 + 0.5*math.random()
  local x = x1+ t*(x2 - x1)
  local y = y1+ t*(y2 - y1)
  x = x + 0.25*(y2 - y1)* (math.random()-0.5)
  y = y + 0.25*(x2 - x1)* (math.random()-0.5)
  table.insert (lightning.mainLine, index+1, {x=x,y=y})
end
 
function love.update(dt)
	-- reset the line
	lightning= {
	  source=source,
	  target=target,
	  mainLine={source, target},
	}
	for i = 1, 10 do
		local index = math.random(#lightning.mainLine -1)
		addPoint (lightning, index)
	end
end

function love.draw()
	for i = 1, #lightning.mainLine-1 do
		local v1 = lightning.mainLine[i]
		local v2 = lightning.mainLine[i+1]
		love.graphics.line (v1.x, v1.y, v2.x, v2.y)
	end
end

function love.mousepressed( x, y, button, istouch, presses )
	if button == 1 then -- left mouse button
		source ={x=x, y=y}
	elseif button == 2 then -- right mouse button
		target ={x=x, y=y}
	end
end

function love.keypressed(key, scancode, isrepeat)
	if false then
	elseif key == "escape" then
		love.event.quit()
	end
end
I see some ways for optimization, but this solution is clean to read.
Wow, nice. You're other version (the one I put in code above) works well too (it's my version on the first page that's weird).
What do you think could be optimized. I see that the lightning doesn't have to be reset on every update but besides that it seems pretty optimal.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
darkfrei
Party member
Posts: 1173
Joined: Sat Feb 08, 2020 11:09 pm

Re: How to do lightning

Post by darkfrei »

Here is with optimizations:

Code: Select all

-- License CC0 (Creative Commons license) (c) darkfrei, 2022

lightning1 = {
	source={x=200, y=300},
	target={x=600, y=300},
	mainLine={},
}

lightning2 = {
	source={x=250, y=450},
	target={x=550, y=450},
	mainLine={},
}

function reset (lightning)
	lightning.mainLine={lightning.source.x, lightning.source.y, lightning.target.x, lightning.target.y}
end

function addPoint (lightning, bool)
	local line = lightning.mainLine
	local index = math.random(#line/2 -1)*2-1
	local x1, y1=line[index], line[index+1]
	local x2, y2=line[index+2], line[index+3]
	local t = 0.25 + 0.5*math.random()
	local x = x1- t*(x2 - x1) -- must be minus!
	local y = y1+ t*(y2 - y1)
	x = x + 0.25*(y2 - y1)* (math.random()-0.5)
	if bool then
		y = y + 0.125*(x2 - x1)* (math.random()-1)
	else
		y = y + 0.25*(x2 - x1)* (math.random()-0.5)
	end
	table.insert (lightning.mainLine, index+2, y)
	table.insert (lightning.mainLine, index+2, x)
end
 
function love.update(dt)
	-- reset the line
	reset (lightning1)
	reset (lightning2)
	for i = 1, 10 do
		addPoint (lightning1)
		addPoint (lightning2, true) -- higher then straight line
	end
end

function love.draw()
	love.graphics.setLineWidth (2)
	love.graphics.setColor (1,1,1)
	love.graphics.line (lightning1.mainLine)
	
	love.graphics.setLineWidth (1)
	love.graphics.setColor (0,1,1)
	love.graphics.line (lightning2.mainLine)
end

function love.mousepressed( x, y, button, istouch, presses )
	if button == 1 then -- left mouse button
		lightning1.source ={x=x, y=y}
	elseif button == 2 then -- right mouse button
		lightning1.target ={x=x, y=y}
	end
end

function love.keypressed(key, scancode, isrepeat)
	if false then
	elseif key == "escape" then
		love.event.quit()
	end
end
Animation (51).gif
Animation (51).gif (498.74 KiB) Viewed 1714 times
Last edited by darkfrei on Thu Nov 10, 2022 3:08 pm, edited 1 time in total.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
Gunroar:Cannon()
Party member
Posts: 1088
Joined: Thu Dec 10, 2020 1:57 am

Re: How to do lightning

Post by Gunroar:Cannon() »

Oh, though not important, your version can't have branching lighting. Still fine though.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
darkfrei
Party member
Posts: 1173
Joined: Sat Feb 08, 2020 11:09 pm

Re: How to do lightning

Post by darkfrei »

Gunroar:Cannon() wrote: Tue Aug 02, 2022 7:13 pm Oh, though not important, your version can't have branching lighting. Still fine though.
Just create near the target other targets and use some middle points as source for the new lightning.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
Post Reply

Who is online

Users browsing this forum: No registered users and 54 guests