LED Wall Display: 0 - 99

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Lark
Posts: 178
Joined: Wed Sep 19, 2012 4:23 pm
Location: Springfield, MO USA

LED Wall Display: 0 - 99

Post by Lark »

The following code was developed from looking at a lot of sample code (thank you Lmaoboat) as I teach myself LUA. It displays a one or two digit number between 0 and 99 on a wall. I've tried to document most of it and supply some parameters at the top to allow for some easy changes. It's designed to be embedded into other scripts so the direction the script faces can be different from the wall on which the display is placed using one of the parameters, for example. Since I don't really understand how LUA or GrimRock works internally, things I coded thinking they were efficient may not be. If you know of any inefficiencies, please let me know because there are many ways to implement various things. This was really developed to support another that I've not posted yet.

Image

Code: Select all

---------------------------------------------------------------------------------------
---  LED display:  version 1.4.3  12-9-2014      Written by Lark                    ---
---                                              Much thanks to:  Lmaoboat          ---
---------------------------------------------------------------------------------------

---
---  Light Parameters
---
displayed = self.level       --the initial number displayed by the script
wall = self.facing           --adjust wall used for display from script's facing; i.e. opposite = (self.facing + 2) % 4
initallyOn = true            --specify if the light is initially on

vertical_spacing = .17       --vertical LED spacing
horizontal_spacing = .15     --horizontal LED spacing; center, left, & right values are based on this number being .15
height = 3                   --height above the floor for the top row of LEDs
center = -.3                 --start of row offset for single digit displays
left = -.85                  --start of row offset for left digit
right = .25                  --start of row offset for right digit

---  Usage:
---
---  1.  drop this script into a square facing the wall where the display is desired (or adjust "wall" above)
---  2.  set parameters to suit:  displayed, wall, and initiallyOn for basic parameters
---  3.  on() to display the initial value
---  4.  off() to turn off lights
---  5.  add() to increment by one
---  6.  sub() to decrement by one
---  7.  display(number) to set the display to a new number
---  8.  do not call digit() directly
---
---  Version 1.4.3:   
---    * Fixed issue of storing objects in a non-local table; now just store the object name (Thanks Isaac)
---    * Updated "off" routine to handle names instead of objects.
---    * Removed bad "null" and replaced with "nil" - mixed up LUA and another language...
---    * Improved error checking in the "off" routine - avoids crashes in strange circumstances

---
---  Create a LED panel for numbers 0 - 99.  LED grid is:
---

--   00 01 02 03 04
--   05 06 07 08 09
--   10 11 12 13 14
--   15 16 17 18 19
--   20 21 22 23 24
--   25 26 27 28 29
--   30 31 32 33 34

digits = {
    {1,2,3,5,9,10,14,15,19,20,24,25,29,31,32,33},
    {6,2,7,12,17,22,27,31,32,33},
    {5,1,2,3,9,14,18,22,26,30,31,32,33,34},
    {5,1,2,3,9,14,18,17,16,24,29,33,32,31,25},
    {0,5,10,15,16,17,18,19,3,8,13,23,28,33},
    {4,3,2,1,0,5,10,15,16,17,18,24,29,33,32,31,30},
    {9,3,2,1,5,10,15,20,25,31,32,33,29,24,18,17,16},
    {5,0,1,2,3,4,9,14,18,22,27,32},
    {10,5,1,2,3,9,14,18,17,16,20,25,31,32,33,29,24},
    {25,31,32,33,29,24,19,14,9,3,2,1,5,10,16,17,18}
  }

led = {nil}
cos = math.cos(1.5707963267949 * wall)
sin = math.sin(1.5707963267949 * wall)
tz = 1.3

---
---  divide into digits and display in correct sector
---
function display(number)
  if number == nil then return end
  local b = number % 10
  local a = (number - b) / 10
  off()

  if a > 0 then
    digit(a, left)
    digit(b, right)
  else
    digit(b, center)
    end
  displayed = number
  end

---
---  display a digit of the number at the given alignment and light set
---
function digit(number, align)
  local dix = number + 1
  for ix = 1, 35 do
    local pix = digits[dix][ix]
    if pix == nil then return end
    local tx = align + pix % 5 * horizontal_spacing
    lix = lix + 1

    local light = spawn("fx", self.level, self.x, self.y, 3, self.id.."_"..lix)
    led[lix] = light.id
    light:setLight(1, 0, 0, 1500, 0.24, 360000, false)
    light:translate(tx * cos + tz * sin, height - math.floor(pix / 5) * vertical_spacing - 1, tz * cos + tx * sin * (1 - wall%2 * 2))    
    
    end
  end

---
---  add one to the current display w/ wrap
---
function add()
  display((displayed + 1)%100)
  end

---
---  subtract one from the current display w/ wrap
---
function sub()
  display((displayed + 99)%100)
  end

---
---  turn lights off
---
function off()
  if lix ~= nil and led ~= {nil} then
    for dix = 1, lix do
      local light = findEntity(led[dix])
      if light ~= nil then light:destroy() end
      end
    end
  lix = 0
  led = {nil}
 end

---
---  turn lights on
---
function on()
  display(displayed)
  end

---
---  turn lights on if specified in parameters
---
if initallyOn then on() end
I'm still tweaking the script, so I thought I'd put it in its own thread and post (or edit) later versions into it. Please let me know if you find this useful or if you have any enhancement requests.

Thank you, -Lark

Updated to version 1.4.1 on 10-10-2012
Updated to version 1.4.3 on 12-09-2014
Last edited by Lark on Wed Dec 10, 2014 7:43 am, edited 2 times in total.
Lmaoboat
Posts: 359
Joined: Wed Apr 11, 2012 8:55 pm

Re: LED Wall Display: 0 - 99

Post by Lmaoboat »

Seems a lot more properly done than mine was. I was lucky that I even vaguely recalled what tables were, otherwise I might have still been using 10 functions with a translate function for each dot in each.
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: LED Wall Display: 0 - 99

Post by Isaac »

Lark wrote:...
That is very cool.
Does it glow in the dark?
User avatar
Komag
Posts: 3658
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: LED Wall Display: 0 - 99

Post by Komag »

That's pretty awesome, and nicely written out code with all the notes, love it :)

You should definitely add it to the script repository (and soon to the wiki!)
Finished Dungeons - complete mods to play
wickermoon
Posts: 21
Joined: Fri Apr 13, 2012 10:48 am

Re: LED Wall Display: 0 - 99

Post by wickermoon »

Just two short remarks:

1. local tx = align + (pix - 0) % 5 * horizontal_spacing <--- why'd you subtract 0? legacy code?
2. Instead of nested if-clauses, you could use sine and cosine functions to calculate which value goes to tx and which to tz. I'm not entirely sure if this would be more efficient computing-wise, but it would at least look more elegant. XD

Without much more thought about it, a short explanation:

-- considered that facing can have 0,1,2 and 3 as values
-- x being your REAL x variable, while tx and tz are your calculated values, or 1.3 respectively
- x = tx * sin(90*facing) + tz * cos(90*facing); The problem here is with sin(0) and sin(180) as both evaluate to 0 (which isn't signed). Adding 1° and then dividing by the absolute value of it would fix that, probably...yeah, why simple, if you can make it that complicated, right? But the elegancy! XD

Anyway, that's some nice script there! :)

P.S.: If you'd use the radiant system (I think) it would work...I think...I'll have to put more thought into this.

Edit: DERP....You'd want to be sin(0) and sin(180) to be zero - respectively cos(90) and cos(270) - to cancel out the corresponding tx or tz. -_-'
User avatar
Lark
Posts: 178
Joined: Wed Sep 19, 2012 4:23 pm
Location: Springfield, MO USA

Re: LED Wall Display: 0 - 99

Post by Lark »

Thanks to everyone for your kind comments. I'm slowly learning how this works!
wickermoon wrote:1. local tx = align + (pix - 0) % 5 * horizontal_spacing <--- why'd you subtract 0? legacy code?
2. Instead of nested if-clauses, you could use sine and cosine functions to calculate which value goes to tx and which to tz. I'm not entirely sure if this would be more efficient computing-wise, but it would at least look more elegant. XD
Yes, in spite of my cleanup efforts, the "pix - 0" was left over when I shifted the LED numbers from starting at one to starting at zero. In development, I changed it to "- 0" to remember what I was changing (silly boy), but accidentally left it in. I'll edit the script above to remove it.

I like the idea of using sine and cosine functions - I never thought of that, but it should work. You'd naturally suspect it wouldn't be more efficient since sin(x) = (x) - (x^3)/3! + (x^5)/5! - ..., for example, which is pretty complicated and slow to calculate, and of course there's CORDIC (COordinate Rotation DIgital Computer) methods, but modern processors implement transcendental functions in hardware, so it should be about as efficient (and more elegant as noted). I think I'll try it after I get my next script posted.

Thanks Everyone! -Lark
Lmaoboat
Posts: 359
Joined: Wed Apr 11, 2012 8:55 pm

Re: LED Wall Display: 0 - 99

Post by Lmaoboat »

I'm starting to wish I payed attention in Trig.
wickermoon
Posts: 21
Joined: Fri Apr 13, 2012 10:48 am

Re: LED Wall Display: 0 - 99

Post by wickermoon »

I think the functions to use would be:

x = tx * sin(90 * facing) + tz * cos(90 * facing);
z = tx * cos(90 * (facing + 1)) + tz * sin(90 * (facing + 1));

Reasoning:

__ x z
0 tx tz
1 tz -tx
2 -tx -tz
3 -tz tx

z is shifted by 90° of x plus-wise - if you know what I mean ;) ... no, really, I have no idea how to say this in english.

edit:

also this:

led[lix]:translate(0,-1,0)
led[lix]:translate(tx, height - math.floor((pix - 0) / 5) * vertical_spacing, tz)

could probably be written in one line, or am I missing something? It would take away one (unnecessary) vector translation. :)
Last edited by wickermoon on Wed Oct 10, 2012 9:08 pm, edited 1 time in total.
User avatar
Lark
Posts: 178
Joined: Wed Sep 19, 2012 4:23 pm
Location: Springfield, MO USA

Re: LED Wall Display: 0 - 99

Post by Lark »

Isaac wrote: That is very cool.
Does it glow in the dark?
Thank you; I’m glad you like it! It's fun working together to help each other improve our work. And yes, it does glow in the dark. -Lark
User avatar
Lark
Posts: 178
Joined: Wed Sep 19, 2012 4:23 pm
Location: Springfield, MO USA

Re: LED Wall Display: 0 - 99

Post by Lark »

wickermoon wrote:x = tx * sin(90 * facing) + tz * cos(90 * facing);
z = tx * cos(90 * (facing + 1)) + tz * sin(90 * (facing + 1));
The more optimizations I do, the more I find. I implemented the functions above, with some modifications (thank you Wickermoon), and got them working. Then I pulled the sign inversion out and calculated the sine and cosine only once pulling them out of the loop altogether. Then I pulled a few more constants out, yet there are still some calculations that need be done only once that I can pull out. So the work is yet in progress, but hopefully more elegant all the time.

I've thought of adding countdown/up timers, color selection, random or ranges of color, but I don't know if anyone would use them. Changing the color is easy, and I might use the count down/up timers for something. Like pull a lever in a room of monsters, the timer starts rapidly dropping to zero, and then ***BOOM*** the room is filled with tons of explosions killing everyone, including you if you didn't run. The color could change from green to red as it got closer to zero. Flashing displays would need simple timers, but I could add those in too. Who knows?

Anyway, if you want something, let me know.

Thanks, -Lark
Post Reply