# Electricity effect

I took the kids to ascience museum recently and they had a few tablets set up with an electricity style effect. Thought I’d share mine here, still lots of stuff which could improve it!

https://imgur.com/a/QDtEEN7

ElectricityEffect.zip (1.8 KB)

``````-- ElectricityEffect

local touchArcs = {}
local contact = nil

-- Use this function to perform your initial setup
function setup()
viewer.mode = FULLSCREEN
screenBody = physics.body( POLYGON,
vec2(0,0),
vec2(0, HEIGHT),
vec2(WIDTH, HEIGHT),
vec2(WIDTH, 0) )

screenBody.type = STATIC
end

-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(0, 40, 50)

-- This sets the line thickness
strokeWidth(5)

stroke(0, 178, 255)

for _, bolt in pairs(touchArcs) do
local points = computeLightningArc(bolt.origin, bolt.destination)
for i = 1, #points do
if i == #points then
break
end

line(points[i].x, points[i].y, points[i+1].x, points[i+1].y)
end
end

if contact ~= nil then
ellipse(contact.x, contact.y, 200)
end
end

function nearestScreenEdgeInDirection(origin, direction)
-- Find a point really far outside the screen
local outsidePoint = origin + direction * 10000

-- Then raycast back in to find a point along the edge
local result = physics.raycast(outsidePoint, origin)
if result then
return result.point
end

return nil
end

function computeLightningArc(origin, destination)

local points = {}
local numPoints = 10.0
local maxLength = origin:dist(destination)
local maxStepVariation = 1.0
local direction = (destination - origin):normalize()

-- Calculate the initial step size between each point
local stepSize = maxLength / numPoints

table.insert(points, origin)

for i = 1, numPoints do
-- Randomize the step size for each point
local stepVariation = (math.random() * 2 - 1) * maxStepVariation
local currentStepSize = stepSize + stepVariation

-- Calculate the distance from offset for the current point
local distance = currentStepSize * i

-- Calculate the angle multiplier using cosine interpolation
local x = (i - 1) / (numPoints - 1)
local angleMultiplier = 0.02 * math.cos(math.pi * x - (math.pi/2.0))

-- Generate a random angle within a certain range
local angle = (math.random() * 2.0 - 1.0) * math.pi * angleMultiplier

local nextDirection = (direction * distance):rotate(angle)

-- Calculate the position of the point
local point = origin + nextDirection -- direction * distance -- + vec2(math.cos(angle), math.sin(angle)) * distance

-- Add the point to the table
table.insert(points, point)
end

return points
end

function touched(touch)
if touch.state == BEGAN then
for i = 1, 20 do
table.insert(touchArcs, {
origin = nearestScreenEdgeInDirection(touch.pos, vec2(1,0):rotate(math.random() * 2 * math.pi)),
destination = touch.pos
})
end
elseif touch.state == CHANGED then
for _, bolt in pairs(touchArcs) do
bolt.destination = touch.pos
end
else
touchArcs = {}
end
end

``````
3 Likes

@sim been away a while, but picking back up with Codea. Reminded me of this old thread: Lightning touch

1 Like

Hah I like yours better, nice work!

1 Like