Advertisement
Snusmumriken

love2d virtual display for ascii graphics

Nov 12th, 2018
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.60 KB | None | 0 0
  1. --[=[
  2. Example font image: https://vk.com/doc75175715_480892724
  3. Charset for this image:
  4. local charset = table.concat{
  5.     [[ ☺☻♥♦♣♠•◘○◙♂♀♪♫☼]],
  6.     [[►◄↕‼¶§▬↨↑↓→←∟↔▲▼]],
  7.     [[ !"#$%&'()*+,-./]],
  8.     [[0123456789:;<=>?]],
  9.     [[@ABCDEFGHIJKLMNO]],
  10.     [[PQRSTUVWXYZ[\]^_]],
  11.     [[`abcdefghijklmno]],
  12.     [[pqrstuvwxyz{|}~⌂]],
  13.     [[ÇüéâäàåçêëèïîìÄÅ]],
  14.     [[ÉæÆôöòûùÿÖÜ¢£¥₧ƒ]],
  15.     [[áíóúñѪº¿⌐¬½¼¡«»]],
  16.     [[░▒▓│┤╡╢╖╕╣║╗╝╜╛┐]],
  17.     [[└┴┬├─┼╞╟╚╔╩╦╠═╬╧]],
  18.     [[╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀]],
  19.     [[αßΓπΣσµτΦΘΩδ∞φε∩]],
  20.     [[≡±≥≤⌠⌡÷≈°∙·√ⁿ²■⯑]]
  21. }
  22.  
  23. example for this img:
  24.  
  25.  
  26. local d = display:new('image.png', 16, 16, charset)
  27.  
  28. ]=]
  29.  
  30.  
  31. local utf8  = require'utf8'
  32. local display = {}
  33. display._white = {1, 1, 1, 1}
  34. display.__index = display
  35.  
  36. function display:new(image, w, h, sym, def)
  37.     local gr   = love.graphics
  38.    
  39.     self       = setmetatable({}, self)
  40.     self.map   = {}
  41.     self.image = gr.newImage(image)
  42.     self.layers  = {}
  43.     self.layer = nil -- corrent layer
  44.    
  45.     self.image:setFilter('nearest')
  46.    
  47.     local iw, ih = self.image:getDimensions()
  48.     self.w     = iw/w
  49.     self.h     = ih/h
  50.    
  51.     local symw   = iw/self.w
  52.    
  53.     local i = 0
  54.     for p, c in utf8.codes(sym) do
  55.         local char = utf8.char(c)
  56.         local x, y = i%symw, math.floor(i/symw)
  57.         x, y = x * self.w, y * self.h
  58.         local quad = gr.newQuad(x, y, self.w, self.h, iw, ih)
  59.         self.map[char] = quad
  60.         self.map[i]    = quad
  61.         i = i + 1
  62.     end
  63.    
  64.     self._s = assert(self:get(def or ' '))
  65.     self._b = assert(self:get(def or ' '))
  66.    
  67.     self._scolor = self._white
  68.     self._bcolor = self._white
  69.    
  70.     self:setLayer(1)
  71.     return self
  72. end
  73.  
  74. function display:get(sym)
  75.     return self.map[sym]
  76. end
  77.  
  78. function display:getImage()
  79.     return self.image
  80. end
  81.  
  82. function display:setLayer(i)
  83.     local l = self.layers[i]
  84.     if not l then
  85.         l = {}
  86.         l.batch = love.graphics.newSpriteBatch(self.image)
  87.         l.used  = {}
  88.         self.layers[i] = l
  89.     end
  90.     self.layer = l
  91. end
  92.  
  93. function display:setColor(color, ...)
  94.     if type(color) == 'table' then
  95.         self._scolor = color
  96.         return
  97.     end
  98.     if type(color) == 'number' then
  99.         self._scolor = {color, ...}
  100.         return
  101.     end
  102.     self._scolor = self._white
  103. end
  104.  
  105. function display:setBackground(sym)
  106.     self._b = assert(self:get(sym))
  107. end
  108.  
  109. function display:setBackgroundColor(color, ...)
  110.     if type(color) == 'table' then
  111.         print('SET BCOLOR')
  112.         self._bcolor = color
  113.         return
  114.     end
  115.     if type(color) == 'number' then
  116.         self._bcolor = {color, ...}
  117.         return
  118.     end
  119.     self._bcolor = self._white
  120. end
  121.  
  122. function display:draw(...)
  123.     for i, v in pairs(self.layers) do
  124.         love.graphics.draw(v.batch, ...)
  125.     end
  126. end
  127.  
  128. display.__call = display.get
  129.  
  130. function display:_batch_get(x, y)
  131.     local layer = self.layer
  132.     if not layer.used[y] then
  133.         layer.used[y] = {}
  134.     end
  135.     if not layer.used[y][x] then
  136.         -- background, tile
  137.         layer.batch:setColor(self._bcolor)
  138.         local sym  = layer.batch:add(self._b, x * self.w, y * self.h)
  139.         layer.batch:setColor(self._scolor)
  140.         local bcgr = layer.batch:add(self._s, x * self.w, y * self.h)
  141.         layer.used[y][x] = {sym, bcgr}
  142.     end
  143.    
  144.     return layer.used[y][x]
  145. end
  146.  
  147. function display:_batch_set(quad, x, y, backgr, color)
  148.     local layer = self.layer
  149.     local tile = self:_batch_get(x, y)
  150.    
  151.     local index = backgr and tile[1] or tile[2]
  152.     local color = color or backgr and self._bcolor or self._scolor
  153.  
  154.     layer.batch:setColor(color)
  155.     layer.batch:set(index, quad, x * self.w, y * self.h)
  156. end
  157.  
  158. function display:_clear_area(x, y, w, h, color)
  159.     local layer = self.layer
  160.     for i = x, x + w - 1 do
  161.         for j = y, y + h - 1 do
  162.             local tile = self:_batch_get(i, j)
  163.             layer.batch:setColor(color or self._scolor)
  164.             layer.batch:set(tile[1], self._b, i * self.w, j * self.h)
  165.             layer.batch:setColor(color or self._bcolor)
  166.             layer.batch:set(tile[2], self._s, i * self.w, j * self.h)
  167.         end
  168.     end
  169. end
  170.  
  171. function display:print(str, px, py)
  172.     assert(px, 'arg#1 x pos expected')
  173.     assert(py, 'arg#2 y pos expected')
  174.    
  175.     local x, y = 0, 0
  176.     local bit = 4
  177.     for p, c in utf8.codes(str) do
  178.         c = utf8.char(c)
  179.         if c == '\n' then
  180.             x = 0
  181.             y = y + 1
  182.         else
  183.             local cx = (x + px)
  184.             local cy = (y + py)
  185.             local q  = self.map[c] or self.map[#self.map - 1]
  186.             self:_batch_set(q, cx, cy)
  187.             x = x + 1
  188.         end
  189.     end
  190. end
  191.  
  192. function display:clearAll()
  193.     for i, v in self.layers do
  194.         v.batch:clear()
  195.         v.used = {}
  196.     end
  197. end
  198.  
  199. function display:clearLayer(i)
  200.     local l = self.layers[i] or self.layer
  201.     if l then
  202.         l.batch:clear()
  203.         l.used = {}
  204.     end
  205. end
  206.  
  207. return display
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement