Last active
September 16, 2021 06:04
-
-
Save Skaruts/736521d9cb6d136cfb6c8aedbb9602a5 to your computer and use it in GitHub Desktop.
A terminal emulator console in love2d, which renders using spritebatches
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- import() is a custom made relative-require function | |
local Class = import("lib/middleclass/middleclass", ...) | |
local ClassProperties = import("lib/middleclass/class_properties", ...) | |
local BaseConsole = import("console_base", ...) | |
local palette = import("palette", ...) | |
local db = import("database", ...) | |
local ml = import("main_loop", ...) | |
local vec = import("lib/vec2", ...) | |
-- extends BaseConsole | |
local BatchConsole = Class('BatchConsole', BaseConsole):include(ClassProperties) | |
function BatchConsole:initialize(x, y, w, h, tileset, clear_char, clear_fg, clear_bg) | |
BaseConsole.initialize(self, "root", x, y, w, h, clear_char, clear_fg, clear_bg) | |
self._tileset = tileset | |
self._quads = {} | |
self._fg_spritebatch = nil | |
self._bg_spritebatch = nil | |
self._old_chars = {} | |
self._old_fgs = {} | |
self._old_bgs = {} | |
self:_init_cells() | |
self:_init_quads() | |
self:_init_spritebatch() | |
end | |
function BatchConsole:_init_cells() | |
for i=0, (self.w*self.h)-1 do | |
self._old_chars[i] = true -- just reserve memory for now | |
self._old_fgs[i] = true | |
self._old_bgs[i] = true | |
-- these are all from BaseConsole | |
self._chars[i] = self._clear_char -- text chars | |
self._fgs[i] = self._clear_fg -- foreground color (text) | |
self._bgs[i] = self._clear_bg -- background color (around the text) | |
end | |
end | |
-- take each character in a font set (i.e. cp437 ascii image), and create a | |
-- quad that encompasses it's position and size in the tileset (in pixels) | |
function BatchConsole:_init_quads() | |
local idx = 0 | |
for j=0, self._tileset.rows-1 do | |
for i=0, self._tileset.cols-1 do | |
self._quads[idx] = love.graphics.newQuad( | |
i*self._tileset.cw, j*self._tileset.ch, | |
self._tileset.cw, self._tileset.ch, -- tileset's cell width/height | |
self._tileset.w, self._tileset.h -- tileset's image width/height | |
) | |
idx = idx + 1 | |
end | |
end | |
end | |
function BatchConsole:_init_spritebatch() | |
-- self.w/h is in cells, not in pixels | |
self._fg_spritebatch = love.graphics.newSpriteBatch(self._tileset.image, self.w*self.h) | |
self._bg_spritebatch = love.graphics.newSpriteBatch(self._tileset.image, self.w*self.h) | |
local idx = 0 | |
for j=0, self.h-1 do | |
for i=0, self.w-1 do | |
self._fg_spritebatch:setColor( self._fgs[idx] ) | |
self._fg_spritebatch:add( self._quads[self._chars[idx]], i*self._tileset.cw, j*self._tileset.ch ) | |
self._bg_spritebatch:setColor( self._bgs[idx] ) | |
self._bg_spritebatch:add( self._quads[self._chars[self._tileset.bg_char]], i*self._tileset.cw, j*self._tileset.ch ) | |
idx = idx + 1 | |
end | |
end | |
end | |
function BatchConsole:render() | |
local chars, fgs, bgs = self._chars, self._fgs, self._bgs | |
local ochars, ofgs, obgs = self._old_chars, self._old_fgs, self._old_bgs | |
local CW, CH, bg_char = self._tileset.cw, self._tileset.ch, self._tileset.bg_char | |
-- check what has changed since last frame and apply to spritebatches | |
local idx = -1 | |
local char, fg, bg, ochar, ofg, obg, qx, qy | |
for j=0, self.h-1 do | |
qy = j*CH -- quad y | |
for i=0, self.w-1 do | |
idx = idx + 1 | |
qx = i*CW -- quad x | |
char, fg, bg = chars[idx], fgs[idx], bgs[idx] | |
if bg ~= obgs[idx] then | |
self._bg_spritebatch:setColor(bg) | |
self._bg_spritebatch:set(idx+1, self._quads[bg_char], qx, qy) | |
obgs[idx] = bg | |
end | |
if char ~= ochars[idx] or fg ~= ofgs[idx] then | |
self._fg_spritebatch:setColor(fg) | |
self._fg_spritebatch:set(idx+1, self._quads[char], qx, qy) | |
ochars[idx] = char | |
ofgs[idx] = fg | |
end | |
end | |
end | |
-- render spritebatches | |
love.graphics.setColor( palette.WHITE ) | |
love.graphics.draw( self._bg_spritebatch, self.x*CW, self.y*CH ) | |
love.graphics.draw( self._fg_spritebatch, self.x*CW, self.y*CH ) | |
end | |
--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=-- | |
-- getters / setters (made possible with ClassProperties) | |
--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=-- | |
function BatchConsole:_get_global_x_() return self.x end | |
function BatchConsole:_get_global_y_() return self.y end | |
function BatchConsole:_get_global_pos_() return vec(self.x, self.y) end | |
function BatchConsole:_set_tileset_(ts) | |
if ts ~= self._tileset then | |
local old_ts = self._tileset | |
self._tileset = ts | |
if ts.cw ~= old_ts.cw or ts.ch ~= old_ts.ch then | |
self:_init_quads() | |
if self == db.main_console then | |
ml.set_window(self.w*ts.cw, self.h*ts.ch) | |
end | |
end | |
self._fg_spritebatch:setTexture(self._tileset.image) | |
self._bg_spritebatch:setTexture(self._tileset.image) | |
for j = 0, self.h-1 do | |
for i = 0, self.w-1 do | |
local idx = i+j*self.w | |
self._old_chars[idx] = true | |
self._old_fgs[idx] = true | |
self._old_bgs[idx] = true | |
end | |
end | |
end | |
end | |
function BatchConsole:_get_tileset_() | |
return self._tileset | |
end | |
-- TODO: account for zoom/scale | |
function BatchConsole:_get_global_mouse_pos_() | |
-- (vecf(self._mouse_pos-self.rpos)/self.scale) / self.cs | |
-- return vec( math.floor((self._mouse_pos.x / self.scale.x) / self._tileset.cw), | |
-- math.floor((self._mouse_pos.y / self.scale.y) / self._tileset.ch) ) | |
return vec(self._mouse_pos.x / self._tileset.cw, self._mouse_pos.y / self._tileset.ch):floored() | |
end | |
-- local floor = math.floor | |
function BatchConsole:_get_mouse_pos_() | |
-- return vec( float((self._mouse_pos.x - (self.x*self.cw)) / self.scale.x) // self.cw, | |
-- float((self._mouse_pos.y - (self.y*self.ch)) / self.scale.y) // self.ch ) | |
return vec( (self._mouse_pos.x - (self.x * self._tileset.cw)) / self._tileset.cw, | |
(self._mouse_pos.y - (self.y * self._tileset.ch)) / self._tileset.ch ):floored() | |
end | |
function BatchConsole:_set_mouse_pos_(mp) | |
self._mouse_pos = mp | |
end | |
return BatchConsole |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment