From 1a1159b64306a63787237fb41bb4b1f7318c2d8e Mon Sep 17 00:00:00 2001 From: Song Minjae Date: Sat, 23 Apr 2016 23:08:42 +0900 Subject: [PATCH] WIP collision solver, colour-codes in game fonts Former-commit-id: 0bb85999176d89956398bbcc24e1b33cacd3e87c Former-commit-id: 0ef0c1ac9b88f8fe42a7439fee69a8d4792be96a --- res/graphics/fonts/.gitattributes | 1 - res/graphics/fonts/Braille.png | Bin 160 -> 143 bytes res/graphics/fonts/LatinExtA_majuscule.png | Bin 2008 -> 1797 bytes res/graphics/fonts/alphanumeric_small.png | Bin 0 -> 1487 bytes res/graphics/fonts/ascii_majuscule.png | Bin 2576 -> 2575 bytes res/graphics/fonts/cyrilic_ef.png | Bin 154 -> 149 bytes res/graphics/fonts/cyrilic_majuscule.png | Bin 1464 -> 1463 bytes res/graphics/fonts/kana.png | Bin 3365 -> 3353 bytes res/graphics/fonts/numeric_small.png | Bin 986 -> 0 bytes res/locales/devmsg.csv | 3 - src/net/torvald/colourutil/Col216.kt | 8 +- src/net/torvald/colourutil/Col4096.kt | 10 +- src/net/torvald/imagefont/GameFontBase.kt | 71 +++++++++-- src/net/torvald/imagefont/GameFontWhite.kt | 2 +- src/net/torvald/imagefont/SmallNumbers.kt | 50 -------- src/net/torvald/imagefont/TinyAlphNum.kt | 78 ++++++++++++ src/net/torvald/terrarum/Game.kt | 113 +++++++++++++----- src/net/torvald/terrarum/Terrarum.kt | 4 +- .../torvald/terrarum/console/Authenticator.kt | 7 +- .../terrarum/console/CommandInterpreter.kt | 8 +- src/net/torvald/terrarum/console/Echo.kt | 5 + src/net/torvald/terrarum/console/GetAV.kt | 54 +++++++-- src/net/torvald/terrarum/console/SetAV.kt | 62 ++++++++-- src/net/torvald/terrarum/gameactors/Actor.kt | 13 +- .../terrarum/gameactors/ActorWithBody.kt | 25 ++-- .../terrarum/gameactors/CollisionSolver.kt | 104 ++++++++++++++++ .../torvald/terrarum/gameactors/Glowing.kt | 13 -- .../terrarum/gameactors/PhysTestBall.kt | 10 +- .../torvald/terrarum/gameactors/Visible.kt | 4 + .../terrarum/ui/BasicDebugInfoWindow.kt | 91 ++++++++------ src/net/torvald/terrarum/ui/UIHandler.kt | 51 ++++---- work_files/graphics/fonts/cjkpunct.png | Bin 638 -> 0 bytes work_files/graphics/fonts/futhark.png | Bin 663 -> 0 bytes 33 files changed, 557 insertions(+), 230 deletions(-) delete mode 100644 res/graphics/fonts/.gitattributes create mode 100644 res/graphics/fonts/alphanumeric_small.png delete mode 100644 res/graphics/fonts/numeric_small.png delete mode 100644 src/net/torvald/imagefont/SmallNumbers.kt create mode 100644 src/net/torvald/imagefont/TinyAlphNum.kt create mode 100644 src/net/torvald/terrarum/gameactors/CollisionSolver.kt delete mode 100644 src/net/torvald/terrarum/gameactors/Glowing.kt delete mode 100644 work_files/graphics/fonts/cjkpunct.png delete mode 100644 work_files/graphics/fonts/futhark.png diff --git a/res/graphics/fonts/.gitattributes b/res/graphics/fonts/.gitattributes deleted file mode 100644 index ca82ef549..000000000 --- a/res/graphics/fonts/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.{psd,tga,ogg} filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/res/graphics/fonts/Braille.png b/res/graphics/fonts/Braille.png index 2fd4ee11ae7ab930ff5f3e3ef79f63e01c64732f..ba603fbbb5bbefaab932943d1eda421ebe00de83 100755 GIT binary patch delta 83 zcmZ3$*v~k@*~i?|#WBRU n-*)lCg4$mR(!TOn`1l!I7Rvujo3mb+0SG)@{an^LB{Ts5Ds&pA delta 100 zcmeBYT);TNIo89|#WAEJ?(QT*E(b#%C+kW-_4oBHY)%Uwe6W|4I>GH&v3N(_0UM3; zuAHCh#9bxklzj9Imv1Q9-?_}r?JaX-(_}TaH;)VDrSDJlY24{o7{~wwp00i_>zopr E0I8!VB>(^b diff --git a/res/graphics/fonts/LatinExtA_majuscule.png b/res/graphics/fonts/LatinExtA_majuscule.png index 0c43d8468d14fecd70c9085df8c39469a046c82b..8ab7ed0020d215d09de2e01bfe8840880787f6e0 100644 GIT binary patch delta 1761 zcmV<71|Ip?4}}hp7zqdi0002g;uR;6AtZkWs!2paRCwC$oPm2l7lapsa5_XGCD_Q&jm3Wi zNmNIXB(~TZNS+oG9;wP z3$H`CiBCEa1L4Ba(@Q%dv5^qB<5_=4g5dVwigCVgiV)6kFiAMKn^)Q1yr}h&`zpJY zpseop`n|8R0Ta3#@@4DKPv}WT2HB>(^f4r4b$3SQ?UEQtB#|s6ryN3PNZLT;bT^Sl zRl5^kTR;eUd0Z$E4B~Y+q^epIdX9LNT~)2o!V5|09m&3^S{5}Eyo@9juT_7Ep3b0Z zS&SEuT&ADMk$B^}T~0nYE+M6@BJ&BYC*G;5mOx3gjO?ALq^er3GVaT(2o4ImlB#Nz z#@(||w%7-Kc2200f0P=XM0*+&<$>$PcnVqeGk{%hHys(WG@<$G>Hmao zOvvlpn-lUn_x6Om&ZTmF>~QQmUTL9{ky7K3G#nS>))Ysef??k znz|p(EWo9jx*rbr-?vbG3WTd3%`T$QAqhOfn1l!i4~6i*pAhxs%x5AY;q?;YZJ~A} z;`xLKj#m=GF(bq=h?p#$MnVw0`Ghhb#tP?435iG{;e0P4@!3{5a|wke5=uQ;3N=#+ zshbd-Bb#f)pj|j+6q%&x>%L;^Ex5m8DcI@o@T4G(SKcb$j2gl8~Ak zJdDj%t}$u8kFQ++1B#kQe2$=jfKj(x*EIQ>IE%?7G$bJiJt2R&m{@hSGZkX_Jply!;{A7|Jhwqz=XCCOK~6 zM?MDeMF-?R$Aok;nVmQqb*W{f%=y3Iwh=!OZ>)0Ekg5L7PG|eYe>eP-L zH#K)*S5;f@zeIoZ`Bc02~ju(GQtW?KsA{J1ekWk(A`~)ZMG{C3xU)?p!6a1q*H%XEe#AKM1TOTOsJ|_H)RiUy<&u_ zsgikxBa%(x^M^^EwjIvyX<-ubU$f;(KIIVRz0M8D zcso{7j{GCxX>EttYrY{Cy6N}k;X3(!lc>gZJy+Tvd7&up>%X&k00000NkvXXu0mjf DUOrkr delta 1974 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 delta 91 zcmV-h0Hptw0h$4jMpQpZL_t(|Ud_v)4FDhv1<^uM@qI^tJvu@Sd)2Znn(##>Ctq^H xLlV@GTIfzOH(rdT)qUW9)aGFj62-~TZaCq^4J>l8(U|}M002ovPDHLkV1k(ZCD#A| diff --git a/res/graphics/fonts/cyrilic_majuscule.png b/res/graphics/fonts/cyrilic_majuscule.png index b586dcdabac921f4905f7c8a357b394808ea4b5c..e284256b979dabcd256470866c0950f6469b103a 100644 GIT binary patch delta 1364 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 X6Xkjb*Q!+T00000NkvXXu0mjfK+27$ diff --git a/res/graphics/fonts/kana.png b/res/graphics/fonts/kana.png index 24cb990e1d20046d9cbc7b47ba223bfa871f86a1..3b70966c117a11fdee0d877616aefd0e959d4174 100644 GIT binary patch delta 3328 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 KMNUMnLSTY-+Df|s delta 3340 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 Wmt&`sL8N~G0000pKHvX;LHX6$MF}&{ zoz#j;dAavhK(g7F3lE`#$-*Nt${N@+Kf`?28ul2u|0!50atDnm{r-UW|zKCQA diff --git a/res/locales/devmsg.csv b/res/locales/devmsg.csv index 03f13b02a..85d1aadbf 100644 --- a/res/locales/devmsg.csv +++ b/res/locales/devmsg.csv @@ -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" -"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_BLUE";;" BLUE";" BLEU";;;;;;;;;;;;;;;"青";;;"청";;;;;;;"  あお";"blár" "DEV_COLOUR_LEGEND_ORANGE";;"ORANGE";"ORANGE";;;;;;;;;;;;;;;"黄";;;"황";;;;;;;"オレンジ";"rauðugulur" diff --git a/src/net/torvald/colourutil/Col216.kt b/src/net/torvald/colourutil/Col216.kt index c92ab8f72..419cca0e0 100644 --- a/src/net/torvald/colourutil/Col216.kt +++ b/src/net/torvald/colourutil/Col216.kt @@ -59,16 +59,16 @@ class Col216 : LimitedColours { private fun assertRaw(i: Int) { if (i >= COLOUR_RANGE_SIZE || i < 0) { - println("i: " + i.toString()) + System.err.println("Illegal colour input: $i") throw IllegalArgumentException() } } 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) { - println("r: " + r.toString()) - println("g: " + g.toString()) - println("b: " + b.toString()) + System.err.println("Illegal colour input for channel r: $r") + System.err.println("Illegal colour input for channel g: $g") + System.err.println("Illegal colour input for channel b: $b") throw IllegalArgumentException() } } diff --git a/src/net/torvald/colourutil/Col4096.kt b/src/net/torvald/colourutil/Col4096.kt index 19afce6bf..a6a74bc44 100644 --- a/src/net/torvald/colourutil/Col4096.kt +++ b/src/net/torvald/colourutil/Col4096.kt @@ -111,17 +111,17 @@ class Col4096 : LimitedColours { private fun assertRaw(i: Int) { if (i > 0xFFFF || i < 0) { - println("i: " + i.toString()) + System.err.println("Illegal colour input: $i") throw IllegalArgumentException() } } 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) { - println("a: " + a.toString()) - println("r: " + r.toString()) - println("g: " + g.toString()) - println("b: " + b.toString()) + System.err.println("Illegal colour input for channel a: $a") + System.err.println("Illegal colour input for channel r: $r") + System.err.println("Illegal colour input for channel g: $g") + System.err.println("Illegal colour input for channel b: $b") throw IllegalArgumentException() } } diff --git a/src/net/torvald/imagefont/GameFontBase.kt b/src/net/torvald/imagefont/GameFontBase.kt index eb92cb2f4..1b6b0a627 100644 --- a/src/net/torvald/imagefont/GameFontBase.kt +++ b/src/net/torvald/imagefont/GameFontBase.kt @@ -53,7 +53,7 @@ constructor() : Font { 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) @@ -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 else if (c == SHEET_KANA || c == SHEET_HANGUL || c == SHEET_CJK_PUNCT) len += W_CJK @@ -163,12 +165,19 @@ constructor() : Font { GL11.glColorMask(true, true, true, true) GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA) + var thisCol = color + // hangul fonts first //hangulSheet.startUse() // disabling texture binding to make the font coloured // JOHAB for (i in 0..s.length - 1) { val ch = s[i] + if (ch.isColourCode()) { + thisCol = colourKey[ch]!! + continue + } + if (isHangul(ch)) { val hIndex = ch.toInt() - 0xAC00 @@ -204,17 +213,17 @@ constructor() : Font { hangulSheet.getSubImage(indexCho, choRow).draw( Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f).toFloat(), - color + thisCol ) hangulSheet.getSubImage(indexJung, jungRow).draw( Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f).toFloat(), - color + thisCol ) hangulSheet.getSubImage(indexJong, jongRow).draw( Math.round(x + getWidthSubstr(s, i + 1) - glyphW).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) { val ch = s[i] + if (ch.isColourCode()) { + thisCol = colourKey[ch]!! + continue + } + if (isWenQuanYi1(ch)) { val glyphW = getWidth("" + ch) /*wenQuanYi_1.renderInUse( @@ -257,7 +271,7 @@ constructor() : Font { wenQuanYi_1.getSubImage(wenQuanYiIndexX(ch), wenQuanYi1IndexY(ch)).draw( Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round((H - H_UNIHAN) / 2 + y).toFloat(), - color + thisCol ) } } @@ -269,6 +283,11 @@ constructor() : Font { for (i in 0..s.length - 1) { val ch = s[i] + if (ch.isColourCode()) { + thisCol = colourKey[ch]!! + continue + } + if (isWenQuanYi2(ch)) { val glyphW = getWidth("" + ch) /*wenQuanYi_2.renderInUse( @@ -280,7 +299,7 @@ constructor() : Font { wenQuanYi_2.getSubImage(wenQuanYiIndexX(ch), wenQuanYi2IndexY(ch)).draw( Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), Math.round((H - H_UNIHAN) / 2 + y).toFloat(), - color + thisCol ) } } @@ -292,6 +311,11 @@ constructor() : Font { for (i in 0..s.length - 1) { val ch = s[i] + if (ch.isColourCode()) { + thisCol = colourKey[ch]!! + continue + } + if (!isHangul(ch) && !isUniHan(ch)) { // if not init, endUse first @@ -369,7 +393,7 @@ constructor() : Font { else if (prevInstance == SHEET_FW_UNI) (H - H_HANGUL) / 2 else 0).toFloat(), - color + thisCol ) } catch (e: ArrayIndexOutOfBoundsException) { @@ -413,6 +437,8 @@ constructor() : Font { return SHEET_CJK_PUNCT else if (isFullwidthUni(c)) return SHEET_FW_UNI + else if (c.isColourCode()) + return SHEET_COLOURCODE else return SHEET_ASCII_EM// fixed width punctuations // fixed width @@ -464,6 +490,8 @@ constructor() : Font { Terrarum.appgc.graphics.setDrawMode(Graphics.MODE_NORMAL) } + fun Char.isColourCode() = colourKey.containsKey(this) + companion object { lateinit internal var hangulSheet: SpriteSheet @@ -510,6 +538,8 @@ constructor() : Font { internal val SHEET_WENQUANYI_1 = 13 internal val SHEET_WENQUANYI_2 = 14 + internal val SHEET_COLOURCODE = 255 + lateinit internal var sheetKey: Array internal val asciiEFList = arrayOf(' ', '!', '"', '\'', '(', ')', ',', '.', ':', ';', 'I', '[', ']', '`', 'f', 'i', 'j', 'l', 't', '{', '|', '}', 0xA1.toChar(), 'Ì', 'Í', 'Î', 'Ï', 'ì', 'í', 'î', 'ï', '·') @@ -554,5 +584,30 @@ constructor() : Font { internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', 'ᛁ', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '᛬', '᛫', '᛭', 'ᛮ', 'ᛯ', 'ᛰ') 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()]) + ) } } diff --git a/src/net/torvald/imagefont/GameFontWhite.kt b/src/net/torvald/imagefont/GameFontWhite.kt index e756b6337..0edee3336 100644 --- a/src/net/torvald/imagefont/GameFontWhite.kt +++ b/src/net/torvald/imagefont/GameFontWhite.kt @@ -47,7 +47,7 @@ constructor() : GameFontBase() { GameFontBase.wenQuanYi_2 = SpriteSheet( "./res/graphics/fonts/wenquanyi_11pt_part2.png", 16, 18, 2) - val shk = arrayOf( + val shk = arrayOf( GameFontBase.asciiSheet, GameFontBase.asciiSheetEF, GameFontBase.hangulSheet, diff --git a/src/net/torvald/imagefont/SmallNumbers.kt b/src/net/torvald/imagefont/SmallNumbers.kt deleted file mode 100644 index a38c038e6..000000000 --- a/src/net/torvald/imagefont/SmallNumbers.kt +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/src/net/torvald/imagefont/TinyAlphNum.kt b/src/net/torvald/imagefont/TinyAlphNum.kt new file mode 100644 index 000000000..44f9d83de --- /dev/null +++ b/src/net/torvald/imagefont/TinyAlphNum.kt @@ -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() + + 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) +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/Game.kt b/src/net/torvald/terrarum/Game.kt index 2ec5983ce..884c7a911 100644 --- a/src/net/torvald/terrarum/Game.kt +++ b/src/net/torvald/terrarum/Game.kt @@ -34,11 +34,17 @@ import java.util.* */ class Game @Throws(SlickException::class) constructor() : BasicGameState() { + private val ACTOR_UPDATE_RANGE = 4096 + internal var game_mode = 0 lateinit var map: GameMap - val actorContainer = LinkedList() + /** + * Linked list of Actors that is sorted by Actors' referenceID + */ + val actorContainer = ArrayList(128) + val actorcontainerInactive = ArrayList(128) val uiContainer = LinkedList() lateinit var consoleHandler: UIHandler @@ -128,7 +134,6 @@ constructor() : BasicGameState() { update_delta = delta setAppTitle() - // GL at after_sunrise-noon_before_sunset map.updateWorldTime(delta) map.globalLight = globalLightByTime @@ -139,12 +144,19 @@ constructor() : BasicGameState() { MapDrawer.update(gc, delta) MapCamera.update(gc, delta) - actorContainer.forEach { actor -> actor.update(gc, delta) } - actorContainer.forEach { actor -> - if (actor is Visible) { + actorContainer.forEach { actor -> // update actors + 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) - } - if (actor is Glowing) { actor.updateGlowSprite(gc, delta) } } @@ -186,7 +198,14 @@ constructor() : BasicGameState() { MapCamera.renderBehind(gc, g) // 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) LightmapRenderer.renderLightMap() @@ -204,12 +223,19 @@ constructor() : BasicGameState() { setBlendNormal() // 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) // draw reference ID if debugWindow is open - if (debugWindow.isVisible) { - actorContainer.forEach { actor -> + if (debugWindow.visible) { + actorContainer.forEachIndexed { i, actor -> if (actor is Visible) { g.color = Color.white g.font = Terrarum.smallNumbers @@ -218,6 +244,12 @@ constructor() : BasicGameState() { actor.hitbox.posX, actor.hitbox.pointedY + 4 ) + g.color = Color(0x80FF80) + g.drawString( + i.toString(), + actor.hitbox.posX, + actor.hitbox.pointedY + 12 + ) g.font = Terrarum.gameFont } } @@ -304,40 +336,67 @@ constructor() : BasicGameState() { (this and 0xff00).ushr(8).shl(10) or (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 */ - fun hasActor(ID: Int): Boolean { - for (actor in actorContainer) { - if (actor.referenceID == ID) return true - } - return false - } + fun hasActor(ID: Int): Boolean = + if (actorContainer.size == 0) + false + else + actorContainer.binarySearch(ID) >= 0 + /** + * Remove actor and sort the list + */ fun removeActor(ID: Int) { for (actor in actorContainer) { - if (actor.referenceID == ID) + if (actor.referenceID == ID) { actorContainer.remove(actor) + actorContainer.sort() + break + } } } + /** + * Add actor and sort the list + */ fun addActor(other: Actor): Boolean { if (hasActor(other.referenceID)) return false actorContainer.add(other) + actorContainer.sort() return true } fun getActor(ID: Int): Actor { - for (actor in actorContainer) { - if (actor.referenceID == ID) - return actor - } - throw NullPointerException("Actor with ID $ID does not exist.") + if (actorContainer.size == 0) throw IllegalArgumentException("Actor with ID $ID does not exist.") + + val index = actorContainer.binarySearch(ID) + if (index < 0) + throw IllegalArgumentException("Actor with ID $ID does not exist.") + else + return actorContainer[index] } - fun addUI(other: UIHandler): Boolean { - if (uiContainer.contains(other)) return false - uiContainer.add(other) - return true + private fun ArrayList.binarySearch(ID: Int): Int { + var low = 0 + var high = actorContainer.size - 1 + + 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 } } diff --git a/src/net/torvald/terrarum/Terrarum.kt b/src/net/torvald/terrarum/Terrarum.kt index a7f847b2c..be53c4e9e 100644 --- a/src/net/torvald/terrarum/Terrarum.kt +++ b/src/net/torvald/terrarum/Terrarum.kt @@ -3,7 +3,7 @@ package net.torvald.terrarum import net.torvald.imagefont.GameFontWhite import net.torvald.JsonFetcher import net.torvald.JsonWriter -import net.torvald.imagefont.SmallNumbers +import net.torvald.imagefont.TinyAlphNum import org.lwjgl.input.Controllers import org.lwjgl.opengl.GL11 import org.newdawn.slick.* @@ -47,7 +47,7 @@ constructor(gamename: String) : StateBasedGame(gamename) { @Throws(SlickException::class) override fun initStatesList(gc: GameContainer) { gameFont = GameFontWhite() - smallNumbers = SmallNumbers() + smallNumbers = TinyAlphNum() hasController = gc.input.controllerCount > 0 if (hasController) { diff --git a/src/net/torvald/terrarum/console/Authenticator.kt b/src/net/torvald/terrarum/console/Authenticator.kt index de59f0f2f..fb272f874 100644 --- a/src/net/torvald/terrarum/console/Authenticator.kt +++ b/src/net/torvald/terrarum/console/Authenticator.kt @@ -9,6 +9,8 @@ import org.apache.commons.codec.digest.DigestUtils */ class Authenticator : ConsoleCommand { + private var a = false + override fun execute(args: Array) { if (args.size == 2) { val pwd = args[1] @@ -38,9 +40,4 @@ class Authenticator : ConsoleCommand { override fun printUsage() { CommandInterpreter.echoUnknownCmd("auth") } - - companion object { - - private var a = false - } } diff --git a/src/net/torvald/terrarum/console/CommandInterpreter.kt b/src/net/torvald/terrarum/console/CommandInterpreter.kt index 8230c595f..e0c777301 100644 --- a/src/net/torvald/terrarum/console/CommandInterpreter.kt +++ b/src/net/torvald/terrarum/console/CommandInterpreter.kt @@ -48,9 +48,9 @@ object CommandInterpreter { } } catch (e: Exception) { - println("[CommandInterpreter] :") + System.err.print("[CommandInterpreter] ") 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 formatter = Formatter(sb) - Echo().execute( - formatter.format(Lang.get("DEV_MESSAGE_CONSOLE_COMMAND_UNKNOWN"), cmdname).toString()) + Echo().error( + formatter.format(Lang["DEV_MESSAGE_CONSOLE_COMMAND_UNKNOWN"], cmdname).toString()) } private class CommandInput(o: Array) { diff --git a/src/net/torvald/terrarum/console/Echo.kt b/src/net/torvald/terrarum/console/Echo.kt index 1adfff981..c91c0b0eb 100644 --- a/src/net/torvald/terrarum/console/Echo.kt +++ b/src/net/torvald/terrarum/console/Echo.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.console +import net.torvald.imagefont.GameFontBase import net.torvald.terrarum.Terrarum import net.torvald.terrarum.ui.ConsoleWindow @@ -20,6 +21,10 @@ internal class Echo : ConsoleCommand { (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() { } diff --git a/src/net/torvald/terrarum/console/GetAV.kt b/src/net/torvald/terrarum/console/GetAV.kt index 0b2845c97..88e207bd4 100644 --- a/src/net/torvald/terrarum/console/GetAV.kt +++ b/src/net/torvald/terrarum/console/GetAV.kt @@ -17,37 +17,73 @@ class GetAV : ConsoleCommand { val av = Terrarum.game.player.actorValue val keyset = av.keySet + echo.execute("== ActorValue list for player ==") keyset.forEach { elem -> echo.execute("$elem = ${av[elem as String]}") } - } else if (args.size != 3 && args.size != 2) { printUsage() } else if (args.size == 2) { - echo.execute("player." + args[1] + " = " - + Terrarum.game.player.actorValue[args[1]] - + " (" - + Terrarum.game.player.actorValue[args[1]]!!.javaClass.simpleName - + ")") + // check if args[1] is number or not + if (!args[1].isNum()) { // args[1] is ActorValue name + echo.execute("player.${args[1]} = " + + 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) { - + 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) { 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) { - echo.execute(args[2] + ": actor value does not exist.") + echo.error(args[2] + ": actor value does not exist.") } else { 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() { val echo = Echo() echo.execute("Get desired actor value of specific target.") diff --git a/src/net/torvald/terrarum/console/SetAV.kt b/src/net/torvald/terrarum/console/SetAV.kt index 7b6d81a35..4464a169d 100644 --- a/src/net/torvald/terrarum/console/SetAV.kt +++ b/src/net/torvald/terrarum/console/SetAV.kt @@ -19,43 +19,81 @@ internal class SetAV : ConsoleCommand { } override fun execute(args: Array) { - val echo = Echo() - // setav - if (args.size != 4 && args.size != 3) { - printUsage() - } - else if (args.size == 3) { + fun parseAVInput(arg: String): Any { val `val`: Any try { - `val` = Integer(args[2]) // try for integer + `val` = Integer(arg) // try for integer } catch (e: NumberFormatException) { try { - `val` = args[2].toFloat() // try for float + `val` = arg.toFloat() // try for float } catch (ee: NumberFormatException) { - if (args[2].equals("__true", ignoreCase = true)) { + if (arg.equals("__true", ignoreCase = true)) { `val` = true } - else if (args[2].equals("__false", ignoreCase = true)) { + else if (arg.equals("__false", ignoreCase = true)) { `val` = false } else { - `val` = args[2] // string if not number + `val` = arg // string if not number } } + } + return `val` + } + + val echo = Echo() + + // setav + 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` - echo.execute("Set " + args[1] + " to " + `val`) + echo.execute("Set ${args[1]} to $`val`") } 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 + } + } } diff --git a/src/net/torvald/terrarum/gameactors/Actor.kt b/src/net/torvald/terrarum/gameactors/Actor.kt index 61be521b1..53cc60cf6 100644 --- a/src/net/torvald/terrarum/gameactors/Actor.kt +++ b/src/net/torvald/terrarum/gameactors/Actor.kt @@ -5,15 +5,20 @@ import org.newdawn.slick.GameContainer /** * Created by minjaesong on 16-03-14. */ -interface Actor { +abstract class Actor : Comparable { - fun update(gc: GameContainer, delta_t: Int) + abstract fun update(gc: GameContainer, delta_t: Int) /** * Valid RefID is equal to or greater than 32768. * @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 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt index 5ead41124..da3cb25c0 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt @@ -16,7 +16,7 @@ import org.newdawn.slick.Graphics * * 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() @@ -26,15 +26,13 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing { var baseHitboxH: Int = 0 /** - * Velocity for newtonian sim. - * Fluctuation in, otherwise still, velocity is equal to acceleration. - + * Velocity vector (broken down by axes) for newtonian sim. * Acceleration: used in code like: * veloY += 3.0 * +3.0 is acceleration. You __accumulate__ acceleration to the velocity. */ - @Volatile var veloX: Float = 0.toFloat() - @Volatile var veloY: Float = 0.toFloat() + var veloX: Float = 0.toFloat() + var veloY: Float = 0.toFloat() @Transient private val VELO_HARD_LIMIT = 10000f var grounded = false @@ -61,16 +59,17 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing { @Transient val nextHitbox = Hitbox(0f,0f,0f,0f) /** - * Physical properties + * Physical properties. + * Values derived from ActorValue must be @Transient. */ - @Volatile @Transient var scale = 1f - @Volatile @Transient var mass = 2f + @Transient var scale = 1f + @Transient var mass = 2f @Transient private val MASS_LOWEST = 2f /** Valid range: [0, 1] */ var elasticity = 0f set(value) { 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) { println("[ActorWithBody] Elasticity were capped to 1.") field = ELASTICITY_MAX @@ -89,11 +88,11 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing { */ @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()) /** - * [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 @@ -131,6 +130,8 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing { @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 posAdjustY = 0 diff --git a/src/net/torvald/terrarum/gameactors/CollisionSolver.kt b/src/net/torvald/terrarum/gameactors/CollisionSolver.kt new file mode 100644 index 000000000..e21cf218e --- /dev/null +++ b/src/net/torvald/terrarum/gameactors/CollisionSolver.kt @@ -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(COLL_LIST_SIZE) + private val collListY = ArrayList(COLL_LIST_SIZE) + + private val collCandidateX = ArrayList>(COLL_CANDIDATES_SIZE) + private val collCandidateY = ArrayList>(COLL_CANDIDATES_SIZE) + private val collCandidates = ArrayList>(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 + */ +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/Glowing.kt b/src/net/torvald/terrarum/gameactors/Glowing.kt deleted file mode 100644 index ca86c3f47..000000000 --- a/src/net/torvald/terrarum/gameactors/Glowing.kt +++ /dev/null @@ -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) -} \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/PhysTestBall.kt b/src/net/torvald/terrarum/gameactors/PhysTestBall.kt index 85f589f09..135aa62a1 100644 --- a/src/net/torvald/terrarum/gameactors/PhysTestBall.kt +++ b/src/net/torvald/terrarum/gameactors/PhysTestBall.kt @@ -15,7 +15,7 @@ class PhysTestBall : ActorWithBody { constructor(): super() { setHitboxDimension(16, 16, 0, 0) isVisible = true - mass = 10f + actorValue[AVKey.BASEMASS] = 10f color = RoguelikeRandomiser.composeColourFrom(RoguelikeRandomiser.POTION_PRIMARY_COLSET) } @@ -23,9 +23,9 @@ class PhysTestBall : ActorWithBody { override fun drawBody(gc: GameContainer, g: Graphics) { g.color = color g.fillOval( - hitbox!!.posX, - hitbox!!.posY, - hitbox!!.width, - hitbox!!.height) + hitbox.posX, + hitbox.posY, + hitbox.width, + hitbox.height) } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/Visible.kt b/src/net/torvald/terrarum/gameactors/Visible.kt index 872f52771..bf176477e 100644 --- a/src/net/torvald/terrarum/gameactors/Visible.kt +++ b/src/net/torvald/terrarum/gameactors/Visible.kt @@ -12,4 +12,8 @@ interface Visible { fun drawBody(gc: GameContainer, g: Graphics) fun updateBodySprite(gc: GameContainer, delta: Int) + + fun drawGlow(gc: GameContainer, g: Graphics) + + fun updateGlowSprite(gc: GameContainer, delta: Int) } diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 507c70dd7..54ad49e12 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -1,6 +1,7 @@ package net.torvald.terrarum.ui import com.jme3.math.FastMath +import net.torvald.imagefont.GameFontBase import net.torvald.terrarum.gamemap.PairedMapLayer import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.mapdrawer.LightmapRenderer @@ -18,7 +19,7 @@ import java.util.* /** * Created by minjaesong on 16-03-14. */ -class BasicDebugInfoWindow : UICanvas { +class BasicDebugInfoWindow:UICanvas { override var width: Int = Terrarum.WIDTH 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 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 nextHitbox = player.nextHitbox - printLine(g, 1, "posX: " + val ccG = "${GameFontBase.colToCode["g"]}" + + printLine(g, 1, "posX " + + ccG + "${hitbox.pointedX.toString()}" + " (" + "${(hitbox.pointedX / MapDrawer.TILE_SIZE).toInt().toString()}" + ")") - printLine(g, 2, "posY: " + printLine(g, 2, "posY " + + ccG + hitbox.pointedY.toString() + " (" + (hitbox.pointedY / MapDrawer.TILE_SIZE).toInt().toString() + ")") - printLine(g, 3, "veloX reported: ${player.veloX}") - printLine(g, 4, "veloY reported: ${player.veloY}") + printLine(g, 3, "veloX reported $ccG${player.veloX}") + printLine(g, 4, "veloY reported $ccG${player.veloY}") - printLineColumn(g, 2, 3, "veloX measured: ${xdelta}") - printLineColumn(g, 2, 4, "veloY measured: ${ydelta}") + printLineColumn(g, 2, 3, "veloX measured $ccG${xdelta}") + printLineColumn(g, 2, 4, "veloY measured $ccG${ydelta}") - printLine(g, 5, "grounded : ${player.grounded}") - printLine(g, 6, "noClip : ${player.noClip}") + printLine(g, 5, "grounded $ccG${player.grounded}") + printLine(g, 6, "noClip $ccG${player.noClip}") val lightVal: String var mtX = mouseTileX.toString() @@ -100,7 +106,7 @@ class BasicDebugInfoWindow : UICanvas { rawB.toString() + ")" - printLine(g, 7, "light at cursor : " + lightVal) + printLine(g, 7, "light@cursor $ccG$lightVal") val tileNo: String val tileNumRaw = Terrarum.game.map.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1 @@ -108,33 +114,22 @@ class BasicDebugInfoWindow : UICanvas { val tiledmg = tileNumRaw % PairedMapLayer.RANGE 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 */ - printLineColumn(g, 2, 1, "${Lang["MENU_OPTIONS_VSYNC"]} : " + Terrarum.appgc.isVSyncRequested) - printLineColumn(g, 2, 2, "Env colour temp : " + MapDrawer.getColTemp()) - printLineColumn(g, 2, 5, "Time : ${Terrarum.game.map.worldTime.elapsedSeconds()}" + + printLineColumn(g, 2, 1, "VSync $ccG" + Terrarum.appgc.isVSyncRequested) + printLineColumn(g, 2, 2, "Env colour temp $ccG" + MapDrawer.getColTemp()) + printLineColumn(g, 2, 5, "Time $ccG${Terrarum.game.map.worldTime.elapsedSeconds()}" + " (${Terrarum.game.map.worldTime.getFormattedTime()})") - printLineColumn(g, 2, 6, "Mass : ${player.mass}") + printLineColumn(g, 2, 6, "Mass $ccG${player.mass}") /** * 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 val zoom = Terrarum.game.screenZoom g.color = Color(0x007f00) @@ -148,12 +143,12 @@ class BasicDebugInfoWindow : UICanvas { , (hitbox.pointedY - 1) * zoom - MapCamera.cameraY * zoom , 3f, 3f) g.drawString( - Lang["DEV_COLOUR_LEGEND_GREEN"] + " : hitbox", (Terrarum.WIDTH - 200).toFloat() - , line(2).toFloat()) + "hitbox", (Terrarum.WIDTH - 15 * 8 - 2).toFloat().toFloat() + , line(1)) // Next hitbox 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.width * zoom , nextHitbox.height * zoom) @@ -163,21 +158,41 @@ class BasicDebugInfoWindow : UICanvas { , (nextHitbox.pointedY - 1) * zoom - MapCamera.cameraY * zoom , 3f, 3f) g.drawString( - Lang["DEV_COLOUR_LEGEND_BLUE"] + " : nextHitbox", (Terrarum.WIDTH - 200).toFloat() - , line(3).toFloat()) + "nextHitbox", (Terrarum.WIDTH - 15 * 8 - 2).toFloat().toFloat() + , line(2)) drawHistogram(g, LightmapRenderer.histogram, Terrarum.WIDTH - histogramW - 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) { - 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) { - g.drawString(s, (20 + column(col)).toFloat(), line(row).toFloat()) + g.drawString(s, (10 + column(col)).toFloat(), line(row).toFloat()) } val histogramW = 256 @@ -196,6 +211,10 @@ class BasicDebugInfoWindow : UICanvas { g.color = uiColour 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() for (c in 0..2) { @@ -219,9 +238,9 @@ class BasicDebugInfoWindow : UICanvas { 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) { diff --git a/src/net/torvald/terrarum/ui/UIHandler.kt b/src/net/torvald/terrarum/ui/UIHandler.kt index 0c701fedf..f1eb4b51f 100644 --- a/src/net/torvald/terrarum/ui/UIHandler.kt +++ b/src/net/torvald/terrarum/ui/UIHandler.kt @@ -33,7 +33,10 @@ constructor(val UI: UICanvas) { private var opening = false private var closing = false 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 @@ -48,12 +51,12 @@ constructor(val UI: UICanvas) { fun update(gc: GameContainer, delta: Int) { - if (visible || alwaysVisible) { + if (_visible || alwaysVisible) { UI.update(gc, delta) } if (opening) { - visible = true + _visible = true openCloseCounter += delta // println("UI ${UI.javaClass.simpleName} (open)") @@ -84,14 +87,14 @@ constructor(val UI: UICanvas) { UI.endClosing(gc, delta) closing = false opened = false - visible = false + _visible = false openCloseCounter = 0 } } } fun render(gc: GameContainer, gameGraphicInstance: Graphics) { - if (visible || alwaysVisible) { + if (_visible || alwaysVisible) { UIGraphicInstance.clear() UIGraphicInstance.font = Terrarum.gameFont @@ -113,22 +116,12 @@ constructor(val UI: UICanvas) { if (alwaysVisible) { 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() { alwaysVisible = true - visible = true + _visible = true opened = true opening = false closing = false @@ -155,7 +148,7 @@ constructor(val UI: UICanvas) { if (alwaysVisible) { throw RuntimeException("[UIHandler] Tried to 'toggle opening of' constant UI") } - if (visible) { + if (_visible) { if (!closing) { setAsClosing() } @@ -168,61 +161,61 @@ constructor(val UI: UICanvas) { } fun processInput(input: Input) { - if (visible) { + if (_visible) { UI.processInput(input) } } fun keyPressed(key: Int, c: Char) { - if (visible && UI is UITypable) { + if (_visible && UI is UITypable) { UI.keyPressed(key, c) } } fun keyReleased(key: Int, c: Char) { - if (visible && UI is UITypable) { + if (_visible && UI is UITypable) { UI.keyReleased(key, c) } } 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) } } 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) } } fun mousePressed(button: Int, x: Int, y: Int) { - if (visible && UI is UIClickable) { + if (_visible && UI is UIClickable) { UI.mousePressed(button, x, y) } } fun mouseReleased(button: Int, x: Int, y: Int) { - if (visible && UI is UIClickable) { + if (_visible && UI is UIClickable) { UI.mouseReleased(button, x, y) } } fun mouseWheelMoved(change: Int) { - if (visible && UI is UIClickable) { + if (_visible && UI is UIClickable) { UI.mouseWheelMoved(change) } } fun controllerButtonPressed(controller: Int, button: Int) { - if (visible && UI is UIClickable) { + if (_visible && UI is UIClickable) { UI.controllerButtonPressed(controller, button) } } fun controllerButtonReleased(controller: Int, button: Int) { - if (visible && UI is UIClickable) { + if (_visible && UI is UIClickable) { UI.controllerButtonReleased(controller, button) } } @@ -233,6 +226,6 @@ constructor(val UI: UICanvas) { if (alwaysVisible) { return false } - return visible && !opening + return _visible && !opening } } diff --git a/work_files/graphics/fonts/cjkpunct.png b/work_files/graphics/fonts/cjkpunct.png deleted file mode 100644 index 63d96957116ad67681277e325ee42ec106a3ed27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 638 zcmeAS@N?(olHy`uVBq!ia0vp^3xGI)gAGW|i>)(ZU|@3fba4!+xb^mSV_%bjh)dxA zTj$f8J2USHu~i(@lAAQUG;;>SUb_ubZkzZXFsS>-($Juw;NT!2pl)#Y{r8o>W6rEd z->#ZJz4+hrzq=axCp#RN^K(f>jXy_(=!VEj5y7Gb8GRG;*bM=(+VOz z=H6Yuy1ZyK*v~Ro1^ltC{Jxgl1 za~G~k{n_NQl+RDH`coU{jL++I6DH&bt}7^7)wK1S!iSBormt3DwBM-pP4?;v?isA7 zo6=TpTEima@uK6xJe4d-y@PN6^)>jLoe;g%+|rtR_}jyXqI>7w>}t?WZ)<3MCAzt3 z$9xMO<2r@?y38y*?1o;4bOQcO6aThwir^=wZxW30=c8i}%-z4?n775_z?g?W3tICu zxppKK?cv{T_tX1=-F0KGo2_2)C!^2VuH7_&e_3*40|TR@Lqo$4F~;8;XK(l?ef;L9 zh|v8%Qvc^M{?>f(y!=>$=KGhPhj|#?IcMBDHX)rue&vGf|H2=7ncDc|6cQ>ArHgG? zzk)?ZHzDi)mF@S+xMu7t&^yRt<9$F!oRQPRfk|jW1B;3RqrT>YSqaA&dzt0x-(Iv( zVAQ^H-|F;|LVKnvu{)DnKI;6izF{+c|JwIEdY8UEez11dG>_bh1S_#K>?|A{OiU~+ ujEqc8P`5&&RY8G+LqGtJ1QvZ8&dKk{Q!1Wss9^_8R}7x6elF{r5}E)-6%ecd diff --git a/work_files/graphics/fonts/futhark.png b/work_files/graphics/fonts/futhark.png deleted file mode 100644 index 16009a5b4a2bd20158191a6696bbc64464eed66c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 663 zcmV;I0%-k-P)7b8VnB3i4!2*>pV}(8rJp!undr8fGh)KZ4J<`@@ z2fYf;mHsl&eSl=0g@4r+a2^R(8tQK1DttDFFn|LufNXoi6W5u72tc<13cHIx%<9S> z&Z7Z=7~Oy|22f=P=w^=i4m~y5Q_z%3p!Mf@(idf##w5Bte9xFfXD2$l3}p_{<8uIV zaPYjKDjcJYia-dM*%wcuR{~T|-2f0~2)OV@?<~xLpkXS0FUJsM5X)LQ`t1XB*Qt8| zi3(%p;2vMkc2YUGi|^EUXzP?u0!Vhk20)?=8;N^7!PSTZn(C8YSWXEfMvoAxm2B0aB zL4(8EAXu)d0W?IP0FY=XP=Dwttoc>&8KSuW^;12As6YIRh5kg_^PvdC68)(F x_1E)GRn(`jRu}E9xBN2I@_#6^43M>}egK(jL=AtR*_i+U002ovPDHLkV1mD;C%*sy