Jump to content

Light shorting out

darthlukan

1,582 views

For my current project I wanted to simulate a light that's shorting out in order to add a bit of a creepy ambience to my scene. After a while of messing with the different things that could be done with an emitter (and failing at getting the effect I wanted), I realized that really, a light that's shorting out is really a light that's turning off and on again. Well, that's something that can be scripted pretty easily thanks to Leadwerk's API.

 

 

There are a couple of obvious ways to get the desired effect:

  1. Create the light in a given position, then remove it again. This can be a pain and can also be resource intensive
     
  2. Toggle the light's color between the "on" and "off" colors, where "off" is transparent and "on" is any color with a visible alpha.

Needless to say, I chose the latter.

 

First I needed to define some colors. For my purposes, I wanted to be able to set colors between Red, Green, Blue, and White, so in my Scripts/Objects/Lights/ShortedBlink.lua file I added the following:

 

function Script:Start()
   self.colors = {}
   self.colors["red"] = Vec4(1, 0, 0, 0)
   self.colors["green"] = Vec4(0, 1, 0, 0)
   self.colors["blue"] = Vec4(0, 0, 1, 0)
   self.colors["white"] = Vec4(1, 1, 1, 0)
   if self.color_on == nil then
       self.color_on = self.colors[string.lower(self.OnColor)]
   end
   self:On()
end

 

 

Then it came time to fill in the "on()" and "off()" functions:

 

function Script:On()
   self.entity:SetColor(self.color_on)
   self.component:CallOutputs("On")
   self.isOn = true
end

function Script:Off()
   self.entity:SetColor(self.color_off)
   self.component:CallOutputs("Off")
   self.isOn = false
end

 

 

I then defined a few top-level variables that I knew I would need, one of which needed to be available to the Leadwerks Editor, namely "OnColor" (the desired activated color). Here's what the top of the file looks like:

 

Script.enabled = true
Script.isOn = true
Script.OnColor = "red"	  -- string "Active Color"
Script.color_on = nil
-- transparent
Script.color_off = Vec4(0, 0, 0, 0)

 

 

Now that I had my top-level variables defined coupled with on and off functions, it was time to add a ToggleLight() function that would do the work:

 

function Script:ToggleLight()
   if self.isOn then
    self:Off()
   else
    self:On()
   end
end

 

Pretty self-explanatory. If isOn is true then the light is on, so turn it off, else turn it on.

 

This script is missing one thing: UpdateWorld()

 

function Script:UpdateWorld()
 self:ToggleLight()
end

 

I was pretty happy with myself up until I attached this script to a spotlight and almost suffered an epileptic seizure...

 

Thankfully, the answer was pretty clear: I needed to add some sort of a delay. After some experimentation, the desired effect was achieved by performing some modulo division:

 

function Script:UpdateWorld()
   if Time:Millisecs() % 11 == 0 then
    self:ToggleLight()
   end
end

 

Basically, we're taking the current time in milliseconds and seeing if it's evenly divisible by 11. If it is, then toggle the light, else leave the light's state alone. I probably could have gone with a better way of randomizing the delay, but this one works just fine and isn't resource intensive at all (if a computer struggles to perform a simple math operation, put it out of its misery).

 

The completed script looks like this:

 

Script.enabled = true
Script.isOn = true
Script.OnColor = "red"	  -- string "Active Color"
Script.color_on = nil
-- transparent
Script.color_off = Vec4(0, 0, 0, 0)

function Script:Start()
   self.colors = {}
   self.colors["red"] = Vec4(1, 0, 0, 0)
   self.colors["green"] = Vec4(0, 1, 0, 0)
   self.colors["blue"] = Vec4(0, 0, 1, 0)
   self.colors["white"] = Vec4(1, 1, 1, 0)
   if self.color_on == nil then
    self.color_on = self.colors[string.lower(self.OnColor)]
   end
   self:On()
end

function Script:On()
   self.entity:SetColor(self.color_on)
   self.component:CallOutputs("On")
   self.isOn = true
end

function Script:Off()
   self.entity:SetColor(self.color_off)
   self.component:CallOutputs("Off")
   self.isOn = false
end

function Script:ToggleLight()
   if self.isOn then
    self:Off()
   else
    self:On()
   end
end

function Script:UpdateWorld()
   if Time:Millisecs() % 11 == 0 then
    self:ToggleLight()
   end
end

 

 

Just add the script to a light source, type in the color you want (from the choices available within the script) and watch what happens the next time you debug or play your game.

 

Hopefully this saves someone some time in the future.



2 Comments


Recommended Comments

Couldn't you set the lights visible to false?

 

You mean like

self:Show() or self:Hide()

?

 

That's another way to do it. I'm using the same script elsewhere in the game to simulate a discoball and just overriding the color_on, color_off and UpdateWorld settings. If I relied on Show and Hide then that discoball script would have required more code. I'm also not sure of the performance difference between using Show/Hide versus SetColor.

Share this comment


Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...