mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-13 23:26:07 +09:00
improved terminal drawing performance, and I BROKE COLOUR FILTER
Former-commit-id: ea137e0f9bc94d7c4f246ce45e7570877e4cc534 Former-commit-id: 3f66e2f12e3c42262adbc00f04a6ee9d76c0a49c
This commit is contained in:
@@ -1,13 +1,16 @@
|
|||||||
package net.torvald.aa
|
package net.torvald.aa
|
||||||
|
|
||||||
import net.torvald.terrarum.gameworld.toUint
|
import net.torvald.terrarum.gameworld.toUint
|
||||||
|
import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal
|
||||||
import org.newdawn.slick.*
|
import org.newdawn.slick.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param terminal: for sending redraw only
|
||||||
|
*
|
||||||
* Created by minjaesong on 16-08-10.
|
* Created by minjaesong on 16-08-10.
|
||||||
*/
|
*/
|
||||||
class AAFrame @Throws(SlickException::class)
|
class AAFrame @Throws(SlickException::class)
|
||||||
constructor(var width: Int, var height: Int) {
|
constructor(var width: Int, var height: Int, var terminal: SimpleTextTerminal) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0000_0000_00000000
|
* 0000_0000_00000000
|
||||||
@@ -30,6 +33,8 @@ constructor(var width: Int, var height: Int) {
|
|||||||
if (y * width + x >= frameBuffer.size || y * width + x < 0)
|
if (y * width + x >= frameBuffer.size || y * width + x < 0)
|
||||||
throw ArrayIndexOutOfBoundsException("x: $x, y; $y")
|
throw ArrayIndexOutOfBoundsException("x: $x, y; $y")
|
||||||
frameBuffer[y * width + x] = ((c.toInt().and(0xFF)) + colourKey.shl(8)).toChar()
|
frameBuffer[y * width + x] = ((c.toInt().and(0xFF)) + colourKey.shl(8)).toChar()
|
||||||
|
|
||||||
|
terminal.redraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun drawBuffer(x: Int, y: Int, raw: Char): Boolean =
|
fun drawBuffer(x: Int, y: Int, raw: Char): Boolean =
|
||||||
@@ -37,6 +42,7 @@ constructor(var width: Int, var height: Int) {
|
|||||||
false
|
false
|
||||||
else {
|
else {
|
||||||
frameBuffer[y * width + x] = raw
|
frameBuffer[y * width + x] = raw
|
||||||
|
terminal.redraw()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +51,7 @@ constructor(var width: Int, var height: Int) {
|
|||||||
val char = (other[i].toUint().shl(8) + other[i + 1].toUint()).toChar()
|
val char = (other[i].toUint().shl(8) + other[i + 1].toUint()).toChar()
|
||||||
frameBuffer[i.ushr(1)] = char
|
frameBuffer[i.ushr(1)] = char
|
||||||
}
|
}
|
||||||
|
terminal.redraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBackgroundColour(x: Int, y: Int): Int {
|
fun getBackgroundColour(x: Int, y: Int): Int {
|
||||||
@@ -71,6 +78,7 @@ constructor(var width: Int, var height: Int) {
|
|||||||
drawBuffer(x, y, 0.toChar(), background.shl(4))
|
drawBuffer(x, y, 0.toChar(), background.shl(4))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
terminal.redraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun drawFromOther(other: AAFrame) {
|
fun drawFromOther(other: AAFrame) {
|
||||||
@@ -80,6 +88,7 @@ constructor(var width: Int, var height: Int) {
|
|||||||
frameBuffer[y * width + x] = other.getRaw(x, y)!!
|
frameBuffer[y * width + x] = other.getRaw(x, y)!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
terminal.redraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkOOB(x: Int, y: Int) = (x < 0 || y < 0 || x >= width || y >= height)
|
private fun checkOOB(x: Int, y: Int) = (x < 0 || y < 0 || x >= width || y >= height)
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ class StateVTTest : BasicGameState() {
|
|||||||
|
|
||||||
// HiRes: 100x64, LoRes: 80x25
|
// HiRes: 100x64, LoRes: 80x25
|
||||||
val computerInside = BaseTerrarumComputer(8)
|
val computerInside = BaseTerrarumComputer(8)
|
||||||
val vt = SimpleTextTerminal(SimpleTextTerminal.AMETHYST_NOVELTY, 80, 25,
|
val vt = SimpleTextTerminal(SimpleTextTerminal.WHITE, 80, 25,
|
||||||
computerInside, colour = true, hires = false)
|
computerInside, colour = false, hires = false)
|
||||||
|
|
||||||
|
|
||||||
val vtUI = Image(vt.displayW, vt.displayH)
|
val vtUI = Image(vt.displayW, vt.displayH)
|
||||||
@@ -47,14 +47,40 @@ class StateVTTest : BasicGameState() {
|
|||||||
|
|
||||||
private val paperColour = Color(0xfffce6)
|
private val paperColour = Color(0xfffce6)
|
||||||
|
|
||||||
|
val vtUIrenderX = Terrarum.WIDTH.minus(vtUI.width).div(2f)
|
||||||
|
val vtUIrenderY = Terrarum.HEIGHT.minus(vtUI.height).div(2f)
|
||||||
|
|
||||||
override fun render(container: GameContainer, game: StateBasedGame, g: Graphics) {
|
override fun render(container: GameContainer, game: StateBasedGame, g: Graphics) {
|
||||||
vt.render(container, vtUI.graphics)
|
vt.render(container, vtUI.graphics)
|
||||||
|
|
||||||
g.drawImage(vtUI,
|
|
||||||
Terrarum.WIDTH.minus(vtUI.width).div(2f),
|
|
||||||
Terrarum.HEIGHT.minus(vtUI.height).div(2f))
|
|
||||||
|
|
||||||
vtUI.graphics.flush()
|
blendNormal()
|
||||||
|
g.drawImage(vtUI, vtUIrenderX, vtUIrenderY)
|
||||||
|
|
||||||
|
|
||||||
|
// cursor
|
||||||
|
if (vt.cursorBlinkOn) {
|
||||||
|
g.color = vt.getColor(if (vt.cursorBlink) vt.foreDefault else vt.backDefault)
|
||||||
|
|
||||||
|
g.fillRect(
|
||||||
|
vt.fontW * vt.cursorX.toFloat() + vt.borderSize + vtUIrenderX,
|
||||||
|
vt.fontH * vt.cursorY.toFloat() + vt.borderSize + vtUIrenderY,
|
||||||
|
vt.fontW.toFloat(),
|
||||||
|
vt.fontH.toFloat()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// not-pure-black screen
|
||||||
|
/*g.color = vt.colourScreen
|
||||||
|
blendScreen()
|
||||||
|
g.fillRect(vtUIrenderX, vtUIrenderY, vt.displayW.toFloat(), vt.displayH.toFloat())
|
||||||
|
|
||||||
|
|
||||||
|
// colour overlay
|
||||||
|
g.color = vt.phosphor
|
||||||
|
blendMul()
|
||||||
|
g.fillRect(vtUIrenderX, vtUIrenderY, vt.displayW.toFloat(), vt.displayH.toFloat())*/
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun keyPressed(key: Int, c: Char) {
|
override fun keyPressed(key: Int, c: Char) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ _G._TERRARUM = true -- for multi-env programs
|
|||||||
|
|
||||||
-- global functions
|
-- global functions
|
||||||
_G.runscript = function(s, src, ...)
|
_G.runscript = function(s, src, ...)
|
||||||
if s:byte(1) == 27 then error("Bytecode execution is prohibited.") end -- untested; it's Lua 5.1 code and we're 5.2
|
if s:byte(1) == 0x1b then error("Bytecode execution is prohibited.") end -- exact MAGIC is 0x1b 'L' 'u' 'a'
|
||||||
|
|
||||||
local code, reason = load(s, src)
|
local code, reason = load(s, src)
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,10 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
|
|||||||
|
|
||||||
val table = LuaTable()
|
val table = LuaTable()
|
||||||
val file = File(computer.getRealPath(path)).absoluteFile
|
val file = File(computer.getRealPath(path)).absoluteFile
|
||||||
file.list().forEachIndexed { i, s -> table.insert(i, LuaValue.valueOf(s)) }
|
try {
|
||||||
|
file.list().forEachIndexed { i, s -> table.insert(i, LuaValue.valueOf(s)) }
|
||||||
|
}
|
||||||
|
catch (e: NullPointerException) {}
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,15 +62,15 @@ open class SimpleTextTerminal(
|
|||||||
) // THESE ARE THE STANDARD
|
) // THESE ARE THE STANDARD
|
||||||
|
|
||||||
val phosphor = if (colour) WHITE7500 else phosphorColour
|
val phosphor = if (colour) WHITE7500 else phosphorColour
|
||||||
open protected val colourScreen = if (colour) Color(8, 8, 8) else Color(19, 19, 19)
|
open val colourScreen = if (colour) Color(8, 8, 8) else Color(19, 19, 19)
|
||||||
|
|
||||||
override val coloursCount: Int
|
override val coloursCount: Int
|
||||||
get() = colours.size
|
get() = colours.size
|
||||||
|
|
||||||
val errorColour = if (coloursCount > 4) 6 else 1
|
val errorColour = if (coloursCount > 4) 6 else 1
|
||||||
|
|
||||||
open protected val backDefault = 0 // STANDARD
|
open val backDefault = 0 // STANDARD
|
||||||
open protected val foreDefault = 3 // STANDARD
|
open val foreDefault = 3 // STANDARD
|
||||||
|
|
||||||
override var backColour = backDefault
|
override var backColour = backDefault
|
||||||
override var foreColour = foreDefault
|
override var foreColour = foreDefault
|
||||||
@@ -81,7 +81,7 @@ open class SimpleTextTerminal(
|
|||||||
override var cursorY = 0
|
override var cursorY = 0
|
||||||
override var cursorBlink = true
|
override var cursorBlink = true
|
||||||
|
|
||||||
val screenBuffer = AAFrame(width, height)
|
val screenBuffer = AAFrame(width, height, this)
|
||||||
|
|
||||||
open protected val fontRef =
|
open protected val fontRef =
|
||||||
"./assets/graphics/fonts/${
|
"./assets/graphics/fonts/${
|
||||||
@@ -90,11 +90,11 @@ open class SimpleTextTerminal(
|
|||||||
else "milkymda.png"
|
else "milkymda.png"
|
||||||
}"
|
}"
|
||||||
open protected val fontImg = Image(fontRef)
|
open protected val fontImg = Image(fontRef)
|
||||||
open protected val fontW = fontImg.width / 16
|
open val fontW = fontImg.width / 16
|
||||||
open protected val fontH = fontImg.height / 16
|
open val fontH = fontImg.height / 16
|
||||||
open protected val font = ColouredFastFont(this, fontRef, fontW, fontH)
|
open protected val font = ColouredFastFont(this, fontRef, fontW, fontH)
|
||||||
|
|
||||||
private val borderSize = 20
|
val borderSize = 20
|
||||||
override val displayW = fontW * width + 2 * borderSize
|
override val displayW = fontW * width + 2 * borderSize
|
||||||
override val displayH = fontH * height + 2 * borderSize
|
override val displayH = fontH * height + 2 * borderSize
|
||||||
|
|
||||||
@@ -103,9 +103,12 @@ open class SimpleTextTerminal(
|
|||||||
|
|
||||||
private var cursorBlinkTimer = 0
|
private var cursorBlinkTimer = 0
|
||||||
private val cursorBlinkLen = 250
|
private val cursorBlinkLen = 250
|
||||||
private var cursorBlinkOn = true
|
var cursorBlinkOn = true
|
||||||
|
private set
|
||||||
|
|
||||||
|
|
||||||
|
private var redrawSemaphore = false
|
||||||
|
|
||||||
|
|
||||||
override fun getColor(index: Int): Color = colours[index]
|
override fun getColor(index: Int): Color = colours[index]
|
||||||
|
|
||||||
@@ -140,63 +143,65 @@ open class SimpleTextTerminal(
|
|||||||
* pass UIcanvas to the parameter "g"
|
* pass UIcanvas to the parameter "g"
|
||||||
*/
|
*/
|
||||||
override fun render(gc: GameContainer, g: Graphics) {
|
override fun render(gc: GameContainer, g: Graphics) {
|
||||||
|
// FIXME don't redraw every time it's slow
|
||||||
g.font = font
|
g.font = font
|
||||||
|
|
||||||
blendNormal()
|
|
||||||
|
|
||||||
// black background (this is mandatory)
|
// don't redraw() every fucking time, you're wasting your precious process cycle
|
||||||
g.color = Color.black
|
if (redrawSemaphore) {
|
||||||
g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat())
|
|
||||||
|
blendNormal()
|
||||||
|
|
||||||
|
// black background (this is mandatory)
|
||||||
|
g.color = Color.black
|
||||||
|
g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat())
|
||||||
|
|
||||||
|
|
||||||
// screen buffer
|
// screen buffer
|
||||||
for (y in 0..height - 1) {
|
for (y in 0..height - 1) {
|
||||||
for (x in 0..width - 1) {
|
for (x in 0..width - 1) {
|
||||||
val ch = screenBuffer.getChar(x, y)
|
val ch = screenBuffer.getChar(x, y)
|
||||||
|
|
||||||
// background
|
// background
|
||||||
g.color = getColor(screenBuffer.getBackgroundColour(x, y))
|
g.color = getColor(screenBuffer.getBackgroundColour(x, y))
|
||||||
g.fillRect(fontW * x.toFloat() + borderSize, fontH * y.toFloat() + borderSize,
|
g.fillRect(fontW * x.toFloat() + borderSize, fontH * y.toFloat() + borderSize,
|
||||||
fontW.toFloat(), fontH.toFloat())
|
fontW.toFloat(), fontH.toFloat())
|
||||||
|
|
||||||
// foreground
|
// foreground
|
||||||
if (ch.toInt() != 0 && ch.toInt() != 32) {
|
if (ch.toInt() != 0 && ch.toInt() != 32) {
|
||||||
g.color = getColor(screenBuffer.getForegroundColour(x, y))
|
g.color = getColor(screenBuffer.getForegroundColour(x, y))
|
||||||
g.drawString(
|
g.drawString(
|
||||||
Character.toString(ch),
|
Character.toString(ch),
|
||||||
fontW * x.toFloat() + borderSize, fontH * y.toFloat() + borderSize)
|
fontW * x.toFloat() + borderSize, fontH * y.toFloat() + borderSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redrawSemaphore = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// cursor
|
// cursor
|
||||||
g.color = getColor(foreDefault)
|
/*if (cursorBlinkOn) {
|
||||||
if (cursorBlinkOn && cursorBlink)
|
g.color = getColor(if (cursorBlink) foreDefault else backDefault)
|
||||||
|
|
||||||
g.fillRect(
|
g.fillRect(
|
||||||
fontW * cursorX.toFloat() + borderSize,
|
fontW * cursorX.toFloat() + borderSize,
|
||||||
fontH * cursorY.toFloat() + borderSize,
|
fontH * cursorY.toFloat() + borderSize,
|
||||||
fontW.toFloat(),
|
fontW.toFloat(),
|
||||||
fontH.toFloat()
|
fontH.toFloat()
|
||||||
)
|
)
|
||||||
|
}*/
|
||||||
|
|
||||||
// not-pure-black screen
|
|
||||||
g.color = colourScreen
|
|
||||||
blendScreen()
|
|
||||||
g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat())
|
|
||||||
|
|
||||||
|
|
||||||
// colour overlay
|
|
||||||
g.color = phosphor
|
|
||||||
blendMul()
|
|
||||||
g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat())
|
|
||||||
|
|
||||||
|
|
||||||
blendNormal()
|
blendNormal()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun redraw() {
|
||||||
|
redrawSemaphore = true
|
||||||
|
}
|
||||||
|
|
||||||
/** Unlike lua function, this one in Zero-based. */
|
/** Unlike lua function, this one in Zero-based. */
|
||||||
override fun setCursor(x: Int, y: Int) {
|
override fun setCursor(x: Int, y: Int) {
|
||||||
cursorX = x
|
cursorX = x
|
||||||
|
|||||||
Reference in New Issue
Block a user