WIP collision solver, colour-codes in game fonts

Former-commit-id: 0bb85999176d89956398bbcc24e1b33cacd3e87c
Former-commit-id: 0ef0c1ac9b88f8fe42a7439fee69a8d4792be96a
This commit is contained in:
Song Minjae
2016-04-23 23:08:42 +09:00
parent cffc9a9ba2
commit 1a1159b643
33 changed files with 557 additions and 230 deletions

View File

@@ -1 +0,0 @@
*.{psd,tga,ogg} filter=lfs diff=lfs merge=lfs -text

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 986 B

View File

@@ -1,8 +1,5 @@
"STRING_ID";"IETF language tag(s) without dash";"enUS";"frFR";"esES";"deDE";"itIT";"ptBR";"ptPT";"ruRU";"elGR";"trTR";"daDK";"noNB";"svSE";"nlNL";"plPL";"fiFI";"jaJP";"zhCN";"zhTW";"koKR";"csCZ";"huHU";"roRO";"thTH";"bgBG";"heIL";"jakanaJP";"isIC" "STRING_ID";"IETF language tag(s) without dash";"enUS";"frFR";"esES";"deDE";"itIT";"ptBR";"ptPT";"ruRU";"elGR";"trTR";"daDK";"noNB";"svSE";"nlNL";"plPL";"fiFI";"jaJP";"zhCN";"zhTW";"koKR";"csCZ";"huHU";"roRO";"thTH";"bgBG";"heIL";"jakanaJP";"isIC"
"DEV_MEMORY_SHORT_CAP";;"MEM";"MEM";;;;;;;;;;;;;;;"メモリー";;;"메모리";;;;;;;"メモリー";"MIN"
"DEV_MEMORY_A_OF_B";;"%1$sM out of %2$sM";"%1$sM sur %2$sM";;;;;;;;;;;;;;;"%2$sM中%1$sM";;;"%2$sM 중 %1$sM";;;;;;;"%2$sM ちゅう %1$sM";"%1$sM af %2$sM"
"DEV_COLOUR_LEGEND_GREEN";;" GREEN";" VERT";;;;;;;;;;;;;;;"緑";;;"녹";;;;;;;" みどり";"grænn" "DEV_COLOUR_LEGEND_GREEN";;" GREEN";" VERT";;;;;;;;;;;;;;;"緑";;;"녹";;;;;;;" みどり";"grænn"
"DEV_COLOUR_LEGEND_BLUE";;" BLUE";" BLEU";;;;;;;;;;;;;;;"青";;;"청";;;;;;;"  あお";"blár" "DEV_COLOUR_LEGEND_BLUE";;" BLUE";" BLEU";;;;;;;;;;;;;;;"青";;;"청";;;;;;;"  あお";"blár"
"DEV_COLOUR_LEGEND_ORANGE";;"ORANGE";"ORANGE";;;;;;;;;;;;;;;"黄";;;"황";;;;;;;"オレンジ";"rauðugulur" "DEV_COLOUR_LEGEND_ORANGE";;"ORANGE";"ORANGE";;;;;;;;;;;;;;;"黄";;;"황";;;;;;;"オレンジ";"rauðugulur"
1 STRING_ID IETF language tag(s) without dash enUS frFR esES deDE itIT ptBR ptPT ruRU elGR trTR daDK noNB svSE nlNL plPL fiFI jaJP zhCN zhTW koKR csCZ huHU roRO thTH bgBG heIL jakanaJP isIC
2 DEV_MEMORY_SHORT_CAP DEV_COLOUR_LEGEND_GREEN MEM GREEN MEM VERT メモリー 메모리 メモリー  みどり MIN grænn
DEV_MEMORY_A_OF_B %1$sM out of %2$sM %1$sM sur %2$sM %2$sM中%1$sM %2$sM 중 %1$sM %2$sM ちゅう %1$sM %1$sM af %2$sM
DEV_COLOUR_LEGEND_GREEN GREEN VERT  みどり grænn
DEV_COLOUR_LEGEND_BLUE BLUE BLEU   あお blár
3 DEV_COLOUR_LEGEND_ORANGE DEV_COLOUR_LEGEND_BLUE ORANGE BLUE ORANGE BLEU オレンジ   あお rauðugulur blár
4 DEV_COLOUR_LEGEND_RED DEV_COLOUR_LEGEND_ORANGE RED ORANGE ROUGE ORANGE   あか オレンジ rauður rauðugulur
5 DEV_MESSAGE_CONSOLE_CODEX DEV_COLOUR_LEGEND_RED Type “codex” for available commands. RED Tapez « codex » pour commandes disponibles. ROUGE 使用可能な命令語の目録は「codex」を入力してください。 사용 가능한 명령어 목록을 보려면 ‘codex’를 입력해 주십시오. しようかのうな めいれいごのもくろくは 「codex」を にゅうりょくしてください。   あか Skrifa „codex“ fyrir tiltækilegum skipunum. rauður

View File

@@ -59,16 +59,16 @@ class Col216 : LimitedColours {
private fun assertRaw(i: Int) { private fun assertRaw(i: Int) {
if (i >= COLOUR_RANGE_SIZE || i < 0) { if (i >= COLOUR_RANGE_SIZE || i < 0) {
println("i: " + i.toString()) System.err.println("Illegal colour input: $i")
throw IllegalArgumentException() throw IllegalArgumentException()
} }
} }
private fun assertRGB(r: Int, g: Int, b: Int) { private fun assertRGB(r: Int, g: Int, b: Int) {
if (r !in 0..MAX_STEP || g !in 0..MAX_STEP || b !in 0..MAX_STEP) { if (r !in 0..MAX_STEP || g !in 0..MAX_STEP || b !in 0..MAX_STEP) {
println("r: " + r.toString()) System.err.println("Illegal colour input for channel r: $r")
println("g: " + g.toString()) System.err.println("Illegal colour input for channel g: $g")
println("b: " + b.toString()) System.err.println("Illegal colour input for channel b: $b")
throw IllegalArgumentException() throw IllegalArgumentException()
} }
} }

View File

@@ -111,17 +111,17 @@ class Col4096 : LimitedColours {
private fun assertRaw(i: Int) { private fun assertRaw(i: Int) {
if (i > 0xFFFF || i < 0) { if (i > 0xFFFF || i < 0) {
println("i: " + i.toString()) System.err.println("Illegal colour input: $i")
throw IllegalArgumentException() throw IllegalArgumentException()
} }
} }
private fun assertARGB(a: Int, r: Int, g: Int, b: Int) { private fun assertARGB(a: Int, r: Int, g: Int, b: Int) {
if (a !in 0..16 || r !in 0..16 || g !in 0..16 || b !in 0..16) { if (a !in 0..16 || r !in 0..16 || g !in 0..16 || b !in 0..16) {
println("a: " + a.toString()) System.err.println("Illegal colour input for channel a: $a")
println("r: " + r.toString()) System.err.println("Illegal colour input for channel r: $r")
println("g: " + g.toString()) System.err.println("Illegal colour input for channel g: $g")
println("b: " + b.toString()) System.err.println("Illegal colour input for channel b: $b")
throw IllegalArgumentException() throw IllegalArgumentException()
} }
} }

View File

@@ -53,7 +53,7 @@ constructor() : Font {
private fun isHangul(c: Char) = c.toInt() >= 0xAC00 && c.toInt() < 0xD7A4 private fun isHangul(c: Char) = c.toInt() >= 0xAC00 && c.toInt() < 0xD7A4
private fun isAscii(c: Char) = c.toInt() > 0 && c.toInt() <= 0xFF private fun isAscii(c: Char) = c.toInt() > 0x20 && c.toInt() <= 0xFF
private fun isRunic(c: Char) = runicList.contains(c) private fun isRunic(c: Char) = runicList.contains(c)
@@ -138,7 +138,9 @@ constructor() : Font {
} }
if (c == SHEET_ASCII_EF || c == SHEET_EXTA_EF || c == SHEET_CYRILIC_EF) if (c == SHEET_COLOURCODE)
len += 0
else if (c == SHEET_ASCII_EF || c == SHEET_EXTA_EF || c == SHEET_CYRILIC_EF)
len += W_LATIN_NARROW len += W_LATIN_NARROW
else if (c == SHEET_KANA || c == SHEET_HANGUL || c == SHEET_CJK_PUNCT) else if (c == SHEET_KANA || c == SHEET_HANGUL || c == SHEET_CJK_PUNCT)
len += W_CJK len += W_CJK
@@ -163,12 +165,19 @@ constructor() : Font {
GL11.glColorMask(true, true, true, true) GL11.glColorMask(true, true, true, true)
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA) GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
var thisCol = color
// hangul fonts first // hangul fonts first
//hangulSheet.startUse() // disabling texture binding to make the font coloured //hangulSheet.startUse() // disabling texture binding to make the font coloured
// JOHAB // JOHAB
for (i in 0..s.length - 1) { for (i in 0..s.length - 1) {
val ch = s[i] val ch = s[i]
if (ch.isColourCode()) {
thisCol = colourKey[ch]!!
continue
}
if (isHangul(ch)) { if (isHangul(ch)) {
val hIndex = ch.toInt() - 0xAC00 val hIndex = ch.toInt() - 0xAC00
@@ -204,17 +213,17 @@ constructor() : Font {
hangulSheet.getSubImage(indexCho, choRow).draw( hangulSheet.getSubImage(indexCho, choRow).draw(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f).toFloat(), Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f).toFloat(),
color thisCol
) )
hangulSheet.getSubImage(indexJung, jungRow).draw( hangulSheet.getSubImage(indexJung, jungRow).draw(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f).toFloat(), Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f).toFloat(),
color thisCol
) )
hangulSheet.getSubImage(indexJong, jongRow).draw( hangulSheet.getSubImage(indexJong, jongRow).draw(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f).toFloat(), Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f).toFloat(),
color thisCol
) )
} }
} }
@@ -246,6 +255,11 @@ constructor() : Font {
for (i in 0..s.length - 1) { for (i in 0..s.length - 1) {
val ch = s[i] val ch = s[i]
if (ch.isColourCode()) {
thisCol = colourKey[ch]!!
continue
}
if (isWenQuanYi1(ch)) { if (isWenQuanYi1(ch)) {
val glyphW = getWidth("" + ch) val glyphW = getWidth("" + ch)
/*wenQuanYi_1.renderInUse( /*wenQuanYi_1.renderInUse(
@@ -257,7 +271,7 @@ constructor() : Font {
wenQuanYi_1.getSubImage(wenQuanYiIndexX(ch), wenQuanYi1IndexY(ch)).draw( wenQuanYi_1.getSubImage(wenQuanYiIndexX(ch), wenQuanYi1IndexY(ch)).draw(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
Math.round((H - H_UNIHAN) / 2 + y).toFloat(), Math.round((H - H_UNIHAN) / 2 + y).toFloat(),
color thisCol
) )
} }
} }
@@ -269,6 +283,11 @@ constructor() : Font {
for (i in 0..s.length - 1) { for (i in 0..s.length - 1) {
val ch = s[i] val ch = s[i]
if (ch.isColourCode()) {
thisCol = colourKey[ch]!!
continue
}
if (isWenQuanYi2(ch)) { if (isWenQuanYi2(ch)) {
val glyphW = getWidth("" + ch) val glyphW = getWidth("" + ch)
/*wenQuanYi_2.renderInUse( /*wenQuanYi_2.renderInUse(
@@ -280,7 +299,7 @@ constructor() : Font {
wenQuanYi_2.getSubImage(wenQuanYiIndexX(ch), wenQuanYi2IndexY(ch)).draw( wenQuanYi_2.getSubImage(wenQuanYiIndexX(ch), wenQuanYi2IndexY(ch)).draw(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
Math.round((H - H_UNIHAN) / 2 + y).toFloat(), Math.round((H - H_UNIHAN) / 2 + y).toFloat(),
color thisCol
) )
} }
} }
@@ -292,6 +311,11 @@ constructor() : Font {
for (i in 0..s.length - 1) { for (i in 0..s.length - 1) {
val ch = s[i] val ch = s[i]
if (ch.isColourCode()) {
thisCol = colourKey[ch]!!
continue
}
if (!isHangul(ch) && !isUniHan(ch)) { if (!isHangul(ch) && !isUniHan(ch)) {
// if not init, endUse first // if not init, endUse first
@@ -369,7 +393,7 @@ constructor() : Font {
else if (prevInstance == SHEET_FW_UNI) (H - H_HANGUL) / 2 else if (prevInstance == SHEET_FW_UNI) (H - H_HANGUL) / 2
else 0).toFloat(), else 0).toFloat(),
color thisCol
) )
} }
catch (e: ArrayIndexOutOfBoundsException) { catch (e: ArrayIndexOutOfBoundsException) {
@@ -413,6 +437,8 @@ constructor() : Font {
return SHEET_CJK_PUNCT return SHEET_CJK_PUNCT
else if (isFullwidthUni(c)) else if (isFullwidthUni(c))
return SHEET_FW_UNI return SHEET_FW_UNI
else if (c.isColourCode())
return SHEET_COLOURCODE
else else
return SHEET_ASCII_EM// fixed width punctuations return SHEET_ASCII_EM// fixed width punctuations
// fixed width // fixed width
@@ -464,6 +490,8 @@ constructor() : Font {
Terrarum.appgc.graphics.setDrawMode(Graphics.MODE_NORMAL) Terrarum.appgc.graphics.setDrawMode(Graphics.MODE_NORMAL)
} }
fun Char.isColourCode() = colourKey.containsKey(this)
companion object { companion object {
lateinit internal var hangulSheet: SpriteSheet lateinit internal var hangulSheet: SpriteSheet
@@ -510,6 +538,8 @@ constructor() : Font {
internal val SHEET_WENQUANYI_1 = 13 internal val SHEET_WENQUANYI_1 = 13
internal val SHEET_WENQUANYI_2 = 14 internal val SHEET_WENQUANYI_2 = 14
internal val SHEET_COLOURCODE = 255
lateinit internal var sheetKey: Array<SpriteSheet> lateinit internal var sheetKey: Array<SpriteSheet>
internal val asciiEFList = arrayOf(' ', '!', '"', '\'', '(', ')', ',', '.', ':', ';', 'I', '[', ']', '`', 'f', 'i', 'j', 'l', 't', '{', '|', '}', 0xA1.toChar(), 'Ì', 'Í', 'Î', 'Ï', 'ì', 'í', 'î', 'ï', '·') internal val asciiEFList = arrayOf(' ', '!', '"', '\'', '(', ')', ',', '.', ':', ';', 'I', '[', ']', '`', 'f', 'i', 'j', 'l', 't', '{', '|', '}', 0xA1.toChar(), 'Ì', 'Í', 'Î', 'Ï', 'ì', 'í', 'î', 'ï', '·')
@@ -554,5 +584,30 @@ constructor() : Font {
internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', '', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '', '᛫', '', 'ᛮ', 'ᛯ', 'ᛰ') internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', '', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '', '᛫', '', 'ᛮ', 'ᛯ', 'ᛰ')
internal var interchar = 0 internal var interchar = 0
val colourKey = hashMapOf(
Pair(0x11.toChar(), Color(0xFFFFFF)), //w
Pair(0x12.toChar(), Color(0xFF8080)), //r
Pair(0x13.toChar(), Color(0x80FF80)), //g
Pair(0x14.toChar(), Color(0x8080FF)), //b
Pair(0x15.toChar(), Color(0xFFE080)), //y
Pair(0x16.toChar(), Color(0x808080)) //k
)
val colToCode = hashMapOf(
Pair("w", 0x11.toChar()),
Pair("r", 0x12.toChar()),
Pair("g", 0x13.toChar()),
Pair("b", 0x14.toChar()),
Pair("y", 0x15.toChar()),
Pair("k", 0x16.toChar())
)
val codeToCol = hashMapOf(
Pair("w", colourKey[0x11.toChar()]),
Pair("r", colourKey[0x12.toChar()]),
Pair("g", colourKey[0x13.toChar()]),
Pair("b", colourKey[0x14.toChar()]),
Pair("y", colourKey[0x15.toChar()]),
Pair("k", colourKey[0x16.toChar()])
)
} }
} }

View File

@@ -47,7 +47,7 @@ constructor() : GameFontBase() {
GameFontBase.wenQuanYi_2 = SpriteSheet( GameFontBase.wenQuanYi_2 = SpriteSheet(
"./res/graphics/fonts/wenquanyi_11pt_part2.png", 16, 18, 2) "./res/graphics/fonts/wenquanyi_11pt_part2.png", 16, 18, 2)
val shk = arrayOf<SpriteSheet>( val shk = arrayOf(
GameFontBase.asciiSheet, GameFontBase.asciiSheet,
GameFontBase.asciiSheetEF, GameFontBase.asciiSheetEF,
GameFontBase.hangulSheet, GameFontBase.hangulSheet,

View File

@@ -1,50 +0,0 @@
package net.torvald.imagefont
import org.newdawn.slick.Color
import org.newdawn.slick.Font
import org.newdawn.slick.SpriteSheet
/**
* Created by minjaesong on 16-04-15.
*/
class SmallNumbers : Font {
internal val fontSheet: SpriteSheet
internal val W = 8
internal val H = 8
private val chars = arrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-')
init {
fontSheet = SpriteSheet("./res/graphics/fonts/numeric_small.png", W, H)
}
override fun getHeight(str: String): Int = H
override fun getWidth(str: String): Int = str.length * W
override fun getLineHeight(): Int = H
override fun drawString(x: Float, y: Float, text: String) = drawString(x, y, text, Color.white)
override fun drawString(x: Float, y: Float, text: String, col: Color) {
for (i in 0..text.length - 1) {
val index = charToSpriteNum(text.codePointAt(i))
if (index != null) {
fontSheet.getSubImage(index, 0).draw(
x + i * W, y, col
)
}
}
}
override fun drawString(x: Float, y: Float, text: String, col: Color, startIndex: Int, endIndex: Int) {
throw UnsupportedOperationException()
}
private fun charToSpriteNum(ch: Int): Int? =
if (ch in '0'.toInt()..'9'.toInt()) ch - '0'.toInt()
else if (ch == '-'.toInt()) 10
else null
}

View File

@@ -0,0 +1,78 @@
package net.torvald.imagefont
import org.newdawn.slick.Color
import org.newdawn.slick.Font
import org.newdawn.slick.SpriteSheet
import java.util.*
/**
* Created by minjaesong on 16-04-15.
*/
class TinyAlphNum : Font {
internal val fontSheet: SpriteSheet
internal val W = 8
internal val H = 8
private val chars = arrayOf(
'0','1','2','3','4','5','6','7',
'8','9','[','#','@',':','>','?',
' ','A','B','C','D','E','F','G',
'H','I','&','.',']','(','<','\\',
'^','J','K','L','M','N','O','P',
'Q','R','-','¤','*',')',';','\'',
'+','/','S','T','U','V','W','X',
'Y','Z','_',',','%','=','"','!'
)
private val mappingTable = HashMap<Int, Int>()
init {
fontSheet = SpriteSheet("./res/graphics/fonts/alphanumeric_small.png", W, H)
chars.forEachIndexed { i, c -> mappingTable[c.toInt()] = i }
}
override fun getHeight(str: String): Int = H
override fun getWidth(str: String): Int {
var ret = 0
for (i in 0..str.length - 1) {
val c = str.codePointAt(i).toChar()
if (!c.isColourCode())
ret += W
}
return ret
}
override fun getLineHeight(): Int = H
override fun drawString(x: Float, y: Float, text: String) = drawString(x, y, text, Color.white)
override fun drawString(x: Float, y: Float, text: String, col: Color) {
var thisCol = col
var textPosOffset = 0
for (i in 0..text.length - 1) {
val index = charToSpriteNum(text.toUpperCase().codePointAt(i))
val ch = text[i]
if (ch.isColourCode()) {
thisCol = GameFontBase.colourKey[ch]!!
continue
}
if (index != null) {
fontSheet.getSubImage(index % 8, index / 8).draw(
x + textPosOffset, y, thisCol
)
}
textPosOffset += W
}
}
override fun drawString(x: Float, y: Float, text: String, col: Color, startIndex: Int, endIndex: Int) {
throw UnsupportedOperationException()
}
private fun charToSpriteNum(ch: Int): Int? = mappingTable[ch]
fun Char.isColourCode() = GameFontBase.colourKey.containsKey(this)
}

View File

@@ -34,11 +34,17 @@ import java.util.*
*/ */
class Game @Throws(SlickException::class) class Game @Throws(SlickException::class)
constructor() : BasicGameState() { constructor() : BasicGameState() {
private val ACTOR_UPDATE_RANGE = 4096
internal var game_mode = 0 internal var game_mode = 0
lateinit var map: GameMap lateinit var map: GameMap
val actorContainer = LinkedList<Actor>() /**
* Linked list of Actors that is sorted by Actors' referenceID
*/
val actorContainer = ArrayList<Actor>(128)
val actorcontainerInactive = ArrayList<Actor>(128)
val uiContainer = LinkedList<UIHandler>() val uiContainer = LinkedList<UIHandler>()
lateinit var consoleHandler: UIHandler lateinit var consoleHandler: UIHandler
@@ -128,7 +134,6 @@ constructor() : BasicGameState() {
update_delta = delta update_delta = delta
setAppTitle() setAppTitle()
// GL at after_sunrise-noon_before_sunset
map.updateWorldTime(delta) map.updateWorldTime(delta)
map.globalLight = globalLightByTime map.globalLight = globalLightByTime
@@ -139,12 +144,19 @@ constructor() : BasicGameState() {
MapDrawer.update(gc, delta) MapDrawer.update(gc, delta)
MapCamera.update(gc, delta) MapCamera.update(gc, delta)
actorContainer.forEach { actor -> actor.update(gc, delta) } actorContainer.forEach { actor -> // update actors
actorContainer.forEach { actor -> if (actor !is Visible
if (actor is Visible) { || actor is Visible && distToActorSqr(actor, player) < ACTOR_UPDATE_RANGE.sqr())
// update if the does not have specific position. (visible)
// if the actor has position (visible), update only if it is within the range
actor.update(gc, delta)
}
actorContainer.forEach { actor -> // update sprite(s)
if (actor is Visible &&
distToActorSqr(actor, player) <= (Terrarum.WIDTH.plus(actor.hitbox.width.div(2)).sqr() +
Terrarum.HEIGHT.plus(actor.hitbox.height.div(2)).sqr())
) { // if visible and within screen
actor.updateBodySprite(gc, delta) actor.updateBodySprite(gc, delta)
}
if (actor is Glowing) {
actor.updateGlowSprite(gc, delta) actor.updateGlowSprite(gc, delta)
} }
} }
@@ -186,7 +198,14 @@ constructor() : BasicGameState() {
MapCamera.renderBehind(gc, g) MapCamera.renderBehind(gc, g)
// draw actors // draw actors
actorContainer.forEach { actor -> if (actor is Visible) actor.drawBody(gc, g) } actorContainer.forEach { actor ->
if (actor is Visible &&
distToActorSqr(actor, player) <= (Terrarum.WIDTH.plus(actor.hitbox.width.div(2)).sqr() +
Terrarum.HEIGHT.plus(actor.hitbox.height.div(2)).sqr())
) { // if visible and within screen
actor.drawBody(gc, g)
}
}
player.drawBody(gc, g) player.drawBody(gc, g)
LightmapRenderer.renderLightMap() LightmapRenderer.renderLightMap()
@@ -204,12 +223,19 @@ constructor() : BasicGameState() {
setBlendNormal() setBlendNormal()
// draw actor glows // draw actor glows
actorContainer.forEach { actor -> if (actor is Glowing) actor.drawGlow(gc, g) } actorContainer.forEach { actor ->
if (actor is Visible &&
distToActorSqr(actor, player) <= (Terrarum.WIDTH.plus(actor.hitbox.width.div(2)).sqr() +
Terrarum.HEIGHT.plus(actor.hitbox.height.div(2)).sqr())
) {
actor.drawGlow(gc, g)
}
}
player.drawGlow(gc, g) player.drawGlow(gc, g)
// draw reference ID if debugWindow is open // draw reference ID if debugWindow is open
if (debugWindow.isVisible) { if (debugWindow.visible) {
actorContainer.forEach { actor -> actorContainer.forEachIndexed { i, actor ->
if (actor is Visible) { if (actor is Visible) {
g.color = Color.white g.color = Color.white
g.font = Terrarum.smallNumbers g.font = Terrarum.smallNumbers
@@ -218,6 +244,12 @@ constructor() : BasicGameState() {
actor.hitbox.posX, actor.hitbox.posX,
actor.hitbox.pointedY + 4 actor.hitbox.pointedY + 4
) )
g.color = Color(0x80FF80)
g.drawString(
i.toString(),
actor.hitbox.posX,
actor.hitbox.pointedY + 12
)
g.font = Terrarum.gameFont g.font = Terrarum.gameFont
} }
} }
@@ -304,40 +336,67 @@ constructor() : BasicGameState() {
(this and 0xff00).ushr(8).shl(10) or (this and 0xff00).ushr(8).shl(10) or
(this and 0xff0000).ushr(16).shl(20) (this and 0xff0000).ushr(16).shl(20)
fun Float.sqr() = this * this
fun Int.sqr() = this * this
private fun distToActorSqr(a: Visible, p: Player) =
(a.hitbox.centeredX - p.hitbox.centeredX).sqr() + (a.hitbox.centeredY - p.hitbox.centeredY).sqr()
/** /**
* actorContainer extensions * actorContainer extensions
*/ */
fun hasActor(ID: Int): Boolean { fun hasActor(ID: Int): Boolean =
for (actor in actorContainer) { if (actorContainer.size == 0)
if (actor.referenceID == ID) return true false
} else
return false actorContainer.binarySearch(ID) >= 0
}
/**
* Remove actor and sort the list
*/
fun removeActor(ID: Int) { fun removeActor(ID: Int) {
for (actor in actorContainer) { for (actor in actorContainer) {
if (actor.referenceID == ID) if (actor.referenceID == ID) {
actorContainer.remove(actor) actorContainer.remove(actor)
actorContainer.sort()
break
}
} }
} }
/**
* Add actor and sort the list
*/
fun addActor(other: Actor): Boolean { fun addActor(other: Actor): Boolean {
if (hasActor(other.referenceID)) return false if (hasActor(other.referenceID)) return false
actorContainer.add(other) actorContainer.add(other)
actorContainer.sort()
return true return true
} }
fun getActor(ID: Int): Actor { fun getActor(ID: Int): Actor {
for (actor in actorContainer) { if (actorContainer.size == 0) throw IllegalArgumentException("Actor with ID $ID does not exist.")
if (actor.referenceID == ID)
return actor val index = actorContainer.binarySearch(ID)
} if (index < 0)
throw NullPointerException("Actor with ID $ID does not exist.") throw IllegalArgumentException("Actor with ID $ID does not exist.")
else
return actorContainer[index]
} }
fun addUI(other: UIHandler): Boolean { private fun ArrayList<Actor>.binarySearch(ID: Int): Int {
if (uiContainer.contains(other)) return false var low = 0
uiContainer.add(other) var high = actorContainer.size - 1
return true
while (low <= high) {
val mid = (low + high).ushr(1) // safe from overflows
val midVal = get(mid)
if (ID > midVal.referenceID)
low = mid + 1
else if (ID < midVal.referenceID)
high = mid - 1
else
return mid // key found
}
return -(low + 1) // key not found
} }
} }

View File

@@ -3,7 +3,7 @@ package net.torvald.terrarum
import net.torvald.imagefont.GameFontWhite import net.torvald.imagefont.GameFontWhite
import net.torvald.JsonFetcher import net.torvald.JsonFetcher
import net.torvald.JsonWriter import net.torvald.JsonWriter
import net.torvald.imagefont.SmallNumbers import net.torvald.imagefont.TinyAlphNum
import org.lwjgl.input.Controllers import org.lwjgl.input.Controllers
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
import org.newdawn.slick.* import org.newdawn.slick.*
@@ -47,7 +47,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
@Throws(SlickException::class) @Throws(SlickException::class)
override fun initStatesList(gc: GameContainer) { override fun initStatesList(gc: GameContainer) {
gameFont = GameFontWhite() gameFont = GameFontWhite()
smallNumbers = SmallNumbers() smallNumbers = TinyAlphNum()
hasController = gc.input.controllerCount > 0 hasController = gc.input.controllerCount > 0
if (hasController) { if (hasController) {

View File

@@ -9,6 +9,8 @@ import org.apache.commons.codec.digest.DigestUtils
*/ */
class Authenticator : ConsoleCommand { class Authenticator : ConsoleCommand {
private var a = false
override fun execute(args: Array<String>) { override fun execute(args: Array<String>) {
if (args.size == 2) { if (args.size == 2) {
val pwd = args[1] val pwd = args[1]
@@ -38,9 +40,4 @@ class Authenticator : ConsoleCommand {
override fun printUsage() { override fun printUsage() {
CommandInterpreter.echoUnknownCmd("auth") CommandInterpreter.echoUnknownCmd("auth")
} }
companion object {
private var a = false
}
} }

View File

@@ -48,9 +48,9 @@ object CommandInterpreter {
} }
} }
catch (e: Exception) { catch (e: Exception) {
println("[CommandInterpreter] :") System.err.print("[CommandInterpreter] ")
e.printStackTrace() e.printStackTrace()
Echo().execute(Lang.get("ERROR_GENERIC_TEXT")) Echo().error(Lang["ERROR_GENERIC_TEXT"])
} }
} }
@@ -92,8 +92,8 @@ object CommandInterpreter {
val sb = StringBuilder() val sb = StringBuilder()
val formatter = Formatter(sb) val formatter = Formatter(sb)
Echo().execute( Echo().error(
formatter.format(Lang.get("DEV_MESSAGE_CONSOLE_COMMAND_UNKNOWN"), cmdname).toString()) formatter.format(Lang["DEV_MESSAGE_CONSOLE_COMMAND_UNKNOWN"], cmdname).toString())
} }
private class CommandInput(o: Array<Any>) { private class CommandInput(o: Array<Any>) {

View File

@@ -1,5 +1,6 @@
package net.torvald.terrarum.console package net.torvald.terrarum.console
import net.torvald.imagefont.GameFontBase
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.ui.ConsoleWindow import net.torvald.terrarum.ui.ConsoleWindow
@@ -20,6 +21,10 @@ internal class Echo : ConsoleCommand {
(Terrarum.game.consoleHandler.UI as ConsoleWindow).sendMessage(single_line) (Terrarum.game.consoleHandler.UI as ConsoleWindow).sendMessage(single_line)
} }
fun error(single_line: String) {
(Terrarum.game.consoleHandler.UI as ConsoleWindow).sendMessage("${GameFontBase.colToCode["r"]}$single_line")
}
override fun printUsage() { override fun printUsage() {
} }

View File

@@ -17,37 +17,73 @@ class GetAV : ConsoleCommand {
val av = Terrarum.game.player.actorValue val av = Terrarum.game.player.actorValue
val keyset = av.keySet val keyset = av.keySet
echo.execute("== ActorValue list for player ==")
keyset.forEach { elem -> echo.execute("$elem = ${av[elem as String]}") } keyset.forEach { elem -> echo.execute("$elem = ${av[elem as String]}") }
} }
else if (args.size != 3 && args.size != 2) { else if (args.size != 3 && args.size != 2) {
printUsage() printUsage()
} }
else if (args.size == 2) { else if (args.size == 2) {
echo.execute("player." + args[1] + " = " // check if args[1] is number or not
+ Terrarum.game.player.actorValue[args[1]] if (!args[1].isNum()) { // args[1] is ActorValue name
+ " (" echo.execute("player.${args[1]} = "
+ Terrarum.game.player.actorValue[args[1]]!!.javaClass.simpleName + Terrarum.game.player.actorValue[args[1]]
+ ")") + " ("
+ Terrarum.game.player.actorValue[args[1]]!!.javaClass.simpleName
+ ")"
)
}
else { // args[1] is actor ID
val av = Terrarum.game.getActor(args[1].toInt()).actorValue
val keyset = av.keySet
echo.execute("== ActorValue list for ${args[1].toInt()} ==")
if (keyset.size == 0)
echo.execute("(nothing)")
else
keyset.forEach { elem -> echo.execute("$elem = ${av[elem as String]}") }
}
} }
else if (args.size == 3) { else if (args.size == 3) {
val id = args[1].toInt()
val av = args[2]
echo.execute("$id.$av = " +
Terrarum.game.getActor(id).actorValue[av] +
" (" +
Terrarum.game.getActor(id).actorValue[av]!!.javaClass.simpleName +
")"
)
} }
} }
catch (e: NullPointerException) { catch (e: NullPointerException) {
if (args.size == 2) { if (args.size == 2) {
echo.execute(args[1] + ": actor value does not exist.") echo.error(args[1] + ": actor value does not exist.")
} }
else if (args.size == 3) { else if (args.size == 3) {
echo.execute(args[2] + ": actor value does not exist.") echo.error(args[2] + ": actor value does not exist.")
} }
else { else {
throw NullPointerException() throw NullPointerException()
} }
} }
catch (e1: IllegalArgumentException) {
if (args.size == 3) {
echo.error(args[1] + ": no actor with this ID.")
}
}
} }
fun String.isNum(): Boolean {
try {
this.toInt()
return true
}
catch (e: NumberFormatException) {
return false
}
}
override fun printUsage() { override fun printUsage() {
val echo = Echo() val echo = Echo()
echo.execute("Get desired actor value of specific target.") echo.execute("Get desired actor value of specific target.")

View File

@@ -19,43 +19,81 @@ internal class SetAV : ConsoleCommand {
} }
override fun execute(args: Array<String>) { override fun execute(args: Array<String>) {
val echo = Echo()
// setav <id or "player"> <av> <val> fun parseAVInput(arg: String): Any {
if (args.size != 4 && args.size != 3) {
printUsage()
}
else if (args.size == 3) {
val `val`: Any val `val`: Any
try { try {
`val` = Integer(args[2]) // try for integer `val` = Integer(arg) // try for integer
} }
catch (e: NumberFormatException) { catch (e: NumberFormatException) {
try { try {
`val` = args[2].toFloat() // try for float `val` = arg.toFloat() // try for float
} }
catch (ee: NumberFormatException) { catch (ee: NumberFormatException) {
if (args[2].equals("__true", ignoreCase = true)) { if (arg.equals("__true", ignoreCase = true)) {
`val` = true `val` = true
} }
else if (args[2].equals("__false", ignoreCase = true)) { else if (arg.equals("__false", ignoreCase = true)) {
`val` = false `val` = false
} }
else { else {
`val` = args[2] // string if not number `val` = arg // string if not number
} }
} }
}
return `val`
}
val echo = Echo()
// setav <id, or blank for player> <av> <val>
if (args.size != 4 && args.size != 3) {
printUsage()
}
else if (args.size == 3) {
val `val` = parseAVInput(args[2])
// check if av is number
if (args[1].isNum()) {
echo.error("Illegal ActorValue “${args[1]}”: ActorValue cannot be a number.")
return
} }
Terrarum.game.player.actorValue[args[1]] = `val` Terrarum.game.player.actorValue[args[1]] = `val`
echo.execute("Set " + args[1] + " to " + `val`) echo.execute("Set ${args[1]} to $`val`")
} }
else if (args.size == 4) { else if (args.size == 4) {
try {
val id = args[1].toInt()
val `val` = parseAVInput(args[3])
// check if av is number
if (args[2].isNum()) {
echo.error("Illegal ActorValue “${args[2]}”: ActorValue cannot be a number.")
return
}
Terrarum.game.getActor(id).actorValue[args[2]] = `val`
echo.execute("Set ${args[2]} of $id to $`val`")
}
catch (e: IllegalArgumentException) {
if (args.size == 4)
echo.error(args[1] + ": no actor with this ID.")
}
} }
} }
fun String.isNum(): Boolean {
try {
this.toInt()
return true
}
catch (e: NumberFormatException) {
return false
}
}
} }

View File

@@ -5,15 +5,20 @@ import org.newdawn.slick.GameContainer
/** /**
* Created by minjaesong on 16-03-14. * Created by minjaesong on 16-03-14.
*/ */
interface Actor { abstract class Actor : Comparable<Actor> {
fun update(gc: GameContainer, delta_t: Int) abstract fun update(gc: GameContainer, delta_t: Int)
/** /**
* Valid RefID is equal to or greater than 32768. * Valid RefID is equal to or greater than 32768.
* @return Reference ID. (32768-0xFFFF_FFFF) * @return Reference ID. (32768-0xFFFF_FFFF)
*/ */
var referenceID: Int abstract var referenceID: Int
var actorValue: ActorValue abstract var actorValue: ActorValue
override fun equals(other: Any?) = referenceID == (other as Actor).referenceID
override fun hashCode() = referenceID
override fun toString() = "ActorID: ${hashCode()}"
override fun compareTo(other: Actor): Int = this.referenceID - other.referenceID
} }

View File

@@ -16,7 +16,7 @@ import org.newdawn.slick.Graphics
* *
* Created by minjaesong on 16-03-14. * Created by minjaesong on 16-03-14.
*/ */
open class ActorWithBody constructor() : Actor, Visible, Glowing { open class ActorWithBody constructor() : Actor(), Visible {
override var actorValue: ActorValue = ActorValue() override var actorValue: ActorValue = ActorValue()
@@ -26,15 +26,13 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
var baseHitboxH: Int = 0 var baseHitboxH: Int = 0
/** /**
* Velocity for newtonian sim. * Velocity vector (broken down by axes) for newtonian sim.
* Fluctuation in, otherwise still, velocity is equal to acceleration.
* Acceleration: used in code like: * Acceleration: used in code like:
* veloY += 3.0 * veloY += 3.0
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity. * +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
*/ */
@Volatile var veloX: Float = 0.toFloat() var veloX: Float = 0.toFloat()
@Volatile var veloY: Float = 0.toFloat() var veloY: Float = 0.toFloat()
@Transient private val VELO_HARD_LIMIT = 10000f @Transient private val VELO_HARD_LIMIT = 10000f
var grounded = false var grounded = false
@@ -61,16 +59,17 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
@Transient val nextHitbox = Hitbox(0f,0f,0f,0f) @Transient val nextHitbox = Hitbox(0f,0f,0f,0f)
/** /**
* Physical properties * Physical properties.
* Values derived from ActorValue must be @Transient.
*/ */
@Volatile @Transient var scale = 1f @Transient var scale = 1f
@Volatile @Transient var mass = 2f @Transient var mass = 2f
@Transient private val MASS_LOWEST = 2f @Transient private val MASS_LOWEST = 2f
/** Valid range: [0, 1] */ /** Valid range: [0, 1] */
var elasticity = 0f var elasticity = 0f
set(value) { set(value) {
if (value < 0) if (value < 0)
throw IllegalArgumentException("[ActorWithBody] $value: valid elasticity value is [0, 1].") throw IllegalArgumentException("[ActorWithBody] Invalid elasticity value: $value; valid elasticity value is [0, 1].")
else if (value > 1) { else if (value > 1) {
println("[ActorWithBody] Elasticity were capped to 1.") println("[ActorWithBody] Elasticity were capped to 1.")
field = ELASTICITY_MAX field = ELASTICITY_MAX
@@ -89,11 +88,11 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
*/ */
@Transient private val METER = 24f @Transient private val METER = 24f
/** /**
* [m / s^2] * SI_TO_GAME_ACC -> [px / IFrame^2] * [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
*/ */
@Transient private val SI_TO_GAME_ACC = METER / FastMath.sqr(Terrarum.TARGET_FPS.toFloat()) @Transient private val SI_TO_GAME_ACC = METER / FastMath.sqr(Terrarum.TARGET_FPS.toFloat())
/** /**
* [m / s] * SI_TO_GAME_VEL -> [px / IFrame] * [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame]
*/ */
@Transient private val SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS @Transient private val SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS
@@ -131,6 +130,8 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
@Transient private val MASS_DEFAULT = 60f @Transient private val MASS_DEFAULT = 60f
internal val physSleep: Boolean
get() = veloX.abs() < 0.5 && veloY.abs() < 0.5
private var posAdjustX = 0 private var posAdjustX = 0
private var posAdjustY = 0 private var posAdjustY = 0

View File

@@ -0,0 +1,104 @@
package net.torvald.terrarum.gameactors
import com.jme3.math.FastMath
import net.torvald.terrarum.Terrarum
import java.util.*
/**
* Created by minjaesong on 16-04-22.
*/
object CollisionSolver {
private const val STARTPOINT = 1
private const val ENDPOINT = 2
private const val COLL_LIST_SIZE = 256
private const val COLL_CANDIDATES_SIZE = 128
private const val COLL_FINAL_CANDIDATES_SIZE = 16
private val collListX = ArrayList<CollisionMarkings>(COLL_LIST_SIZE)
private val collListY = ArrayList<CollisionMarkings>(COLL_LIST_SIZE)
private val collCandidateX = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_CANDIDATES_SIZE)
private val collCandidateY = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_CANDIDATES_SIZE)
private val collCandidates = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_FINAL_CANDIDATES_SIZE)
/**
* @link https://www.toptal.com/game/video-game-physics-part-ii-collision-detection-for-solid-objects
*/
fun process() {
// mark list x
Terrarum.game.actorContainer.forEach { it ->
if (it is ActorWithBody) {
collListX.add(CollisionMarkings(it.hitbox.hitboxStart.x, STARTPOINT, it.referenceID))
collListX.add(CollisionMarkings(it.hitbox.hitboxEnd.x, ENDPOINT, it.referenceID))
}
}
// sort list x (will use Timsort with Java SE >= 8, Mergesort otherwise)
collListX.sortBy { it.pos }
// set candidateX
// mark list y
Terrarum.game.actorContainer.forEach { it ->
if (it is ActorWithBody) {
collListY.add(CollisionMarkings(it.hitbox.hitboxStart.y, STARTPOINT, it.referenceID))
collListY.add(CollisionMarkings(it.hitbox.hitboxEnd.y, ENDPOINT, it.referenceID))
}
}
// sort list y
collListY.sortBy { it.pos }
// set candidateY
// look for overlaps in candidate X/Y and put them into collCandidates
// solve collision for actors in collCandidates
}
private fun solveCollision(a: ActorWithBody, b: ActorWithBody) {
}
private infix fun ActorWithBody.isCollidingWith(other: ActorWithBody): Boolean {
val ax = this.hitbox.centeredX
val ay = this.hitbox.centeredY
val bx = other.hitbox.centeredX
val by = other.hitbox.centeredY
// will refer 'actor_dist_t' as 't' afterward
val actor_dist_t_sqr = ((ay - by).sqr() + (ax - bx).sqr()) // no sqrt; 'power' is slower than 'times'
val dist_x = (ax - bx).abs() // 'tx'
val dist_y = (ay - by).abs() // 'ty'
val tangent = dist_y / dist_x
var t_ax: Float; var t_ay: Float
if (dist_x > dist_y) {
t_ax = this.hitbox.width / 2
t_ay = t_ax * tangent
}
else {
t_ay = this.hitbox.height / 2
t_ax = t_ay * tangent
}
return (t_ax.sqr() + t_ay.sqr()) < actor_dist_t_sqr
}
fun Float.abs() = if (this < 0) -this else this
fun Float.sqr() = this * this
data class CollisionMarkings(
val pos: Float,
val kind: Int,
val actorID: Int
)
/**
* === Some useful physics knowledge ===
*
* * Momentum = mass × Velocity
*/
}

View File

@@ -1,13 +0,0 @@
package net.torvald.terrarum.gameactors
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
/**
* Created by minjaesong on 16-03-14.
*/
interface Glowing {
fun drawGlow(gc: GameContainer, g: Graphics)
fun updateGlowSprite(gc: GameContainer, delta: Int)
}

View File

@@ -15,7 +15,7 @@ class PhysTestBall : ActorWithBody {
constructor(): super() { constructor(): super() {
setHitboxDimension(16, 16, 0, 0) setHitboxDimension(16, 16, 0, 0)
isVisible = true isVisible = true
mass = 10f actorValue[AVKey.BASEMASS] = 10f
color = RoguelikeRandomiser.composeColourFrom(RoguelikeRandomiser.POTION_PRIMARY_COLSET) color = RoguelikeRandomiser.composeColourFrom(RoguelikeRandomiser.POTION_PRIMARY_COLSET)
} }
@@ -23,9 +23,9 @@ class PhysTestBall : ActorWithBody {
override fun drawBody(gc: GameContainer, g: Graphics) { override fun drawBody(gc: GameContainer, g: Graphics) {
g.color = color g.color = color
g.fillOval( g.fillOval(
hitbox!!.posX, hitbox.posX,
hitbox!!.posY, hitbox.posY,
hitbox!!.width, hitbox.width,
hitbox!!.height) hitbox.height)
} }
} }

View File

@@ -12,4 +12,8 @@ interface Visible {
fun drawBody(gc: GameContainer, g: Graphics) fun drawBody(gc: GameContainer, g: Graphics)
fun updateBodySprite(gc: GameContainer, delta: Int) fun updateBodySprite(gc: GameContainer, delta: Int)
fun drawGlow(gc: GameContainer, g: Graphics)
fun updateGlowSprite(gc: GameContainer, delta: Int)
} }

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.ui package net.torvald.terrarum.ui
import com.jme3.math.FastMath import com.jme3.math.FastMath
import net.torvald.imagefont.GameFontBase
import net.torvald.terrarum.gamemap.PairedMapLayer import net.torvald.terrarum.gamemap.PairedMapLayer
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.mapdrawer.LightmapRenderer import net.torvald.terrarum.mapdrawer.LightmapRenderer
@@ -18,7 +19,7 @@ import java.util.*
/** /**
* Created by minjaesong on 16-03-14. * Created by minjaesong on 16-03-14.
*/ */
class BasicDebugInfoWindow : UICanvas { class BasicDebugInfoWindow:UICanvas {
override var width: Int = Terrarum.WIDTH override var width: Int = Terrarum.WIDTH
override var height: Int = Terrarum.HEIGHT override var height: Int = Terrarum.HEIGHT
@@ -59,30 +60,35 @@ class BasicDebugInfoWindow : UICanvas {
val mouseTileX = ((MapCamera.cameraX + gc.input.mouseX / Terrarum.game.screenZoom) / MapDrawer.TILE_SIZE).toInt() val mouseTileX = ((MapCamera.cameraX + gc.input.mouseX / Terrarum.game.screenZoom) / MapDrawer.TILE_SIZE).toInt()
val mouseTileY = ((MapCamera.cameraY + gc.input.mouseY / Terrarum.game.screenZoom) / MapDrawer.TILE_SIZE).toInt() val mouseTileY = ((MapCamera.cameraY + gc.input.mouseY / Terrarum.game.screenZoom) / MapDrawer.TILE_SIZE).toInt()
g.color = Color.white g.font = Terrarum.smallNumbers
g.color = GameFontBase.codeToCol["y"]
val hitbox = player.hitbox val hitbox = player.hitbox
val nextHitbox = player.nextHitbox val nextHitbox = player.nextHitbox
printLine(g, 1, "posX: " val ccG = "${GameFontBase.colToCode["g"]}"
printLine(g, 1, "posX "
+ ccG
+ "${hitbox.pointedX.toString()}" + "${hitbox.pointedX.toString()}"
+ " (" + " ("
+ "${(hitbox.pointedX / MapDrawer.TILE_SIZE).toInt().toString()}" + "${(hitbox.pointedX / MapDrawer.TILE_SIZE).toInt().toString()}"
+ ")") + ")")
printLine(g, 2, "posY: " printLine(g, 2, "posY "
+ ccG
+ hitbox.pointedY.toString() + hitbox.pointedY.toString()
+ " (" + " ("
+ (hitbox.pointedY / MapDrawer.TILE_SIZE).toInt().toString() + (hitbox.pointedY / MapDrawer.TILE_SIZE).toInt().toString()
+ ")") + ")")
printLine(g, 3, "veloX reported: ${player.veloX}") printLine(g, 3, "veloX reported $ccG${player.veloX}")
printLine(g, 4, "veloY reported: ${player.veloY}") printLine(g, 4, "veloY reported $ccG${player.veloY}")
printLineColumn(g, 2, 3, "veloX measured: ${xdelta}") printLineColumn(g, 2, 3, "veloX measured $ccG${xdelta}")
printLineColumn(g, 2, 4, "veloY measured: ${ydelta}") printLineColumn(g, 2, 4, "veloY measured $ccG${ydelta}")
printLine(g, 5, "grounded : ${player.grounded}") printLine(g, 5, "grounded $ccG${player.grounded}")
printLine(g, 6, "noClip : ${player.noClip}") printLine(g, 6, "noClip $ccG${player.noClip}")
val lightVal: String val lightVal: String
var mtX = mouseTileX.toString() var mtX = mouseTileX.toString()
@@ -100,7 +106,7 @@ class BasicDebugInfoWindow : UICanvas {
rawB.toString() + ")" rawB.toString() + ")"
printLine(g, 7, "light at cursor : " + lightVal) printLine(g, 7, "light@cursor $ccG$lightVal")
val tileNo: String val tileNo: String
val tileNumRaw = Terrarum.game.map.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1 val tileNumRaw = Terrarum.game.map.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1
@@ -108,33 +114,22 @@ class BasicDebugInfoWindow : UICanvas {
val tiledmg = tileNumRaw % PairedMapLayer.RANGE val tiledmg = tileNumRaw % PairedMapLayer.RANGE
tileNo = if (tileNumRaw == -1) "" else "$tilenum:$tiledmg" tileNo = if (tileNumRaw == -1) "" else "$tilenum:$tiledmg"
printLine(g, 8, "tile at cursor : $tileNo ($mtX, $mtY)") printLine(g, 8, "tile@cursor $ccG$tileNo ($mtX, $mtY)")
/** /**
* Second column * Second column
*/ */
printLineColumn(g, 2, 1, "${Lang["MENU_OPTIONS_VSYNC"]} : " + Terrarum.appgc.isVSyncRequested) printLineColumn(g, 2, 1, "VSync $ccG" + Terrarum.appgc.isVSyncRequested)
printLineColumn(g, 2, 2, "Env colour temp : " + MapDrawer.getColTemp()) printLineColumn(g, 2, 2, "Env colour temp $ccG" + MapDrawer.getColTemp())
printLineColumn(g, 2, 5, "Time : ${Terrarum.game.map.worldTime.elapsedSeconds()}" + printLineColumn(g, 2, 5, "Time $ccG${Terrarum.game.map.worldTime.elapsedSeconds()}" +
" (${Terrarum.game.map.worldTime.getFormattedTime()})") " (${Terrarum.game.map.worldTime.getFormattedTime()})")
printLineColumn(g, 2, 6, "Mass : ${player.mass}") printLineColumn(g, 2, 6, "Mass $ccG${player.mass}")
/** /**
* On screen * On screen
*/ */
// Memory allocation
val memInUse = Terrarum.game.memInUse
val totalVMMem = Terrarum.game.totalVMMem
g.color = Color(0xFF7F00)
g.drawString(
Lang["DEV_MEMORY_SHORT_CAP"]
+ " : "
+ formatter.format(
Lang["DEV_MEMORY_A_OF_B"], memInUse, totalVMMem), (Terrarum.WIDTH - 200).toFloat(), line(1).toFloat())
// Hitbox // Hitbox
val zoom = Terrarum.game.screenZoom val zoom = Terrarum.game.screenZoom
g.color = Color(0x007f00) g.color = Color(0x007f00)
@@ -148,12 +143,12 @@ class BasicDebugInfoWindow : UICanvas {
, (hitbox.pointedY - 1) * zoom - MapCamera.cameraY * zoom , (hitbox.pointedY - 1) * zoom - MapCamera.cameraY * zoom
, 3f, 3f) , 3f, 3f)
g.drawString( g.drawString(
Lang["DEV_COLOUR_LEGEND_GREEN"] + " : hitbox", (Terrarum.WIDTH - 200).toFloat() "hitbox", (Terrarum.WIDTH - 15 * 8 - 2).toFloat().toFloat()
, line(2).toFloat()) , line(1))
// Next hitbox // Next hitbox
g.color = Color.blue g.color = Color.blue
g.drawRect(nextHitbox!!.hitboxStart.x * zoom - MapCamera.cameraX * zoom g.drawRect(nextHitbox.hitboxStart.x * zoom - MapCamera.cameraX * zoom
, nextHitbox.hitboxStart.y * zoom - MapCamera.cameraY * zoom , nextHitbox.hitboxStart.y * zoom - MapCamera.cameraY * zoom
, nextHitbox.width * zoom , nextHitbox.width * zoom
, nextHitbox.height * zoom) , nextHitbox.height * zoom)
@@ -163,21 +158,41 @@ class BasicDebugInfoWindow : UICanvas {
, (nextHitbox.pointedY - 1) * zoom - MapCamera.cameraY * zoom , (nextHitbox.pointedY - 1) * zoom - MapCamera.cameraY * zoom
, 3f, 3f) , 3f, 3f)
g.drawString( g.drawString(
Lang["DEV_COLOUR_LEGEND_BLUE"] + " : nextHitbox", (Terrarum.WIDTH - 200).toFloat() "nextHitbox", (Terrarum.WIDTH - 15 * 8 - 2).toFloat().toFloat()
, line(3).toFloat()) , line(2))
drawHistogram(g, LightmapRenderer.histogram, drawHistogram(g, LightmapRenderer.histogram,
Terrarum.WIDTH - histogramW - 30, Terrarum.WIDTH - histogramW - 30,
Terrarum.HEIGHT - histogramH - 30 Terrarum.HEIGHT - histogramH - 30
) )
g.color = GameFontBase.codeToCol["y"]
g.drawString("MEM ", (Terrarum.WIDTH - 15 * 8 - 2).toFloat(), 2f)
//g.drawString("FPS ", (Terrarum.WIDTH - 6 * 8 - 2).toFloat(), 10f)
g.drawString("Actors total ", 2f, Terrarum.HEIGHT - 10f)
g.drawString("Active ", (2 + 17*8).toFloat(), Terrarum.HEIGHT - 10f)
g.color = GameFontBase.codeToCol["g"]
g.drawString("${Terrarum.game.memInUse}M",
(Terrarum.WIDTH - 11 * 8 - 2).toFloat(), 2f)
g.drawString("/${Terrarum.game.totalVMMem}M",
(Terrarum.WIDTH - 6 * 8 - 2).toFloat(), 2f)
//g.drawString("${Terrarum.appgc.fps}",
// (Terrarum.WIDTH - 2 * 8 - 2).toFloat(), 10f)
g.drawString("${Terrarum.game.actorContainer.size + Terrarum.game.actorcontainerInactive.size}",
(2 + 13*8).toFloat(), Terrarum.HEIGHT - 10f
)
g.drawString(Terrarum.game.actorContainer.size.toString(),
(2 + 24*8).toFloat(), Terrarum.HEIGHT - 10f
)
} }
private fun printLine(g: Graphics, l: Int, s: String) { private fun printLine(g: Graphics, l: Int, s: String) {
g.drawString(s, 20f, line(l).toFloat()) g.drawString(s, 10f, line(l).toFloat())
} }
private fun printLineColumn(g: Graphics, col: Int, row: Int, s: String) { private fun printLineColumn(g: Graphics, col: Int, row: Int, s: String) {
g.drawString(s, (20 + column(col)).toFloat(), line(row).toFloat()) g.drawString(s, (10 + column(col)).toFloat(), line(row).toFloat())
} }
val histogramW = 256 val histogramW = 256
@@ -196,6 +211,10 @@ class BasicDebugInfoWindow : UICanvas {
g.color = uiColour g.color = uiColour
g.fillRect(x.toFloat(), y.toFloat(), w.plus(1).toFloat(), h.toFloat()) g.fillRect(x.toFloat(), y.toFloat(), w.plus(1).toFloat(), h.toFloat())
g.color = Color.gray
g.drawString("0", x.toFloat(), y.toFloat() + h + 2)
g.drawString("255", x.toFloat() + w + 1 - 8*3, y.toFloat() + h + 2)
g.drawString("Histogramme", x + w / 2 - 5.5f * 8, y.toFloat() + h + 2)
setBlendScreen() setBlendScreen()
for (c in 0..2) { for (c in 0..2) {
@@ -219,9 +238,9 @@ class BasicDebugInfoWindow : UICanvas {
setBlendNormal() setBlendNormal()
} }
private fun line(i: Int): Int = i * 20 private fun line(i: Int): Float = i * 10f
private fun column(i: Int): Int = 250 * (i - 1) private fun column(i: Int): Float = 250f * (i - 1)
override fun doOpening(gc: GameContainer, delta: Int) { override fun doOpening(gc: GameContainer, delta: Int) {

View File

@@ -33,7 +33,10 @@ constructor(val UI: UICanvas) {
private var opening = false private var opening = false
private var closing = false private var closing = false
private var opened = false // fully opened private var opened = false // fully opened
private var visible = false private var _visible = false
val visible: Boolean
get() = if (alwaysVisible) true
else _visible
var openCloseCounter = 0 var openCloseCounter = 0
@@ -48,12 +51,12 @@ constructor(val UI: UICanvas) {
fun update(gc: GameContainer, delta: Int) { fun update(gc: GameContainer, delta: Int) {
if (visible || alwaysVisible) { if (_visible || alwaysVisible) {
UI.update(gc, delta) UI.update(gc, delta)
} }
if (opening) { if (opening) {
visible = true _visible = true
openCloseCounter += delta openCloseCounter += delta
// println("UI ${UI.javaClass.simpleName} (open)") // println("UI ${UI.javaClass.simpleName} (open)")
@@ -84,14 +87,14 @@ constructor(val UI: UICanvas) {
UI.endClosing(gc, delta) UI.endClosing(gc, delta)
closing = false closing = false
opened = false opened = false
visible = false _visible = false
openCloseCounter = 0 openCloseCounter = 0
} }
} }
} }
fun render(gc: GameContainer, gameGraphicInstance: Graphics) { fun render(gc: GameContainer, gameGraphicInstance: Graphics) {
if (visible || alwaysVisible) { if (_visible || alwaysVisible) {
UIGraphicInstance.clear() UIGraphicInstance.clear()
UIGraphicInstance.font = Terrarum.gameFont UIGraphicInstance.font = Terrarum.gameFont
@@ -113,22 +116,12 @@ constructor(val UI: UICanvas) {
if (alwaysVisible) { if (alwaysVisible) {
throw RuntimeException("[UIHandler] Tried to 'set visibility of' constant UI") throw RuntimeException("[UIHandler] Tried to 'set visibility of' constant UI")
} }
visible = b _visible = b
} }
val isVisible: Boolean
get() {
if (alwaysVisible) {
return true
}
else {
return visible
}
}
fun setAsAlwaysVisible() { fun setAsAlwaysVisible() {
alwaysVisible = true alwaysVisible = true
visible = true _visible = true
opened = true opened = true
opening = false opening = false
closing = false closing = false
@@ -155,7 +148,7 @@ constructor(val UI: UICanvas) {
if (alwaysVisible) { if (alwaysVisible) {
throw RuntimeException("[UIHandler] Tried to 'toggle opening of' constant UI") throw RuntimeException("[UIHandler] Tried to 'toggle opening of' constant UI")
} }
if (visible) { if (_visible) {
if (!closing) { if (!closing) {
setAsClosing() setAsClosing()
} }
@@ -168,61 +161,61 @@ constructor(val UI: UICanvas) {
} }
fun processInput(input: Input) { fun processInput(input: Input) {
if (visible) { if (_visible) {
UI.processInput(input) UI.processInput(input)
} }
} }
fun keyPressed(key: Int, c: Char) { fun keyPressed(key: Int, c: Char) {
if (visible && UI is UITypable) { if (_visible && UI is UITypable) {
UI.keyPressed(key, c) UI.keyPressed(key, c)
} }
} }
fun keyReleased(key: Int, c: Char) { fun keyReleased(key: Int, c: Char) {
if (visible && UI is UITypable) { if (_visible && UI is UITypable) {
UI.keyReleased(key, c) UI.keyReleased(key, c)
} }
} }
fun mouseMoved(oldx: Int, oldy: Int, newx: Int, newy: Int) { fun mouseMoved(oldx: Int, oldy: Int, newx: Int, newy: Int) {
if (visible && UI is UIClickable) { if (_visible && UI is UIClickable) {
UI.mouseMoved(oldx, oldy, newx, newy) UI.mouseMoved(oldx, oldy, newx, newy)
} }
} }
fun mouseDragged(oldx: Int, oldy: Int, newx: Int, newy: Int) { fun mouseDragged(oldx: Int, oldy: Int, newx: Int, newy: Int) {
if (visible && UI is UIClickable) { if (_visible && UI is UIClickable) {
UI.mouseDragged(oldx, oldy, newx, newy) UI.mouseDragged(oldx, oldy, newx, newy)
} }
} }
fun mousePressed(button: Int, x: Int, y: Int) { fun mousePressed(button: Int, x: Int, y: Int) {
if (visible && UI is UIClickable) { if (_visible && UI is UIClickable) {
UI.mousePressed(button, x, y) UI.mousePressed(button, x, y)
} }
} }
fun mouseReleased(button: Int, x: Int, y: Int) { fun mouseReleased(button: Int, x: Int, y: Int) {
if (visible && UI is UIClickable) { if (_visible && UI is UIClickable) {
UI.mouseReleased(button, x, y) UI.mouseReleased(button, x, y)
} }
} }
fun mouseWheelMoved(change: Int) { fun mouseWheelMoved(change: Int) {
if (visible && UI is UIClickable) { if (_visible && UI is UIClickable) {
UI.mouseWheelMoved(change) UI.mouseWheelMoved(change)
} }
} }
fun controllerButtonPressed(controller: Int, button: Int) { fun controllerButtonPressed(controller: Int, button: Int) {
if (visible && UI is UIClickable) { if (_visible && UI is UIClickable) {
UI.controllerButtonPressed(controller, button) UI.controllerButtonPressed(controller, button)
} }
} }
fun controllerButtonReleased(controller: Int, button: Int) { fun controllerButtonReleased(controller: Int, button: Int) {
if (visible && UI is UIClickable) { if (_visible && UI is UIClickable) {
UI.controllerButtonReleased(controller, button) UI.controllerButtonReleased(controller, button)
} }
} }
@@ -233,6 +226,6 @@ constructor(val UI: UICanvas) {
if (alwaysVisible) { if (alwaysVisible) {
return false return false
} }
return visible && !opening return _visible && !opening
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 663 B