Advertisement
Guest User

Screen

a guest
Feb 21st, 2017
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.08 KB | None | 0 0
  1. --[[
  2.     [Class] Screen
  3.     @version 0.2, 2017-02-20
  4.     @author TheOddByte
  5. --]]
  6.  
  7. local Screen   = {}
  8. Screen.__index = Screen
  9.  
  10.  
  11.  
  12. --[[
  13.     Get the widest character of the font
  14.  
  15.     @param  object font, "The font object"
  16.     @return int   width,   "The width of the widest character"
  17. --]]
  18. local function getWidth( font )
  19.     local width = 0
  20.     for i = 32, 127 do
  21.         local w = font:getWidth( string.char( i ) )
  22.         if w > width then
  23.             width = w
  24.         end
  25.     end
  26.     return width
  27. end
  28.  
  29.  
  30.  
  31. --[[
  32.     Automatically scales a font to fit into the pixelWidth and pixelHeight
  33.     depending on the grid dimensions.
  34.  
  35.     @param string font,     "The path of the font"
  36.     @param int width,       "The width of the grid"
  37.     @param int height,      "The height of the grid"
  38.     @param int pixelWidth,  "The actual width of the virtual screen"
  39.     @param int pixelHeight, "The actual height of the virtual screen"
  40.     @return int scale, int fontWidth, int fontHeight
  41. --]]
  42. local function autoScale( font, width, height, pixelWidth, pixelHeight )
  43.     local scale   = 1
  44.     local Font
  45.     while true do
  46.         Font    = love.graphics.newFont( font, scale );
  47.         local fWidth  = getWidth( Font )
  48.         local fHeight = Font:getHeight()
  49.         local w, h    = fWidth*width, fHeight*height
  50.         if w < pixelWidth and h < pixelHeight then
  51.             scale = scale + 1
  52.         else
  53.             if w > pixelWidth or h > pixelHeight then
  54.                 scale = scale - 1
  55.             end
  56.             break
  57.         end
  58.     end
  59.     local fWidth  = getWidth( Font )
  60.     local fHeight = Font:getHeight()
  61.     return scale, fWidth, fHeight
  62. end
  63.  
  64.  
  65.  
  66. --[[
  67.     Creates a new screen object
  68.  
  69.     @param string font,     "The path of the font"
  70.     @param int width,       "The width of the grid"
  71.     @param int height,      "The height of the grid"
  72.     @param int pixelWidth,  "The actual width of the virtual screen"
  73.     @param int pixelHeight, "The actual height of the virtual screen"
  74.     @return object screen,  "The screen object"
  75. --]]
  76. Screen.new = function( font, x, y, width, height, pixelWidth, pixelHeight )
  77.     local fontsize, fW, fH = autoScale( font, width, height, pixelWidth, pixelHeight )
  78.     local screen = {
  79.         grid       = {};
  80.         background = { 0, 0, 0 };
  81.         rWidth     = pixelWidth;
  82.         rHeight    = pixelHeight;
  83.         width      = width;
  84.         height     = height;
  85.         fontsize   = fontsize;
  86.         fW         = fW;
  87.         fH         = fH;
  88.         x          = x;
  89.         y          = y;
  90.         shader     = "none";
  91.         cursor     = {
  92.             x     = 1;
  93.             y     = 1;
  94.             show  = false;
  95.             blink = false;
  96.             time  = 0;
  97.             rate  = 0.5;
  98.         };
  99.         font_path  = font;
  100.         font       = love.graphics.newFont( font, fontsize );
  101.         background = { 30, 30, 30, 255 };
  102.         foreground = { 255, 255, 255, 255 };
  103.     }
  104.     for x = 1, screen.width do
  105.         screen.grid[x] = {}
  106.         for y = 1, screen.height do
  107.             screen.grid[x][y] = { char = " ", background = screen.background, foreground = screen.foreground }
  108.         end
  109.     end
  110.  
  111.     return setmetatable( screen, Screen )
  112. end
  113.  
  114.  
  115.  
  116. --[[
  117.     Sets the current background color of the screen
  118.  
  119.     @param table color, "The color to set, example { 255, 255, 255, 255 }"
  120. --]]
  121. function Screen:setBackgroundColor( color )
  122.     self.background = color
  123. end
  124.  
  125.  
  126.  
  127. --[[
  128.     Gets the current background color of the screen
  129.  
  130.     @param table color, "The color to set, example { 255, 255, 255, 255 }"
  131. --]]
  132. function Screen:getBackground()
  133.     return self.background
  134. end
  135.  
  136.  
  137.  
  138. --[[
  139.     Sets the current text color of the screen
  140.  
  141.     @param table color, "The color to set, example { 255, 255, 255, 255 }"
  142. --]]
  143. function Screen:setTextColor( color )
  144.     self.foreground = color
  145. end
  146.  
  147.  
  148.  
  149. --[[
  150.     Gets the current text color of the screen
  151.  
  152.     @param table color, "The color to set, example { 255, 255, 255, 255 }"
  153. --]]
  154. function Screen:getTextColor()
  155.     return self.foreground
  156. end
  157.  
  158.  
  159.  
  160. --[[
  161.     Sets the grid dimension
  162.  
  163.     @param int width,  "The width of the grid"
  164.     @param int height, "The height of the grid"
  165. --]]
  166. function Screen:setResolution( width, height )
  167.     local size, fW, fH = autoScale( self.font_path, width, height, self.rHeight, self.rWidth )
  168.     self.font = love.graphics.newFont( self.font_path, size )
  169.     self.fW   = fW
  170.     self.fH   = fH
  171. end
  172.  
  173.  
  174.  
  175. --[[
  176.     Gets the grid dimension
  177.  
  178.     @return int width, int height
  179. --]]
  180. function Screen:getResolution()
  181.     return self.width, self.height
  182. end
  183.  
  184.  
  185.  
  186. --[[
  187.     Update the screen to match the new width and height
  188.  
  189.     @param int width,  "The new width in pixels"
  190.     @param int height, "The new height in pixels"
  191. --]]
  192. function Screen:refresh( width, height )
  193.     self.rWidth  = width
  194.     self.rHeight = height
  195.  
  196.     local size, fW, fH = autoScale( self.font_path, self.width, self.height, self.rHeight, self.rWidth )
  197.     self.font = love.graphics.newFont( self.font_path, size )
  198.     self.fW   = fW
  199.     self.fH   = fH
  200. end
  201.  
  202.  
  203. function Screen:setShader( shader )
  204.     shader      = type( shader ) == "string" and shader or "none"
  205.     self.shader = shader
  206. end
  207.  
  208.  
  209.  
  210. --[[
  211.     Sets the font to use
  212.  
  213.     @param string font_path, "The path of the font to set"
  214. --]]
  215. function Screen:setFont( font_path )
  216.     self.font_path = font_path
  217.     local size, fW, fH = autoScale( self.font_path, self.width, self.height, self.rHeight, self.rWidth )
  218.     self.font = love.graphics.newFont( self.font_path, size )
  219.     self.fW   = fW
  220.     self.fH   = fH
  221. end
  222.  
  223.  
  224.  
  225. --[[
  226.     Gets the current font the screen is using
  227. --]]
  228. function Screen:getFont()
  229.     return self.font
  230. end
  231.  
  232.  
  233.  
  234. --[[
  235.     Sets cursor blink to be enabled or disabled
  236.  
  237.     @param boolean bool, "Whether or not cursor blink is enabled"
  238. --]]
  239. function Screen:setBlink( bool )
  240.     self.cursor.blink = type( bool ) == "boolean" and bool or self.cursor.blink
  241.     self.cursor.show  = not self.cursor.blink and false or self.cursor.show
  242. end
  243.  
  244.  
  245. --[[
  246.     Gets whether or no cursor blink is enabled
  247.  
  248.     @return boolean blink, "The state of cursor blink"
  249. --]]
  250. function Screen:getBlink()
  251.     return self.cursor.blink
  252. end
  253.  
  254.  
  255.  
  256. --[[
  257.     Writes at the specified position on the screen
  258.  
  259.     @param string text, "The text to write"
  260.     @param int x,       "The x position"
  261.     @param int y,       "The y position"
  262. --]]
  263. function Screen:writeAt( text, x, y )
  264.     self.cursor.y = y
  265.     self.cursor.x = x
  266.     for i = 1, #text do
  267.         if x <= self.width and y <= self.height then
  268.             self.grid[x + (i-1)][y] = { char = text:sub( i, i ), background = self.background, foreground = self.foreground }
  269.             self.cursor.x = self.cursor.x + 1
  270.         end
  271.     end
  272. end
  273.  
  274.  
  275. --[[
  276.     Writes text at the current cursor position
  277.  
  278.     @param string text, "The text to write"
  279. --]]
  280. function Screen:write( text )
  281.     self:writeAt( text, self.cursor.x, self.cursor.y )
  282. end
  283.  
  284.  
  285.  
  286. --[[
  287.     Centers text on the screen at the give y position
  288.  
  289.     @param string text, "The text to write"
  290.     @param int y,       "The y position to write at"
  291. --]]
  292. function Screen:center( text, y )
  293.     self:writeAt( text, math.ceil( (self.width-#text)/2 ), y )
  294. end
  295.  
  296.  
  297. function Screen:midpoint( text, x1, x2, y )
  298.     self:writeAt( text, math.ceil( ((x1 + x2)-#text)/2 ), y )
  299. end
  300.  
  301.  
  302. --[[
  303.     Converts a grid position to the real position on the screen
  304.  
  305.     @param int x, "The x position in the grid"
  306.     @param int y, "The y position in the grid"
  307. --]]
  308. function Screen:getRealPos( x, y )
  309.     return self.x + ( (x-1)*self.fW ), self.y + ( (y-1)*self.fH )
  310. end
  311.  
  312.  
  313.  
  314. --[[
  315.     Converts a real position to a grid position
  316.  
  317.     @param int x, "The x position"
  318.     @param int y, "The y position"
  319. --]]
  320. function Screen:getGridPos( x, y )
  321.     --# Loop and check every grid position
  322.     for gX = 1, self.width do
  323.         for gY = 1, self.height do
  324.             local _x, _y = self:getRealPos( gX, gY )
  325.             if x >= _x and x <= _x + self.fW and y >= _y and y <= _y + self.fH then
  326.                 return gX, gY
  327.             end
  328.         end
  329.     end
  330. end
  331.  
  332.  
  333.  
  334. --[[
  335.     Clears the screen
  336. --]]
  337. function Screen:clear()
  338.     for x = 1, self.width do
  339.         self.grid[x] = {}
  340.         for y = 1, self.height do
  341.             self.grid[x][y] = { char = " ", background = self.background, foreground = self.foreground }
  342.         end
  343.     end
  344. end
  345.  
  346.  
  347.  
  348. --[[
  349.     Clears a line on the screen, either the current cursor position
  350.     or the given line
  351.  
  352.     @param int line, "The line to clear, this one is optional"
  353. --]]
  354. function Screen:clearLine( line )
  355.     for x = 1, self.width do
  356.         self.screen[x][self.y] = { char = " ", background = self.background, foreground = self.foreground }
  357.     end
  358. end
  359.  
  360.  
  361.  
  362. --[[
  363.     Renders the screen to the screen.
  364. --]]
  365. function Screen:render()
  366.  
  367.  
  368.  
  369.     shaders:set( 1, self.shader )
  370.     shaders:predraw()
  371.  
  372.     love.graphics.setFont( self.font )
  373.     for x = 1, #self.grid do
  374.         for y = 1, #self.grid[x] do
  375.             local t = self.grid[x][y]
  376.             local rX, rY = self:getRealPos( x, y )
  377.             love.graphics.setColor( unpack( t.background ) )
  378.             love.graphics.rectangle("fill", rX, rY, self.fW, self.fH)
  379.             love.graphics.setColor( unpack( t.foreground ) )
  380.             love.graphics.print( t.char, rX, rY )
  381.         end
  382.     end
  383.  
  384.     --# Draw the cursor( if it's enabled )
  385.     if self.cursor.blink and self.cursor.show then
  386.         love.graphics.setColor(255, 255, 255, 255)
  387.         local rX, rY = self:getRealPos( self.cursor.x, self.cursor.y )
  388.         love.graphics.setColor( {255,255,255,255} )
  389.         love.graphics.rectangle( "fill", rX, rY, self.fW, self.fH )
  390.     end
  391.  
  392.     shaders:postdraw()
  393.     shaders:set( 1, "none" )
  394.  
  395. end
  396.  
  397.  
  398. function Screen:update( dt )
  399.     if self.cursor.blink then
  400.         self.cursor.time = self.cursor.time + dt
  401.         if self.cursor.time >= self.cursor.rate then
  402.             self.cursor.time = 0;
  403.             self.cursor.show = not self.cursor.show
  404.         end
  405.     end
  406. end
  407.  
  408. return Screen
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement