main.lua 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. local moonshine = require"moonshine"
  2. local PI = math.pi
  3. local TWOPI = 2 * PI
  4. local HALFPI = PI / 2
  5. local segments = {sec = 60, min = 60, hour = 24}
  6. local conf = {
  7. font = {name = "ledfont.otf", size = 96},
  8. canvassize = 1024,
  9. padding = 10, linethickness = 5,
  10. clockscale = 0.55,
  11. dials = {
  12. sec = {radius = 0.98, width = 0.09, segments = segments.sec},
  13. min = {radius = 0.88, width = 0.10, segments = segments.min},
  14. hour = {radius = 0.77, width = 0.16, segments = segments.hour},
  15. },
  16. colorback = {0.05, 0.05, 0.05},
  17. colorbase = {0.40, 0.15, 0.00, 0.15},
  18. colorfore = {0.80, 0.15, 0.00},
  19. startangle = -HALFPI, clockwise = true, invertangle = false,
  20. }
  21. local scalefactor
  22. local font
  23. local clocktextwidth, datetextwidth
  24. local clocktextheight, datetextheight
  25. local clocktextscale, datetextscale
  26. local padding
  27. local clocktext, datetext = "888888", "88888888"
  28. local time
  29. local padx, pady
  30. local dials, effect
  31. local startangle, endangle, clockwise, invertangle
  32. local rescaletext = function(width)
  33. local fontheight = font:getHeight()
  34. local ctw = font:getWidth("######")
  35. local dtw = font:getWidth("########")
  36. local ratio = ctw / dtw
  37. local factor = width / ctw
  38. padding = factor * conf.padding
  39. clocktextscale = factor
  40. clocktextwidth = clocktextscale * ctw
  41. clocktextheight = clocktextscale * fontheight
  42. datetextscale = ratio * clocktextscale
  43. datetextwidth = datetextscale * dtw
  44. datetextheight = datetextscale * fontheight
  45. end
  46. local generatedial = function(radius, thickness, segments)
  47. local dia = 2 * radius
  48. local base = love.graphics.newCanvas(dia, dia)
  49. love.graphics.setCanvas(base)
  50. love.graphics.setBlendMode('replace')
  51. love.graphics.setColor(1, 1, 1)
  52. love.graphics.circle( "fill", radius, radius, radius, segments * 4 )
  53. love.graphics.setColor(1, 1, 1, 0)
  54. love.graphics.circle( "fill", radius, radius, radius - thickness, segments * 4 )
  55. love.graphics.setLineWidth(conf.linethickness)
  56. local tetha = TWOPI / segments
  57. local x, y, t
  58. for i = 1, segments / 2 do
  59. t = tetha * i
  60. x, y = radius * math.cos(t), radius * math.sin(t)
  61. love.graphics.line(radius - x, radius - y, x + radius, y + radius)
  62. end
  63. love.graphics.setCanvas()
  64. return {base = base, radius = radius}
  65. end
  66. local drawnumbers = function(clocktext, datetext, x, y, width, height)
  67. local textheight = clocktextheight + datetextheight + padding
  68. y = y + (height - textheight) / 2
  69. love.graphics.print(clocktext, x + (width - clocktextwidth) / 2, y , 0, clocktextscale, clocktextscale)
  70. love.graphics.print(datetext, x + (width - datetextwidth) / 2, y + clocktextheight + padding, 0, datetextscale, datetextscale)
  71. end
  72. local generatebase = function(size)
  73. local radius = size / 2
  74. local dials = {}
  75. for k, v in pairs(conf.dials) do
  76. dials[k] = generatedial(radius * v.radius, radius * v.width, v.segments)
  77. dials[k].canvas = love.graphics.newCanvas(size, size)
  78. end
  79. rescaletext(size * conf.clockscale)
  80. local base = love.graphics.newCanvas(size, size)
  81. love.graphics.setCanvas(base)
  82. love.graphics.setBlendMode('alpha')
  83. love.graphics.setColor(1, 1, 1)
  84. drawnumbers('######', '########', 0, 0, size, size) -- there's no character with all segments
  85. drawnumbers('XXXXXX', 'XXXXXXXX', 0, 0, size, size) -- it is #X or 0*
  86. local x
  87. for k, v in pairs(dials) do
  88. x = radius - v.radius
  89. love.graphics.draw(v.base, x, x)
  90. end
  91. love.graphics.setCanvas()
  92. dials.back = {base = base, radius = radius}
  93. return dials
  94. end
  95. local rescale = function(width, height)
  96. local size = conf.canvassize
  97. if width >= height then
  98. scalefactor = height / size
  99. padx, pady = math.floor((width - height) / 2), 0
  100. else
  101. scalefactor = width / size
  102. padx, pady = 0, math.floor((height - width) / 2)
  103. end
  104. rescaletext(scalefactor * size * conf.clockscale)
  105. effect = moonshine(moonshine.effects.glow)
  106. effect.glow.min_luma = 0.2
  107. --effect.glow.strength = 6
  108. end
  109. function love.load()
  110. font = love.graphics.newFont(conf.font.name, conf.font.size)
  111. love.graphics.setFont(font);
  112. local size = conf.canvassize
  113. dials = generatebase(size)
  114. rescale(love.graphics.getDimensions())
  115. love.graphics.setBackgroundColor(conf.colorback)
  116. clockwise, invertangle = conf.clockwise, conf.invertangle
  117. startangle, endangle = conf.startangle, (invertangle and 0 or TWOPI) + conf.startangle
  118. end
  119. local drawTimeArc = function(time, name)
  120. local div = segments[name]
  121. local t = time[name]
  122. local dial = dials[name]
  123. local angle = (invertangle or t ~= 0) and (t * TWOPI) / div or TWOPI
  124. local radius = dials.back.radius
  125. local x = radius - dial.radius
  126. local y = radius - dial.radius
  127. love.graphics.setCanvas(dial.canvas)
  128. local a1, a2
  129. if clockwise then a1, a2 = startangle + angle, endangle
  130. else a1, a2 = startangle, endangle - angle end
  131. love.graphics.clear()
  132. love.graphics.setBlendMode('alpha')
  133. love.graphics.setColor( 1, 1, 1, 1 )
  134. love.graphics.draw(dial.base, x, y)
  135. love.graphics.setColor( 1, 1, 1, 0 )
  136. love.graphics.setBlendMode('multiply', 'premultiplied')
  137. love.graphics.arc("fill", radius, radius, 2 * radius, a1, a2, 4)
  138. love.graphics.setCanvas()
  139. end
  140. local drawstage = function()
  141. local back = dials.back
  142. love.graphics.setBlendMode('alpha')
  143. love.graphics.setColor(conf.colorbase)
  144. love.graphics.draw(back.base, padx, pady, 0, scalefactor, scalefactor)
  145. local w = 2 * back.radius * scalefactor
  146. love.graphics.setColor(conf.colorfore)
  147. drawnumbers(clocktext, datetext, padx, pady, w, w)
  148. for k, v in pairs(segments) do
  149. love.graphics.draw(dials[k].canvas, padx, pady, 0, scalefactor, scalefactor)
  150. end
  151. end
  152. function love.draw()
  153. effect(drawstage)
  154. --love.graphics.setColor( 1, 1, 1, 1 )
  155. --love.graphics.print(love.timer.getFPS(), 10, 10, 0, 0.7, 0.7)
  156. end
  157. local totaldt = 0
  158. function love.update(dt)
  159. love.timer.sleep(0.08)
  160. totaldt = totaldt + dt
  161. if totaldt < 1 then return end
  162. totaldt = totaldt - 1
  163. time = os.date("*t")
  164. clocktext = ("%02i%02i%02i"):format(time.hour, time.min, time.sec)
  165. datetext = ("%04i%02i%02i"):format(time.year, time.month, time.day)
  166. for k, v in pairs(segments) do drawTimeArc(time, k) end
  167. end
  168. function love.resize(width, height)
  169. rescale(width, height)
  170. end
  171. function love.keyreleased(key)
  172. if key == "escape" then
  173. love.event.quit()
  174. end
  175. end