Greek support, modular weather, command history for console window
Former-commit-id: b72d0b018c084e80cf4fef77e1b1a81101d6daea Former-commit-id: 32da6a2998826de6519a901dcff7bf058f689b2f
29
res/books/polyglot_test_2.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
"APP_WARNING_HEALTH_AND_SAFETY": ""
|
||||
|
||||
bgBG ВНИМАНИЕ-ЗДРАВЕ И БЕЗОПАСНОСТ
|
||||
csCZ POZOR-ZDRAVÍ A BEZPEČNOST
|
||||
daDK ADVARSEL-SUNDHED OG SIKKERHED
|
||||
de WARNUNG-GESUNDHEIT UND SICHERHEIT
|
||||
elGR ΠΡΟΣΟΧΗ-ΥΓΕΙΑ ΚΑΙ ΑΣΦΑΛΕΙΑ
|
||||
en WARNING-HEALTH AND SAFETY
|
||||
es ADVERTENCIA-SALUD Y SEGURIDAD
|
||||
fiFI VAROITUS-TERVEYS JA TURVALLISUUS
|
||||
fr ATTENTION-SANTÉ ET SÉCURITÉ
|
||||
huHU VIGYÁZAT-EGÉSZSÉGÜGYI ÉS BIZTONSÁGI
|
||||
isIC VIÐVÖRUN-HEILSA OG ÖRYGGI
|
||||
it ATTENZIONE-SALUTE E SICUREZZA
|
||||
jaJP 警告ー健康と安全のために
|
||||
jakana けいこくーけんこうと あんぜんの ために
|
||||
koKR 경고—건강과 안전을 위하여
|
||||
nlNL WAARSCHUWING-GEZONDHEID EN VEILIGHEID
|
||||
noNB ADVARSEL-HELSE OG SIKKERHET
|
||||
plPL UWAGA-ZDROWIE I BEZPIECZEŃSTWO
|
||||
ptBR ATENÇÃO-SAÚDE E SEGURANÇA
|
||||
ptPT ATENÇÃO-SAÚDE E SEGURANÇA
|
||||
roRO ATENȚIONARE-SĂNĂTATE ȘI SIGURANȚĂ
|
||||
ruRU ПРЕДУПРЕЖДЕНИЕ-ЗДОРОВЬЕ И БЕЗОПАСНОСТЬ
|
||||
svSE VARNING-HÄLSA OCH SÄKERHET
|
||||
thTH คำเตือน-อนามัยและความปลอดภัย
|
||||
trTR UYARI-SAĞLIK VE GÜVENLİK
|
||||
zhCN 警告ー健康和安全
|
||||
zhTW 警告ー健康和安全
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
res/graphics/fonts/greek_ef.png
Normal file
|
After Width: | Height: | Size: 934 B |
BIN
res/graphics/fonts/greek_majuscule.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
res/graphics/weathers/generic_light.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
res/graphics/weathers/generic_skybox.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
@@ -4,6 +4,6 @@
|
||||
"COPYRIGHT_ALL_RIGHTS_RESERVED": "ぜんちょさくけん しょゆう。",
|
||||
"APP_ADJUST_YOUR_MONITOR": "このゲームは、てきせつにちょうせいした モニターから さいこうのプレイができます。ちょうせいして いなかったら、プレイするまえに ちょうせいしてください。",
|
||||
|
||||
"APP_WARNING_HEALTH_AND_SAFETY": "けいこくーけんこうと あんぜんを ために"
|
||||
"APP_WARNING_HEALTH_AND_SAFETY": "けいこくーけんこうと あんぜんの ために"
|
||||
|
||||
}
|
||||
46
res/raw/Creature_raw_doc.md
Normal file
@@ -0,0 +1,46 @@
|
||||
Creature raw documentation
|
||||
|
||||
## Physical properties ##
|
||||
|
||||
* 1 m = 24 px
|
||||
* mult: Multiplier. e.g. 1.0, 0.85, 1.25, ...
|
||||
|
||||
|name|unit|description|
|
||||
|----|----|-----------|
|
||||
|baseheight|pixels|Base height for hitbox. Also used for attack point bonus calculation|
|
||||
|basemass|kg|Base mass for creature|
|
||||
|accel|px per TARGET_FPS^2|Acceleration for walking|
|
||||
|speed|px per TARGET_FPS|Walk speed|
|
||||
|jumppower|neg. px per TARGET_FPS^2|Self-explanatory|
|
||||
|scale|unit|Creature body scale. Mass/strength/accel/etc. will be changed accordingly, hence the prefix “base” for some raw tokens|
|
||||
|dragcoeff|unit|Drag coefficient|
|
||||
|speedmult, accelmult, jumppowermult|array of percentiles (Int)|Variability factor|
|
||||
|physiquemult|mult|Breadth variation for mobs|
|
||||
|
||||
## Creature properties ##
|
||||
|
||||
|name|unit|description|
|
||||
|----|----|-----------|
|
||||
|strength|unit|Strength value, no significant unit is given. The value for regular human is fixed to 1 000|
|
||||
|encumbrance|kg or itemcount|Capacity of carrying|
|
||||
|basedefence|unit|Base defence value of body. Sterner body composition (material) == higher value|
|
||||
|armourdefence|unit|Current defence point of armour worn|
|
||||
|armourdefencemult|mult|Bonus point for armour defence|
|
||||
|toolsize|kg|Base tool size for the creature. See MECHANICS file for more information|
|
||||
|
||||
## Aesthetic properties ##
|
||||
|
||||
|name|unit|description|
|
||||
|----|----|-----------|
|
||||
|luminosity|30-bit RGB (Int)|Self-glow. Set to 0 for not glowing|
|
||||
|name|String|Given (perhaps customised) name|
|
||||
|racename|STRING_ID|Racename token in language CSV|
|
||||
|racenameplural|STRING_ID|Racename token in language CSV|
|
||||
|
||||
* Note: luminosity uses customised 30-bit RGB. The format specifies ```1.0``` luminosity of white (```#FFFFFF```) be ```0000_0011111111_0011111111_0011111111```, and can hold luminosity range of 0.0-4.0
|
||||
|
||||
## Flags ##
|
||||
|
||||
|name|unit|description|
|
||||
|----|----|-----------|
|
||||
|intelligent|Boolean|Whether the creature can speak and talk.|
|
||||
@@ -1,27 +0,0 @@
|
||||
Creature raw documentation
|
||||
|
||||
== string values ==
|
||||
|
||||
racename(plural) : Racename token in language CSV
|
||||
|
||||
baseheight : base height for hitbox. [px] (24 px == 1 metre)
|
||||
basemass : base mass for creature. [kg]
|
||||
|
||||
== number values ==
|
||||
|
||||
strength : strength value, no significant unit is given. The value for regular human is fixed to 1 000.
|
||||
accel : acceleration for walking. [px / TARGET_FPS^2]
|
||||
speed : walk speed. [px / TARGET_FPS]
|
||||
jumppower : self-explanatory. [-px / TARGET_FPS^2]
|
||||
scale : creature body scale. Mass/strength/accel/etc. will be changed accordingly, hence the prefix “base” for some raw tokens.
|
||||
|
||||
-mass : variability factor. [array of percentiles]
|
||||
|
||||
encumbrance : capacity of carrying. [kg]
|
||||
basedefence : base defence value of body. Sterner body material == higher value
|
||||
|
||||
toolsize : base tool size for the creature. See MECHANICS file for more information.
|
||||
|
||||
== boolean values ==
|
||||
|
||||
intelligent : can speak and talk.
|
||||
@@ -1,28 +1,28 @@
|
||||
{
|
||||
"racename" : "RACE_HUMAN",
|
||||
"racenameplural" : "RACE_HUMAN_PLURAL",
|
||||
"baseheight" : 40,
|
||||
"basemass" : 60.0,
|
||||
"racename": "RACE_HUMAN",
|
||||
"racenameplural": "RACE_HUMAN_PLURAL",
|
||||
"baseheight": 40,
|
||||
"basemass": 60.0,
|
||||
|
||||
"strength" : 1000,
|
||||
"strengthmult" : [100,100,100,100,100,100,100],
|
||||
"strength": 1000,
|
||||
"strengthmult": [100,100,100,100,100,100,100],
|
||||
|
||||
"accel" : 0.32,
|
||||
"accel": 0.32,
|
||||
|
||||
"speed" : 3.0,
|
||||
"speedmult" : [100,100,100,100,100,100,100],
|
||||
"speed": 3.0,
|
||||
"speedmult": [100,100,100,100,100,100,100],
|
||||
|
||||
"jumppower" : 4.3,
|
||||
"jumppowermult" : [100,100,100,100,100,100,100],
|
||||
"jumppower": 4.3,
|
||||
"jumppowermult": [100,100,100,100,100,100,100],
|
||||
|
||||
"scale" : 1.0,
|
||||
"scalemult" : [100,100,100,100,100,100,100],
|
||||
"scale": 1.0,
|
||||
"physiquemult": [100,100,100,100,100,100,100],
|
||||
|
||||
"encumbrance" : 1000,
|
||||
"basedefence" : 100,
|
||||
"encumbrance": 1000,
|
||||
"basedefence": 100,
|
||||
|
||||
"toolsize" : 15,
|
||||
"toolsize": 15,
|
||||
|
||||
"intelligent" : true
|
||||
"intelligent": true
|
||||
|
||||
}
|
||||
8
res/raw/weathers/WeatherGeneric.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"globalLight": "generic_light.png",
|
||||
"skyboxGradColourMap": "generic_skybox.png",
|
||||
"classification": "generic",
|
||||
"extraImages": [
|
||||
|
||||
]
|
||||
}
|
||||
57
src/net/torvald/gadgets/HistoryArray.kt
Normal file
@@ -0,0 +1,57 @@
|
||||
package net.torvald.gadgets
|
||||
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
|
||||
/**
|
||||
* Simple ArrayList wrapper that acts as history keeper. You can append any data but cannot delete.
|
||||
* Created by minjaesong on 16-07-13.
|
||||
*/
|
||||
class HistoryArray<T>(val historyMax: Int) {
|
||||
|
||||
val history = ArrayList<T?>(Math.min(historyMax, 256)) // 256: arbitrary-set upper bound
|
||||
|
||||
fun add(value: T) {
|
||||
if (history.size == 0) {
|
||||
history.add(value)
|
||||
return
|
||||
}
|
||||
// push existing values to back 1 index
|
||||
else {
|
||||
for (i in history.size - 1 downTo 0) {
|
||||
// if history.size is smaller than historyMax, make room by appending
|
||||
if (i == history.size - 1 && i < historyMax - 1)
|
||||
history.add(history[i])
|
||||
// actually move if we have some room
|
||||
else if (i < historyMax - 1)
|
||||
history[i + 1] = history[i]
|
||||
}
|
||||
}
|
||||
// add new value to the room
|
||||
history[0] = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Get certain index from history. NOTE: index 0 means latest!
|
||||
*/
|
||||
operator fun get(index: Int): T? =
|
||||
if (index >= history.size) null
|
||||
else history[index]
|
||||
|
||||
/**
|
||||
* Iterate from latest to oldest
|
||||
*/
|
||||
fun iterator() = history.iterator()
|
||||
|
||||
/**
|
||||
* Iterate from latest to oldest
|
||||
*/
|
||||
fun forEach(action: Consumer<T?>) = history.forEach(action)
|
||||
|
||||
val latest: T?
|
||||
get() = this[0]
|
||||
|
||||
val oldest: T?
|
||||
get() = this[history.size - 1]
|
||||
|
||||
}
|
||||
@@ -55,34 +55,22 @@ constructor() : Font {
|
||||
}
|
||||
|
||||
private fun isAsciiEF(c: Char) = asciiEFList.contains(c)
|
||||
|
||||
private fun isExtAEF(c: Char) = extAEFList.contains(c)
|
||||
|
||||
private fun isHangul(c: Char) = c.toInt() >= 0xAC00 && c.toInt() < 0xD7A4
|
||||
|
||||
private fun isAscii(c: Char) = c.toInt() > 0x20 && c.toInt() <= 0xFF
|
||||
|
||||
private fun isRunic(c: Char) = runicList.contains(c)
|
||||
|
||||
private fun isExtA(c: Char) = c.toInt() >= 0x100 && c.toInt() < 0x180
|
||||
|
||||
private fun isKana(c: Char) = c.toInt() >= 0x3040 && c.toInt() < 0x3100
|
||||
|
||||
private fun isCJKPunct(c: Char) = c.toInt() >= 0x3000 && c.toInt() < 0x3040
|
||||
|
||||
private fun isUniHan(c: Char) = c.toInt() >= 0x3400 && c.toInt() < 0xA000
|
||||
|
||||
private fun isCyrilic(c: Char) = c.toInt() >= 0x400 && c.toInt() < 0x460
|
||||
|
||||
private fun isCyrilicEF(c: Char) = cyrilecEFList.contains(c)
|
||||
|
||||
private fun isFullwidthUni(c: Char) = c.toInt() >= 0xFF00 && c.toInt() < 0xFF20
|
||||
|
||||
private fun isUniPunct(c: Char) = c.toInt() >= 0x2000 && c.toInt() < 0x2070
|
||||
|
||||
private fun isWenQuanYi1(c: Char) = c.toInt() >= 0x33F3 && c.toInt() <= 0x69FC
|
||||
|
||||
private fun isWenQuanYi2(c: Char) = c.toInt() >= 0x69FD && c.toInt() <= 0x9FDC
|
||||
private fun isGreek(c: Char) = c.toInt() >= 0x370 && c.toInt() <= 0x3CE
|
||||
private fun isGreekEF(c: Char) = greekEFList.contains(c)
|
||||
|
||||
|
||||
|
||||
@@ -121,37 +109,65 @@ constructor() : Font {
|
||||
private fun wenQuanYi1IndexY(c: Char) = (c.toInt() - (0x33F3 + 0x4A)) / 32
|
||||
private fun wenQuanYi2IndexY(c: Char) = (c.toInt() - 0x69FD) / 32
|
||||
|
||||
override fun getWidth(s: String) = getWidthSubstr(s, s.length)
|
||||
private fun greekIndexX(c: Char) = (c.toInt() - 0x370) % 16
|
||||
private fun greekIndexY(c: Char) = (c.toInt() - 0x370) / 16
|
||||
|
||||
private fun greekEFIndexX(c: Char) = greekEFList.indexOf(c) % 16
|
||||
private fun greekEFIndexY(c: Char) = greekEFList.indexOf(c) / 16
|
||||
|
||||
|
||||
private val narrowWidthSheets = arrayOf(
|
||||
SHEET_ASCII_EF,
|
||||
SHEET_EXTA_EF,
|
||||
SHEET_CYRILIC_EF,
|
||||
SHEET_GREEK_EF
|
||||
)
|
||||
private val unihanWidthSheets = arrayOf(
|
||||
SHEET_UNIHAN,
|
||||
SHEET_FW_UNI,
|
||||
SHEET_WENQUANYI_1,
|
||||
SHEET_WENQUANYI_2
|
||||
)
|
||||
private val zeroWidthSheets = arrayOf(
|
||||
SHEET_COLOURCODE
|
||||
)
|
||||
private val cjkWidthSheets = arrayOf(
|
||||
SHEET_KANA,
|
||||
SHEET_HANGUL,
|
||||
SHEET_CJK_PUNCT
|
||||
)
|
||||
|
||||
|
||||
override fun getWidth(s: String) = getWidthSubstr(s, s.length)
|
||||
|
||||
private fun getWidthSubstr(s: String, endIndex: Int): Int {
|
||||
var len = 0
|
||||
for (i in 0..endIndex - 1) {
|
||||
val c = getSheetType(s[i])
|
||||
val ctype = getSheetType(s[i])
|
||||
|
||||
if (i > 0 && s[i].toInt() > 0x20) {
|
||||
// Kerning
|
||||
// Unihan-hangul Kerning
|
||||
val cpre = getSheetType(s[i - 1])
|
||||
if ((cpre == SHEET_UNIHAN || cpre == SHEET_HANGUL) && !(c == SHEET_UNIHAN || c == SHEET_HANGUL)
|
||||
if ((unihanWidthSheets.contains(cpre) || cpre == SHEET_HANGUL) && !(unihanWidthSheets.contains(ctype) || ctype == SHEET_HANGUL)
|
||||
|
||||
|| (c == SHEET_UNIHAN || c == SHEET_HANGUL) && !(cpre == SHEET_UNIHAN || cpre == SHEET_HANGUL)) {
|
||||
|| (unihanWidthSheets.contains(ctype) || ctype == SHEET_HANGUL) && !(unihanWidthSheets.contains(cpre) || cpre == SHEET_HANGUL)) {
|
||||
// margin after/before hangul/unihan
|
||||
len += 2
|
||||
}
|
||||
else if ((c == SHEET_HANGUL || c == SHEET_KANA) && (cpre == SHEET_HANGUL || cpre == SHEET_KANA)) {
|
||||
else if ((ctype == SHEET_HANGUL || ctype == SHEET_KANA) && (cpre == SHEET_HANGUL || cpre == SHEET_KANA)) {
|
||||
// margin between hangul/kana
|
||||
len += 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (c == SHEET_COLOURCODE)
|
||||
if (zeroWidthSheets.contains(ctype))
|
||||
len += 0
|
||||
else if (c == SHEET_ASCII_EF || c == SHEET_EXTA_EF || c == SHEET_CYRILIC_EF)
|
||||
else if (narrowWidthSheets.contains(ctype))
|
||||
len += W_LATIN_NARROW
|
||||
else if (c == SHEET_KANA || c == SHEET_HANGUL || c == SHEET_CJK_PUNCT)
|
||||
else if (cjkWidthSheets.contains(ctype))
|
||||
len += W_CJK
|
||||
else if (c == SHEET_UNIHAN || c == SHEET_FW_UNI || c == SHEET_WENQUANYI_1 || c == SHEET_WENQUANYI_2)
|
||||
else if (unihanWidthSheets.contains(ctype))
|
||||
len += W_UNIHAN
|
||||
else
|
||||
len += W_LATIN_WIDE
|
||||
@@ -375,6 +391,14 @@ constructor() : Font {
|
||||
sheetX = uniPunctIndexX(ch)
|
||||
sheetY = uniPunctIndexY(ch)
|
||||
}
|
||||
SHEET_GREEK_EM -> {
|
||||
sheetX = greekIndexX(ch)
|
||||
sheetY = greekIndexY(ch)
|
||||
}
|
||||
SHEET_GREEK_EF -> {
|
||||
sheetX = greekEFIndexX(ch)
|
||||
sheetY = greekEFIndexY(ch)
|
||||
}
|
||||
else -> {
|
||||
sheetX = ch.toInt() % 16
|
||||
sheetY = ch.toInt() / 16
|
||||
@@ -406,6 +430,10 @@ constructor() : Font {
|
||||
catch (e: ArrayIndexOutOfBoundsException) {
|
||||
// character that does not exist in the sheet. No render, pass.
|
||||
}
|
||||
catch (e1: RuntimeException) {
|
||||
// System.err.println("[GameFontBase] RuntimeException raised while processing character '$ch' (U+${Integer.toHexString(ch.toInt()).toUpperCase()})")
|
||||
// e1.printStackTrack()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -424,6 +452,8 @@ constructor() : Font {
|
||||
return SHEET_EXTA_EF
|
||||
else if (isCyrilicEF(c))
|
||||
return SHEET_CYRILIC_EF
|
||||
else if (isGreekEF(c))
|
||||
return SHEET_GREEK_EF
|
||||
else if (isRunic(c))
|
||||
return SHEET_RUNIC
|
||||
else if (isHangul(c))
|
||||
@@ -444,6 +474,8 @@ constructor() : Font {
|
||||
return SHEET_CJK_PUNCT
|
||||
else if (isFullwidthUni(c))
|
||||
return SHEET_FW_UNI
|
||||
else if (isGreek(c))
|
||||
return SHEET_GREEK_EM
|
||||
else if (c.isColourCode())
|
||||
return SHEET_COLOURCODE
|
||||
else
|
||||
@@ -516,6 +548,8 @@ constructor() : Font {
|
||||
lateinit internal var uniPunct: SpriteSheet
|
||||
lateinit internal var wenQuanYi_1: SpriteSheet
|
||||
lateinit internal var wenQuanYi_2: SpriteSheet
|
||||
lateinit internal var greekSheet: SpriteSheet
|
||||
lateinit internal var greekSheetEF: SpriteSheet
|
||||
|
||||
internal val JUNG_COUNT = 21
|
||||
internal val JONG_COUNT = 28
|
||||
@@ -544,12 +578,12 @@ constructor() : Font {
|
||||
internal val SHEET_UNI_PUNCT = 12
|
||||
internal val SHEET_WENQUANYI_1 = 13
|
||||
internal val SHEET_WENQUANYI_2 = 14
|
||||
|
||||
internal val SHEET_GREEK_EM = 15
|
||||
internal val SHEET_GREEK_EF = 16
|
||||
internal val SHEET_COLOURCODE = 255
|
||||
|
||||
lateinit internal var sheetKey: Array<SpriteSheet>
|
||||
internal val asciiEFList = arrayOf(' ', '!', '"', '\'', '(', ')', ',', '.', ':', ';', 'I', '[', ']', '`', 'f', 'i', 'j', 'l', 't', '{', '|', '}', 0xA1.toChar(), 'Ì', 'Í', 'Î', 'Ï', 'ì', 'í', 'î', 'ï', '·')
|
||||
|
||||
internal val extAEFList = arrayOf(
|
||||
0x12E.toChar(),
|
||||
0x12F.toChar(),
|
||||
@@ -563,7 +597,6 @@ constructor() : Font {
|
||||
0x167.toChar(),
|
||||
0x17F.toChar()
|
||||
)
|
||||
|
||||
internal val cyrilecEFList = arrayOf(
|
||||
0x406.toChar(),
|
||||
0x407.toChar(),
|
||||
@@ -571,6 +604,14 @@ constructor() : Font {
|
||||
0x457.toChar(),
|
||||
0x458.toChar()
|
||||
)
|
||||
internal val greekEFList = arrayOf(
|
||||
0x390.toChar(),
|
||||
0x399.toChar(),
|
||||
0x3AA.toChar(),
|
||||
0x3AF.toChar(),
|
||||
0x3B9.toChar(),
|
||||
0x3CA.toChar()
|
||||
)
|
||||
|
||||
/**
|
||||
* Runic letters list used for game. The set is
|
||||
|
||||
@@ -46,6 +46,10 @@ constructor() : GameFontBase() {
|
||||
"./res/graphics/fonts/wenquanyi_11pt_part1.png", 16, 18, 2)
|
||||
GameFontBase.wenQuanYi_2 = SpriteSheet(
|
||||
"./res/graphics/fonts/wenquanyi_11pt_part2.png", 16, 18, 2)
|
||||
GameFontBase.greekSheet = SpriteSheet(
|
||||
"./res/graphics/fonts/greek_majuscule.png", GameFontBase.W_LATIN_WIDE, GameFontBase.H)
|
||||
GameFontBase.greekSheetEF = SpriteSheet(
|
||||
"./res/graphics/fonts/greek_ef.png", GameFontBase.W_LATIN_NARROW, GameFontBase.H)
|
||||
|
||||
val shk = arrayOf(
|
||||
GameFontBase.asciiSheet,
|
||||
@@ -62,7 +66,10 @@ constructor() : GameFontBase() {
|
||||
GameFontBase.fullwidthForms,
|
||||
GameFontBase.uniPunct,
|
||||
GameFontBase.wenQuanYi_1,
|
||||
GameFontBase.wenQuanYi_2)//, uniHan
|
||||
GameFontBase.wenQuanYi_2, // uniHan
|
||||
GameFontBase.greekSheet,
|
||||
GameFontBase.greekSheetEF
|
||||
)
|
||||
GameFontBase.sheetKey = shk
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.torvald.serialise
|
||||
|
||||
import net.torvald.terrarum.gamemap.GameMap
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
@@ -29,14 +29,14 @@ object WriteGameMapData {
|
||||
val path = Paths.get("${Terrarum.defaultSaveDir}" +
|
||||
"/$saveDirectoryName/${WriteMeta.META_FILENAME}")
|
||||
val tempPath = Files.createTempFile(path.toString(), "_temp")
|
||||
val map = Terrarum.ingame.map
|
||||
val map = Terrarum.ingame.world
|
||||
|
||||
// TODO gzip
|
||||
|
||||
// write binary
|
||||
Files.write(tempPath, MAGIC)
|
||||
Files.write(tempPath, byteArrayOf(GameMap.BITS))
|
||||
Files.write(tempPath, byteArrayOf(GameMap.LAYERS))
|
||||
Files.write(tempPath, byteArrayOf(GameWorld.BITS))
|
||||
Files.write(tempPath, byteArrayOf(GameWorld.LAYERS))
|
||||
Files.write(tempPath, byteArrayOf(BYTE_NULL))
|
||||
Files.write(tempPath, byteArrayOf(BYTE_NULL))
|
||||
Files.write(tempPath, toByteArray(map.width))
|
||||
|
||||
@@ -58,9 +58,14 @@ All rights reserved.
|
||||
|
||||
---
|
||||
|
||||
Amazing ambient sound recordings in ```sound/ambient/klankbeeld-freesound```
|
||||
Amazing ambient sound recordings:
|
||||
|
||||
Samples used: 173111, 183181, 185290, 195287, 240108, 326914, 337691, 347753
|
||||
ambient_forest_01.ogg
|
||||
ambient_meadow_01.ogg
|
||||
ambient_windy_01.ogg
|
||||
ambient_woods_01.ogg
|
||||
crickets_01.ogg
|
||||
crickets_02.ogg
|
||||
|
||||
Copyright (C) 2012, 2013, 2015, 2016 Klankbeeld
|
||||
Sound from http://www.freesound.org/people/klankbeeld/
|
||||
@@ -1,6 +1,9 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import net.torvald.terrarum.gamecontroller.Key
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-03-12.
|
||||
@@ -15,6 +18,53 @@ object DefaultConfig {
|
||||
jsonObject.addProperty("notificationshowuptime", 6500)
|
||||
jsonObject.addProperty("multithread", true) // experimental!
|
||||
|
||||
// control-gamepad
|
||||
jsonObject.addProperty("joypadkeyn", 4)
|
||||
jsonObject.addProperty("joypadkeyw", 1)
|
||||
jsonObject.addProperty("joypadkeys", 2)
|
||||
jsonObject.addProperty("joypadkeye", 3) // logitech indices
|
||||
|
||||
jsonObject.addProperty("joypadlup", 4)
|
||||
jsonObject.addProperty("joypadrup", 5)
|
||||
jsonObject.addProperty("joypadldown", 6)
|
||||
jsonObject.addProperty("joypadrdown", 7) // logitech indices
|
||||
|
||||
jsonObject.addProperty("joypadlstickx", 0)
|
||||
jsonObject.addProperty("joypadlsticky", 1)
|
||||
jsonObject.addProperty("joypadrstickx", 2)
|
||||
jsonObject.addProperty("joypadrsticky", 3) // logitech indices
|
||||
|
||||
// control-keyboard (Java key index. This is what Minecraft also uses)
|
||||
jsonObject.addProperty("keyup", Key.E)
|
||||
jsonObject.addProperty("keyleft", Key.S)
|
||||
jsonObject.addProperty("keydown", Key.D)
|
||||
jsonObject.addProperty("keyright", Key.F)
|
||||
|
||||
jsonObject.addProperty("keymovementaux", Key.A) // movement-auxiliary, or hookshot
|
||||
jsonObject.addProperty("keyinventory", Key.W)
|
||||
jsonObject.addProperty("keyinteract", Key.R)
|
||||
jsonObject.addProperty("keyclose", Key.C)
|
||||
|
||||
jsonObject.addProperty("keygamemenu", Key.TAB)
|
||||
jsonObject.addProperty("keyquicksel", Key.CAPS_LOCK) // pie menu
|
||||
val keyquickselalt = JsonArray(); keyquickselalt.add(Key.BACKSPACE); keyquickselalt.add(Key.L_COMMAND); keyquickselalt.add(Key.L_CONTROL)
|
||||
// some pro typers assign CapsLock to Backspace, LControl, or LCommand (Mac). Honestly, Control (Command for mac) and CapsLock must swap their places!
|
||||
jsonObject.add("keyquickselalt", keyquickselalt)
|
||||
|
||||
jsonObject.addProperty("keyjump", Key.SPACE)
|
||||
|
||||
val keyquickbars = JsonArray(); for (i in 2..11) keyquickbars.add(i) // NUM_1 to NUM_0
|
||||
jsonObject.add("keyquickbars", keyquickbars)
|
||||
|
||||
|
||||
|
||||
|
||||
return jsonObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Additional description goes here
|
||||
|
||||
*/
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import net.torvald.imagefont.GameFontBase
|
||||
import net.torvald.terrarum.audio.AudioResourceLibrary
|
||||
import net.torvald.terrarum.concurrent.ThreadPool
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.console.Authenticator
|
||||
@@ -9,7 +10,7 @@ import net.torvald.terrarum.gamecontroller.GameController
|
||||
import net.torvald.terrarum.gamecontroller.Key
|
||||
import net.torvald.terrarum.gamecontroller.KeyMap
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gamemap.GameMap
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.gamemap.WorldTime
|
||||
import net.torvald.terrarum.mapdrawer.LightmapRenderer
|
||||
import net.torvald.terrarum.mapdrawer.MapCamera
|
||||
@@ -22,6 +23,7 @@ import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
||||
import net.torvald.terrarum.ui.ConsoleWindow
|
||||
import net.torvald.terrarum.ui.Notification
|
||||
import net.torvald.terrarum.ui.UIHandler
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import org.lwjgl.opengl.GL11
|
||||
import org.newdawn.slick.*
|
||||
import org.newdawn.slick.fills.GradientFill
|
||||
@@ -41,7 +43,7 @@ constructor() : BasicGameState() {
|
||||
|
||||
internal var game_mode = 0
|
||||
|
||||
lateinit var map: GameMap
|
||||
lateinit var world: GameWorld
|
||||
|
||||
/**
|
||||
* list of Actors that is sorted by Actors' referenceID
|
||||
@@ -57,8 +59,8 @@ constructor() : BasicGameState() {
|
||||
|
||||
lateinit internal var player: Player
|
||||
|
||||
private var GRADIENT_IMAGE: Image? = null
|
||||
private var skyBox: Rectangle? = null
|
||||
//private var GRADIENT_IMAGE: Image? = null
|
||||
//private var skyBox: Rectangle? = null
|
||||
|
||||
var screenZoom = 1.0f
|
||||
val ZOOM_MAX = 2.0f
|
||||
@@ -92,15 +94,11 @@ constructor() : BasicGameState() {
|
||||
shaderBlurH = Shader.makeShader("./res/blurH.vrt", "./res/blur.frg")
|
||||
shaderBlurV = Shader.makeShader("./res/blurV.vrt", "./res/blur.frg")
|
||||
|
||||
// init skybox
|
||||
GRADIENT_IMAGE = Image("res/graphics/colourmap/sky_colour.png")
|
||||
skyBox = Rectangle(0f, 0f, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
||||
|
||||
// init map as chosen size
|
||||
map = GameMap(8192, 2048)
|
||||
world = GameWorld(8192, 2048)
|
||||
|
||||
// generate terrain for the map
|
||||
MapGenerator.attachMap(map)
|
||||
MapGenerator.attachMap(world)
|
||||
MapGenerator.SEED = 0x51621D2
|
||||
//mapgenerator.setSeed(new HQRNG().nextLong());
|
||||
MapGenerator.generateMap()
|
||||
@@ -132,6 +130,11 @@ constructor() : BasicGameState() {
|
||||
|
||||
// set smooth lighting as in config
|
||||
KeyToggler.forceSet(KEY_LIGHTMAP_SMOOTH, Terrarum.getConfigBoolean("smoothlighting"))
|
||||
|
||||
|
||||
|
||||
// audio test
|
||||
//AudioResourceLibrary.ambientsWoods[0].play()
|
||||
}
|
||||
|
||||
override fun update(gc: GameContainer, sbg: StateBasedGame, delta: Int) {
|
||||
@@ -139,8 +142,11 @@ constructor() : BasicGameState() {
|
||||
|
||||
setAppTitle()
|
||||
|
||||
map.updateWorldTime(delta)
|
||||
map.globalLight = globalLightByTime
|
||||
world.updateWorldTime(delta)
|
||||
|
||||
WeatherMixer.update(gc, delta)
|
||||
|
||||
world.globalLight = globalLightByTime.toInt()
|
||||
|
||||
GameController.processInput(gc.input)
|
||||
|
||||
@@ -258,30 +264,6 @@ constructor() : BasicGameState() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGradientColour(row: Int, phase: Int) = GRADIENT_IMAGE!!.getColor(phase, row)
|
||||
|
||||
private fun getGradientColour(row: Int): Color {
|
||||
val gradMapWidth = GRADIENT_IMAGE!!.width
|
||||
val phase = Math.round(
|
||||
map.worldTime.elapsedSeconds().toFloat() / WorldTime.DAY_LENGTH.toFloat() * gradMapWidth
|
||||
)
|
||||
|
||||
//update in every INTERNAL_FRAME frames
|
||||
return getGradientColour(row, phase)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param time in seconds
|
||||
*/
|
||||
private fun getGradientColourByTime(row: Int, time: Int): Color {
|
||||
val gradMapWidth = GRADIENT_IMAGE!!.width
|
||||
val phase = Math.round(
|
||||
time.toFloat() / WorldTime.DAY_LENGTH.toFloat() * gradMapWidth
|
||||
)
|
||||
|
||||
return getGradientColour(row, phase)
|
||||
}
|
||||
|
||||
override fun keyPressed(key: Int, c: Char) {
|
||||
GameController.keyPressed(key, c)
|
||||
}
|
||||
@@ -320,13 +302,7 @@ constructor() : BasicGameState() {
|
||||
|
||||
override fun getID(): Int = Terrarum.SCENE_ID_GAME
|
||||
|
||||
private fun drawSkybox(g: Graphics) {
|
||||
val skyColourFill = GradientFill(
|
||||
0f, 0f, getGradientColour(0),
|
||||
0f, Terrarum.HEIGHT.toFloat(), getGradientColour(1)
|
||||
)
|
||||
g.fill(skyBox, skyColourFill)
|
||||
}
|
||||
private fun drawSkybox(g: Graphics) = WeatherMixer.render(g)
|
||||
|
||||
/** Send message to notifier UI and toggle the UI as opened. */
|
||||
fun sendNotification(msg: Array<String>) {
|
||||
@@ -399,15 +375,7 @@ constructor() : BasicGameState() {
|
||||
}
|
||||
}
|
||||
|
||||
private val globalLightByTime: Int
|
||||
get() = getGradientColour(2).getRGB24().rgb24ExpandToRgb30()
|
||||
fun globalLightByTime(t: Int): Int = getGradientColourByTime(2, t).getRGB24().rgb24ExpandToRgb30()
|
||||
|
||||
fun Color.getRGB24(): Int = this.redByte.shl(16) or this.greenByte.shl(8) or this.blueByte
|
||||
/** Remap 8-bit value (0.0-1.0) to 10-bit value (0.0-4.0) by prepending two bits of zero for each R, G and B. */
|
||||
fun Int.rgb24ExpandToRgb30(): Int = (this and 0xff) or
|
||||
(this and 0xff00).ushr(8).shl(10) or
|
||||
(this and 0xff0000).ushr(16).shl(20)
|
||||
private val globalLightByTime = WeatherMixer.globalLightNow
|
||||
|
||||
fun Double.sqr() = this * this
|
||||
fun Int.sqr() = this * this
|
||||
|
||||
48
src/net/torvald/terrarum/audio/AudioMixer.kt
Normal file
@@ -0,0 +1,48 @@
|
||||
package net.torvald.terrarum.audio
|
||||
|
||||
import org.lwjgl.openal.AL10
|
||||
import org.newdawn.slick.openal.Audio
|
||||
import org.newdawn.slick.openal.AudioImpl
|
||||
import org.newdawn.slick.openal.MODSound
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-07-08.
|
||||
*/
|
||||
object AudioMixer {
|
||||
const val TRACK_COUNT = 32
|
||||
|
||||
const val TRACK_AMBIENT_ONE = 0
|
||||
const val TRACK_AMBIENT_ONE_NEXT = 1
|
||||
const val TRACK_AMBIENT_TWO = 2
|
||||
const val TRACK_AMBIENT_TWO_NEXT = 3
|
||||
|
||||
const val TRACK_UI_ONE = 8
|
||||
const val TRACK_UI_TWO = 9
|
||||
|
||||
const val TRACK_SFX_START = 16
|
||||
const val TRACK_SFX_END = 31
|
||||
|
||||
val tracks = ArrayList<MixerTrack>(TRACK_COUNT)
|
||||
|
||||
init {
|
||||
|
||||
}
|
||||
|
||||
fun getAudio(track: Int) = tracks[track]
|
||||
|
||||
/**
|
||||
* Queue an SFX to any empty SFX track and play it.
|
||||
*/
|
||||
fun queueSfx(audio: Audio) {
|
||||
|
||||
}
|
||||
|
||||
fun update() {
|
||||
|
||||
}
|
||||
|
||||
class MixerTrack(val audio: Audio, var volume: Float, var pan: Float) {
|
||||
|
||||
}
|
||||
}
|
||||
31
src/net/torvald/terrarum/audio/AudioResourceLibrary.kt
Normal file
@@ -0,0 +1,31 @@
|
||||
package net.torvald.terrarum.audio
|
||||
|
||||
import org.newdawn.slick.openal.Audio
|
||||
import org.newdawn.slick.openal.AudioLoader
|
||||
import java.io.FileInputStream
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-07-08.
|
||||
*/
|
||||
object AudioResourceLibrary {
|
||||
|
||||
val ambientsForest = ArrayList<Audio>()
|
||||
val ambientsMeadow = ArrayList<Audio>()
|
||||
val ambientsWindy = ArrayList<Audio>()
|
||||
val ambientsWoods = ArrayList<Audio>()
|
||||
val crickets = ArrayList<Audio>()
|
||||
|
||||
init {
|
||||
ambientsForest.add(AudioLoader.getAudio("ogg", FileInputStream("./res/sounds/ambient/ambient_forest_01.ogg")))
|
||||
|
||||
ambientsMeadow.add(AudioLoader.getAudio("ogg", FileInputStream("./res/sounds/ambient/ambient_meadow_01.ogg")))
|
||||
|
||||
ambientsWindy.add(AudioLoader.getAudio("ogg", FileInputStream("./res/sounds/ambient/ambient_windy_01.ogg")))
|
||||
|
||||
ambientsWoods.add(AudioLoader.getAudio("ogg", FileInputStream("./res/sounds/ambient/ambient_woods_01.ogg")))
|
||||
|
||||
crickets.add(AudioLoader.getAudio("ogg", FileInputStream("./res/sounds/ambient/crickets_01.ogg")))
|
||||
crickets.add(AudioLoader.getAudio("ogg", FileInputStream("./res/sounds/ambient/crickets_02.ogg")))
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
package net.torvald.terrarum.console
|
||||
|
||||
import net.torvald.terrarum.StateInGame
|
||||
import net.torvald.imagefont.GameFontBase
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.ui.ConsoleWindow
|
||||
|
||||
import java.util.Formatter
|
||||
|
||||
@@ -10,6 +9,9 @@ import java.util.Formatter
|
||||
* Created by minjaesong on 16-01-16.
|
||||
*/
|
||||
class CodexEdictis : ConsoleCommand {
|
||||
|
||||
val ccW = GameFontBase.colToCode["o"]
|
||||
|
||||
override fun execute(args: Array<String>) {
|
||||
if (args.size == 1) {
|
||||
printList()
|
||||
@@ -23,7 +25,7 @@ class CodexEdictis : ConsoleCommand {
|
||||
val sb = StringBuilder()
|
||||
val formatter = Formatter(sb)
|
||||
|
||||
Echo().execute("Codex: " + formatter.format(Lang.get("DEV_MESSAGE_CONSOLE_COMMAND_UNKNOWN"), args[1]).toString())
|
||||
Echo().execute("Codex: " + formatter.format(Lang["DEV_MESSAGE_CONSOLE_COMMAND_UNKNOWN"], args[1]).toString())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,8 +40,11 @@ class CodexEdictis : ConsoleCommand {
|
||||
|
||||
private fun printList() {
|
||||
val echo = Echo()
|
||||
echo.execute(Lang.get("DEV_MESSAGE_CONSOLE_AVAILABLE_COMMANDS"))
|
||||
CommandDict.dict.keys.forEach { s -> echo.execute("• " + s) }
|
||||
echo.execute(Lang["DEV_MESSAGE_CONSOLE_AVAILABLE_COMMANDS"])
|
||||
CommandDict.dict.forEach { name, cmd ->
|
||||
echo.execute("$ccW• " + name)
|
||||
cmd.printUsage()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ object CommandDict {
|
||||
// Test codes
|
||||
Pair("bulletintest", SetBulletin()),
|
||||
Pair("gsontest", GsonTest()),
|
||||
Pair("tips", PrintRandomTips())
|
||||
Pair("tips", PrintRandomTips()),
|
||||
Pair("langtest", LangTest())
|
||||
)
|
||||
|
||||
fun getCommand(commandName: String): ConsoleCommand {
|
||||
|
||||
@@ -5,6 +5,12 @@ package net.torvald.terrarum.console
|
||||
*/
|
||||
interface ConsoleCommand {
|
||||
|
||||
/**
|
||||
* Args 0: command given
|
||||
* Args 1: first argument
|
||||
*
|
||||
* e.g. in ```setav mass 74```, zeroth args will be ```setav```.
|
||||
*/
|
||||
@Throws(Exception::class)
|
||||
fun execute(args: Array<String>)
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@ class ExportMap : ConsoleCommand {
|
||||
if (args.size == 2) {
|
||||
buildColorTable()
|
||||
|
||||
var mapData = ByteArray(Terrarum.ingame.map.width * Terrarum.ingame.map.height * 3)
|
||||
var mapData = ByteArray(Terrarum.ingame.world.width * Terrarum.ingame.world.height * 3)
|
||||
var mapDataPointer = 0
|
||||
|
||||
for (tile in Terrarum.ingame.map.terrainIterator()) {
|
||||
for (tile in Terrarum.ingame.world.terrainIterator()) {
|
||||
val colArray = (colorTable as Map<Int, Col4096>)
|
||||
.getOrElse(tile, { Col4096(0xFFF) }).toByteArray()
|
||||
|
||||
@@ -44,7 +44,7 @@ class ExportMap : ConsoleCommand {
|
||||
|
||||
try {
|
||||
RasterWriter.writePNG_RGB(
|
||||
Terrarum.ingame.map.width, Terrarum.ingame.map.height, mapData, dir + args[1] + ".png")
|
||||
Terrarum.ingame.world.width, Terrarum.ingame.world.height, mapData, dir + args[1] + ".png")
|
||||
Echo().execute("ExportMap: exported to " + args[1] + ".png")
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import net.torvald.terrarum.Terrarum
|
||||
class GetTime : ConsoleCommand {
|
||||
override fun execute(args: Array<String>) {
|
||||
val echo = Echo()
|
||||
val worldTime = Terrarum.ingame.map.worldTime
|
||||
val worldTime = Terrarum.ingame.world.time
|
||||
echo.execute("Year ${worldTime.years}, Month ${worldTime.months}, " +
|
||||
"Day ${worldTime.days} (${worldTime.getDayNameShort()}), " +
|
||||
"${worldTime.getFormattedTime()}"
|
||||
|
||||
19
src/net/torvald/terrarum/console/LangTest.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
package net.torvald.terrarum.console
|
||||
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-07-11.
|
||||
*/
|
||||
class LangTest : ConsoleCommand {
|
||||
override fun printUsage() {
|
||||
Echo().execute("Prints out string in the current lang pack by STRING_ID provided")
|
||||
}
|
||||
|
||||
override fun execute(args: Array<String>) {
|
||||
if (args.size < 2)
|
||||
printUsage()
|
||||
else
|
||||
Echo().execute(Lang[args[1].toUpperCase()])
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class Seed : ConsoleCommand {
|
||||
// tsalagi
|
||||
|
||||
override fun execute(args: Array<String>) {
|
||||
Echo().execute("${ccY}Map$ccW: $ccG${Terrarum.ingame.map.generatorSeed}")
|
||||
Echo().execute("Map$ccW: $ccG${Terrarum.ingame.world.generatorSeed}")
|
||||
// TODO display randomiser seed
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ internal class SetAV : ConsoleCommand {
|
||||
val echo = Echo()
|
||||
echo.execute("${ccW}Set actor value of specific target to desired value.")
|
||||
echo.execute("${ccW}Usage: ${ccY}setav ${ccG}(id) <av> <val>")
|
||||
echo.execute("${ccW}blank ID for player")
|
||||
echo.execute("${ccR}Contaminated (double -> string) ActorValue will crash the game,")
|
||||
echo.execute("${ccW}blank ID for player. Data type will be inferred automatically.")
|
||||
echo.execute("${ccR}Contaminated (e.g. double -> string) ActorValue will crash the game,")
|
||||
echo.execute("${ccR}so make sure it will not happen before you issue the command!")
|
||||
echo.execute("${ccW}Use ${ccG}__true ${ccW}and ${ccG}__false ${ccW}for boolean value.")
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class SetGlobalLightLevel : ConsoleCommand {
|
||||
val b = args[3].toInt()
|
||||
val GL = LightmapRenderer.constructRGBFromInt(r, g, b)
|
||||
|
||||
Terrarum.ingame.map.globalLight = GL
|
||||
Terrarum.ingame.world.globalLight = GL
|
||||
}
|
||||
catch (e: NumberFormatException) {
|
||||
Echo().execute("Wrong number input.")
|
||||
@@ -33,7 +33,7 @@ class SetGlobalLightLevel : ConsoleCommand {
|
||||
Echo().execute("Range: 0-" + (LightmapRenderer.COLOUR_RANGE_SIZE - 1))
|
||||
}
|
||||
else {
|
||||
Terrarum.ingame.map.globalLight = GL
|
||||
Terrarum.ingame.world.globalLight = GL
|
||||
}
|
||||
}
|
||||
catch (e: NumberFormatException) {
|
||||
|
||||
@@ -11,10 +11,10 @@ class SetTime : ConsoleCommand {
|
||||
if (args.size == 2) {
|
||||
val timeToSet = WorldTime.parseTime(args[1])
|
||||
|
||||
Terrarum.ingame.map.worldTime.setTime(timeToSet)
|
||||
Terrarum.ingame.world.time.setTime(timeToSet)
|
||||
|
||||
Echo().execute("Set time to ${Terrarum.ingame.map.worldTime.elapsedSeconds()} " +
|
||||
"(${Terrarum.ingame.map.worldTime.hours}h${formatMin(Terrarum.ingame.map.worldTime.minutes)})")
|
||||
Echo().execute("Set time to ${Terrarum.ingame.world.time.elapsedSeconds()} " +
|
||||
"(${Terrarum.ingame.world.time.hours}h${formatMin(Terrarum.ingame.world.time.minutes)})")
|
||||
}
|
||||
else {
|
||||
printUsage()
|
||||
|
||||
@@ -14,11 +14,11 @@ class SetTimeDelta : ConsoleCommand {
|
||||
if (args[1].toInt() > HARD_LIMIT)
|
||||
Error().execute("Delta too large -- acceptable delta is 0-60.")
|
||||
|
||||
Terrarum.ingame.map.worldTime.setTimeDelta(args[1].toInt())
|
||||
if (Terrarum.ingame.map.worldTime.timeDelta == 0)
|
||||
Terrarum.ingame.world.time.setTimeDelta(args[1].toInt())
|
||||
if (Terrarum.ingame.world.time.timeDelta == 0)
|
||||
Echo().execute("時間よ止まれ!ザ・ワルド!!")
|
||||
else
|
||||
Echo().execute("Set time delta to ${Terrarum.ingame.map.worldTime.timeDelta}")
|
||||
Echo().execute("Set time delta to ${Terrarum.ingame.world.time.timeDelta}")
|
||||
}
|
||||
else {
|
||||
printUsage()
|
||||
|
||||
@@ -6,5 +6,5 @@ import net.torvald.terrarum.gameactors.ai.ActorAI
|
||||
* Created by minjaesong on 16-03-14.
|
||||
*/
|
||||
interface AIControlled {
|
||||
fun attachAI(ai: ActorAI)
|
||||
var actorAI: ActorAI
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.torvald.terrarum.gameactors
|
||||
|
||||
/**
|
||||
* See [res/raw/Creature_raw_doc.md] for information about raw.
|
||||
*
|
||||
* Created by minjaesong on 16-04-02.
|
||||
*/
|
||||
object AVKey {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.torvald.terrarum.gameactors
|
||||
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.gamemap.GameMap
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.mapdrawer.MapDrawer
|
||||
import net.torvald.terrarum.tileproperties.TilePropCodex
|
||||
import net.torvald.spriteanimation.SpriteAnimation
|
||||
@@ -24,7 +24,7 @@ open class ActorWithBody : Actor(), Visible {
|
||||
@Transient var sprite: SpriteAnimation? = null
|
||||
@Transient var spriteGlow: SpriteAnimation? = null
|
||||
|
||||
@Transient private val map: GameMap = Terrarum.ingame.map
|
||||
@Transient private val world: GameWorld = Terrarum.ingame.world
|
||||
|
||||
var hitboxTranslateX: Double = 0.0// relative to spritePosX
|
||||
var hitboxTranslateY: Double = 0.0// relative to spritePosY
|
||||
@@ -103,7 +103,13 @@ open class ActorWithBody : Actor(), Visible {
|
||||
set(value) { elasticity = 1.0 - value }
|
||||
get() = 1.0 - elasticity
|
||||
|
||||
private var density = 1000.0
|
||||
var density = 1000.0
|
||||
set(value) {
|
||||
if (value < 0)
|
||||
throw IllegalArgumentException("[ActorWithBody] $value: density cannot be negative.")
|
||||
|
||||
field = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags and Properties
|
||||
@@ -145,7 +151,7 @@ open class ActorWithBody : Actor(), Visible {
|
||||
* s^2 = 1/FPS = 1/60 if FPS is targeted to 60
|
||||
* meter to pixel : 24/FPS
|
||||
*/
|
||||
@Transient private val gravitation: Vector2 = map.gravitation
|
||||
@Transient private val gravitation: Vector2 = world.gravitation
|
||||
@Transient val DRAG_COEFF_DEFAULT = 1.2
|
||||
/** Drag coefficient. Parachutes have much higher value than bare body (1.2) */
|
||||
private var DRAG_COEFF: Double
|
||||
@@ -361,9 +367,15 @@ open class ActorWithBody : Actor(), Visible {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME the culprit!
|
||||
* (5566 -> no colliiding but player does not "sink")
|
||||
* (5567 -> colliding)
|
||||
* How to fix:
|
||||
*/
|
||||
private fun applyNormalForce() {
|
||||
if (!isNoCollideWorld) {
|
||||
// axis Y
|
||||
// axis Y. Use operand >=
|
||||
if (moveDelta.y >= 0.0) { // was moving downward?
|
||||
if (isTouchingSide(nextHitbox, COLLIDING_BOTTOM)) { // actor hit something on its bottom
|
||||
hitAndReflectY()
|
||||
@@ -493,14 +505,14 @@ open class ActorWithBody : Actor(), Visible {
|
||||
}
|
||||
}
|
||||
|
||||
val txStart = x1.div(TSIZE).roundInt()
|
||||
val txEnd = x2.div(TSIZE).roundInt()
|
||||
val tyStart = y1.div(TSIZE).roundInt()
|
||||
val tyEnd = y2.div(TSIZE).roundInt()
|
||||
val txStart = x1.div(TSIZE).floorInt()
|
||||
val txEnd = x2.div(TSIZE).floorInt()
|
||||
val tyStart = y1.div(TSIZE).floorInt()
|
||||
val tyEnd = y2.div(TSIZE).floorInt()
|
||||
|
||||
for (y in tyStart..tyEnd) {
|
||||
for (x in txStart..txEnd) {
|
||||
val tile = map.getTileFromTerrain(x, y)
|
||||
val tile = world.getTileFromTerrain(x, y)
|
||||
if (TilePropCodex.getProp(tile).isSolid)
|
||||
return true
|
||||
}
|
||||
@@ -537,14 +549,14 @@ open class ActorWithBody : Actor(), Visible {
|
||||
}
|
||||
else throw IllegalArgumentException()
|
||||
|
||||
val txStart = x1.div(TSIZE).roundInt()
|
||||
val txEnd = x2.div(TSIZE).roundInt()
|
||||
val tyStart = y1.div(TSIZE).roundInt()
|
||||
val tyEnd = y2.div(TSIZE).roundInt()
|
||||
val txStart = x1.plus(1.0).div(TSIZE).floorInt()
|
||||
val txEnd = x2.plus(1.0).div(TSIZE).floorInt()
|
||||
val tyStart = y1.plus(1.0).div(TSIZE).floorInt()
|
||||
val tyEnd = y2.plus(1.0).div(TSIZE).floorInt()
|
||||
|
||||
for (y in tyStart..tyEnd) {
|
||||
for (x in txStart..txEnd) {
|
||||
val tile = map.getTileFromTerrain(x, y)
|
||||
val tile = world.getTileFromTerrain(x, y)
|
||||
if (TilePropCodex.getProp(tile).isSolid)
|
||||
return true
|
||||
}
|
||||
@@ -589,7 +601,7 @@ open class ActorWithBody : Actor(), Visible {
|
||||
|
||||
for (y in tyStart..tyEnd) {
|
||||
for (x in txStart..txEnd) {
|
||||
val tile = map.getTileFromTerrain(x, y)
|
||||
val tile = world.getTileFromTerrain(x, y)
|
||||
if (TilePropCodex.getProp(tile).isSolid)
|
||||
return true
|
||||
}
|
||||
@@ -629,7 +641,7 @@ open class ActorWithBody : Actor(), Visible {
|
||||
}
|
||||
|
||||
// evaluate
|
||||
if (TilePropCodex.getProp(map.getTileFromTerrain(tileX, tileY)).isFluid) {
|
||||
if (TilePropCodex.getProp(world.getTileFromTerrain(tileX, tileY)).isFluid) {
|
||||
contactAreaCounter += 1
|
||||
}
|
||||
}
|
||||
@@ -727,7 +739,7 @@ open class ActorWithBody : Actor(), Visible {
|
||||
val tilePosXEnd = (hitbox.hitboxEnd.x / TSIZE).roundInt()
|
||||
val tilePosY = (hitbox.pointedY.plus(1) / TSIZE).roundInt()
|
||||
for (x in tilePosXStart..tilePosXEnd) {
|
||||
val tile = map.getTileFromTerrain(x, tilePosY)
|
||||
val tile = world.getTileFromTerrain(x, tilePosY)
|
||||
val thisFriction = TilePropCodex.getProp(tile).friction
|
||||
|
||||
if (thisFriction > friction) friction = thisFriction
|
||||
@@ -751,7 +763,7 @@ open class ActorWithBody : Actor(), Visible {
|
||||
val tilePosYEnd = (hitbox.hitboxEnd.y / TSIZE).roundInt()
|
||||
for (y in tilePosXStart..tilePosYEnd) {
|
||||
for (x in tilePosXStart..tilePosXEnd) {
|
||||
val tile = map.getTileFromTerrain(x, y)
|
||||
val tile = world.getTileFromTerrain(x, y)
|
||||
val prop = TilePropCodex.getProp(tile)
|
||||
|
||||
if (prop.isFluid && prop.density > density)
|
||||
@@ -776,7 +788,7 @@ open class ActorWithBody : Actor(), Visible {
|
||||
val tilePosYEnd = (nextHitbox.hitboxEnd.y / TSIZE).roundInt()
|
||||
for (y in tilePosYStart..tilePosYEnd) {
|
||||
for (x in tilePosXStart..tilePosXEnd) {
|
||||
val tile = map.getTileFromTerrain(x, y)
|
||||
val tile = world.getTileFromTerrain(x, y)
|
||||
val thisFluidDensity = TilePropCodex.getProp(tile).density
|
||||
|
||||
if (thisFluidDensity > density) density = thisFluidDensity
|
||||
@@ -849,8 +861,8 @@ open class ActorWithBody : Actor(), Visible {
|
||||
private fun clampW(x: Double): Double =
|
||||
if (x < TSIZE + nextHitbox.width / 2) {
|
||||
TSIZE + nextHitbox.width / 2
|
||||
} else if (x >= (map.width * TSIZE).toDouble() - TSIZE.toDouble() - nextHitbox.width / 2) {
|
||||
(map.width * TSIZE).toDouble() - 1.0 - TSIZE.toDouble() - nextHitbox.width / 2
|
||||
} else if (x >= (world.width * TSIZE).toDouble() - TSIZE.toDouble() - nextHitbox.width / 2) {
|
||||
(world.width * TSIZE).toDouble() - 1.0 - TSIZE.toDouble() - nextHitbox.width / 2
|
||||
} else {
|
||||
x
|
||||
}
|
||||
@@ -858,40 +870,22 @@ open class ActorWithBody : Actor(), Visible {
|
||||
private fun clampH(y: Double): Double =
|
||||
if (y < TSIZE + nextHitbox.height) {
|
||||
TSIZE + nextHitbox.height
|
||||
} else if (y >= (map.height * TSIZE).toDouble() - TSIZE.toDouble() - nextHitbox.height) {
|
||||
(map.height * TSIZE).toDouble() - 1.0 - TSIZE.toDouble() - nextHitbox.height
|
||||
} else if (y >= (world.height * TSIZE).toDouble() - TSIZE.toDouble() - nextHitbox.height) {
|
||||
(world.height * TSIZE).toDouble() - 1.0 - TSIZE.toDouble() - nextHitbox.height
|
||||
} else {
|
||||
y
|
||||
}
|
||||
|
||||
private fun clampWtile(x: Int): Int =
|
||||
if (x < 0) {
|
||||
0
|
||||
} else if (x >= map.width) {
|
||||
map.width - 1
|
||||
} else {
|
||||
x
|
||||
}
|
||||
if (x < 0) 0 else if (x >= world.width) world.width - 1 else x
|
||||
|
||||
private fun clampHtile(x: Int): Int =
|
||||
if (x < 0) {
|
||||
0
|
||||
} else if (x >= map.height) {
|
||||
map.height - 1
|
||||
} else {
|
||||
x
|
||||
}
|
||||
if (x < 0) 0 else if (x >= world.height) world.height - 1 else x
|
||||
|
||||
|
||||
private val isPlayerNoClip: Boolean
|
||||
get() = this is Player && this.isNoClip()
|
||||
|
||||
fun setDensity(density: Int) {
|
||||
if (density < 0)
|
||||
throw IllegalArgumentException("[ActorWithBody] $density: density cannot be negative.")
|
||||
|
||||
this.density = density.toDouble()
|
||||
}
|
||||
|
||||
private val AUTO_CLIMB_RATE: Int
|
||||
get() = Math.min(TSIZE / 8 * Math.sqrt(scale), TSIZE.toDouble()).toInt()
|
||||
|
||||
@@ -907,6 +901,17 @@ open class ActorWithBody : Actor(), Visible {
|
||||
if (this > 0 && this > limit) limit
|
||||
else if (this < 0 && this < -limit) -limit
|
||||
else this
|
||||
fun Double.floorSpecial(): Int {
|
||||
val threshold = 1.1 / TSIZE.toDouble()
|
||||
// the idea is 321.0625 would rounded to 321, 320.9375 would rounded to 321,
|
||||
// and regular flooring for otherwise.
|
||||
if (this % TSIZE.toDouble() <= threshold) // case: 321.0625
|
||||
return this.floorInt()
|
||||
else if (1.0 - this.mod(TSIZE.toDouble()) <= threshold) // case: 320.9375
|
||||
return this.floorInt() + 1
|
||||
else
|
||||
return this.floorInt()
|
||||
}
|
||||
|
||||
private fun assertInit() {
|
||||
// errors
|
||||
@@ -929,8 +934,8 @@ open class ActorWithBody : Actor(), Visible {
|
||||
private fun div16TruncateToMapWidth(x: Int): Int {
|
||||
if (x < 0)
|
||||
return 0
|
||||
else if (x >= Terrarum.ingame.map.width shl 4)
|
||||
return Terrarum.ingame.map.width - 1
|
||||
else if (x >= Terrarum.ingame.world.width shl 4)
|
||||
return Terrarum.ingame.world.width - 1
|
||||
else
|
||||
return x and 0x7FFFFFFF shr 4
|
||||
}
|
||||
@@ -938,8 +943,8 @@ open class ActorWithBody : Actor(), Visible {
|
||||
private fun div16TruncateToMapHeight(y: Int): Int {
|
||||
if (y < 0)
|
||||
return 0
|
||||
else if (y >= Terrarum.ingame.map.height shl 4)
|
||||
return Terrarum.ingame.map.height - 1
|
||||
else if (y >= Terrarum.ingame.world.height shl 4)
|
||||
return Terrarum.ingame.world.height - 1
|
||||
else
|
||||
return y and 0x7FFFFFFF shr 4
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import net.torvald.terrarum.gameitem.InventoryItem
|
||||
*/
|
||||
interface CanBeAnItem {
|
||||
|
||||
fun attachItemData()
|
||||
|
||||
fun getItemWeight(): Double
|
||||
|
||||
fun stopUpdateAndDraw()
|
||||
|
||||
@@ -19,7 +19,7 @@ class FixturesTikiTorch : FixturesBase(), Luminous {
|
||||
|
||||
init {
|
||||
isVisible = true
|
||||
super.setDensity(1200)
|
||||
density = 1200.0
|
||||
|
||||
setHitboxDimension(10, 24, 0, 0)
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ interface LandHolder {
|
||||
* Absolute tile index. index(x, y) = y * map.width + x
|
||||
* The arraylist will be saved in JSON format with GSON.
|
||||
*/
|
||||
var houseDesignation: ArrayList<Int>?
|
||||
fun addHouseTile(x: Int, y: Int);
|
||||
fun removeHouseTile(x: Int, y: Int);
|
||||
fun clearHouseDesignation();
|
||||
var houseDesignation: ArrayList<Long>?
|
||||
fun addHouseTile(x: Int, y: Int)
|
||||
fun removeHouseTile(x: Int, y: Int)
|
||||
fun clearHouseDesignation()
|
||||
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
package net.torvald.terrarum.gameactors
|
||||
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.gameactors.ai.ActorAI
|
||||
import net.torvald.terrarum.gameactors.faction.Faction
|
||||
import net.torvald.terrarum.gameitem.InventoryItem
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.realestate.RealEstateUtility.getAbsoluteTileNumber
|
||||
import org.newdawn.slick.GameContainer
|
||||
import java.util.*
|
||||
|
||||
@@ -14,19 +13,27 @@ import java.util.*
|
||||
open class NPCIntelligentBase : ActorWithBody()
|
||||
, AIControlled, Pocketed, CanBeAnItem, Factionable, LandHolder {
|
||||
|
||||
override var actorAI: ActorAI = object : ActorAI {
|
||||
// TODO fully establish ActorAI so that I can implement AI here
|
||||
}
|
||||
override var inventory: ActorInventory = ActorInventory()
|
||||
override var faction: HashSet<Faction> = HashSet()
|
||||
override var houseDesignation: ArrayList<Long>? = null
|
||||
|
||||
// we're having InventoryItem data so that this class could be somewhat universal
|
||||
override var itemData: InventoryItem = object : InventoryItem {
|
||||
override var itemID = HQRNG().nextInt()
|
||||
override var itemID = referenceID
|
||||
|
||||
override var mass: Double
|
||||
get() = actorValue.getAsDouble("mass")!!
|
||||
get() = actorValue.getAsDouble(AVKey.BASEMASS)!!
|
||||
set(value) {
|
||||
actorValue.set("mass", value)
|
||||
actorValue[AVKey.BASEMASS] = value
|
||||
}
|
||||
|
||||
override var scale: Double
|
||||
get() = actorValue.getAsDouble("scale")!!
|
||||
get() = actorValue.getAsDouble(AVKey.SCALE)!!
|
||||
set(value) {
|
||||
actorValue.set("scale", value)
|
||||
actorValue[AVKey.SCALE] = value
|
||||
}
|
||||
|
||||
override fun effectWhileInPocket(gc: GameContainer, delta_t: Int) {
|
||||
@@ -38,52 +45,32 @@ open class NPCIntelligentBase : ActorWithBody()
|
||||
}
|
||||
|
||||
override fun primaryUse(gc: GameContainer, delta_t: Int) {
|
||||
|
||||
// TODO do not allow primary_use
|
||||
}
|
||||
|
||||
override fun secondaryUse(gc: GameContainer, delta_t: Int) {
|
||||
|
||||
// TODO place this Actor to the world
|
||||
}
|
||||
|
||||
override fun effectWhenThrownAway(gc: GameContainer, delta_t: Int) {
|
||||
override fun effectWhenThrown(gc: GameContainer, delta_t: Int) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Transient private var ai: ActorAI? = null
|
||||
override var inventory: ActorInventory = ActorInventory()
|
||||
|
||||
private val factionSet = HashSet<Faction>()
|
||||
|
||||
override var referenceID: Int = HQRNG().nextInt()
|
||||
|
||||
override var faction: HashSet<Faction> = HashSet()
|
||||
|
||||
override var houseDesignation: ArrayList<Int>? = null
|
||||
/**
|
||||
* Absolute tile index. index(x, y) = y * map.width + x
|
||||
* The arraylist will be saved in JSON format with GSON.
|
||||
*/
|
||||
private var houseTiles = ArrayList<Int>()
|
||||
|
||||
override fun attachItemData() {
|
||||
|
||||
}
|
||||
|
||||
override fun getItemWeight(): Double {
|
||||
return mass
|
||||
}
|
||||
|
||||
override fun addHouseTile(x: Int, y: Int) {
|
||||
houseTiles.add(Terrarum.ingame.map.width * y + x)
|
||||
if (houseDesignation != null) houseDesignation!!.add(getAbsoluteTileNumber(x, y))
|
||||
}
|
||||
|
||||
override fun removeHouseTile(x: Int, y: Int) {
|
||||
houseTiles.remove(Terrarum.ingame.map.width * y + x)
|
||||
if (houseDesignation != null) houseDesignation!!.remove(getAbsoluteTileNumber(x, y))
|
||||
}
|
||||
|
||||
override fun clearHouseDesignation() {
|
||||
houseTiles.clear()
|
||||
if (houseDesignation != null) houseDesignation!!.clear()
|
||||
}
|
||||
|
||||
override fun stopUpdateAndDraw() {
|
||||
@@ -96,7 +83,5 @@ open class NPCIntelligentBase : ActorWithBody()
|
||||
isVisible = true
|
||||
}
|
||||
|
||||
override fun attachAI(ai: ActorAI) {
|
||||
this.ai = ai
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,8 @@ class PhysTestBall : ActorWithBody() {
|
||||
init {
|
||||
setHitboxDimension(16, 16, 0, 0)
|
||||
isVisible = true
|
||||
actorValue[AVKey.BASEMASS] = 10.0
|
||||
mass = 10.0
|
||||
density = 200.0
|
||||
|
||||
color = RoguelikeRandomiser.composeColourFrom(RoguelikeRandomiser.POTION_PRIMARY_COLSET)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class Player : ActorWithBody(), Controllable, Pocketed, Factionable, Luminous, L
|
||||
|
||||
@Transient private val TSIZE = MapDrawer.TILE_SIZE
|
||||
|
||||
@Transient private val BASE_DENSITY = 1020
|
||||
@Transient private val BASE_DENSITY = 980.0
|
||||
|
||||
/** Must be set by PlayerFactory */
|
||||
override var inventory: ActorInventory = ActorInventory()
|
||||
@@ -64,7 +64,7 @@ class Player : ActorWithBody(), Controllable, Pocketed, Factionable, Luminous, L
|
||||
/** Must be set by PlayerFactory */
|
||||
override var faction: HashSet<Faction> = HashSet()
|
||||
|
||||
override var houseDesignation: ArrayList<Int>? = null
|
||||
override var houseDesignation: ArrayList<Long>? = null
|
||||
|
||||
override var luminosity: Int
|
||||
get() = actorValue.getAsInt(AVKey.LUMINOSITY) ?: 0
|
||||
@@ -92,7 +92,7 @@ class Player : ActorWithBody(), Controllable, Pocketed, Factionable, Luminous, L
|
||||
init {
|
||||
isVisible = true
|
||||
referenceID = PLAYER_REF_ID // forcibly set ID
|
||||
super.setDensity(BASE_DENSITY)
|
||||
density = BASE_DENSITY
|
||||
collisionType = KINEMATIC
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ object GameController {
|
||||
if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)) {
|
||||
// test tile remove
|
||||
try {
|
||||
Terrarum.ingame.map.setTileTerrain(mouseTileX, mouseTileY, TileNameCode.AIR)
|
||||
Terrarum.ingame.world.setTileTerrain(mouseTileX, mouseTileY, TileNameCode.AIR)
|
||||
// terrarum.game.map.setTileWall(mouseTileX, mouseTileY, TileNameCode.AIR);
|
||||
}
|
||||
catch (e: ArrayIndexOutOfBoundsException) {
|
||||
@@ -52,7 +52,7 @@ object GameController {
|
||||
else if (input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON)) {
|
||||
// test tile place
|
||||
try {
|
||||
Terrarum.ingame.map.setTileTerrain(mouseTileX, mouseTileY, Terrarum.ingame.player.actorValue.getAsInt("selectedtile")!!)
|
||||
Terrarum.ingame.world.setTileTerrain(mouseTileX, mouseTileY, Terrarum.ingame.player.actorValue.getAsInt("selectedtile")!!)
|
||||
}
|
||||
catch (e: ArrayIndexOutOfBoundsException) {
|
||||
}
|
||||
|
||||
@@ -6,11 +6,16 @@ package net.torvald.terrarum.gamecontroller
|
||||
object Key {
|
||||
|
||||
val RET = 28
|
||||
val BKSP = 14
|
||||
val BACKSPACE = 14
|
||||
val GRAVE = 41
|
||||
val TAB = 15
|
||||
val ESCAPE = 1
|
||||
val SPACE = 57
|
||||
val CAPS_LOCK = 58
|
||||
val L_CONTROL = 29
|
||||
val L_COMMAND = 219 // Mac
|
||||
|
||||
val DELETE = 211
|
||||
|
||||
val L_SHIFT = 42
|
||||
val R_SHIFT = 54
|
||||
@@ -46,12 +51,12 @@ object Key {
|
||||
val NUM_9 = 10
|
||||
val NUM_0 = 11
|
||||
|
||||
// JInput is QWERTY-based
|
||||
val Q = 16
|
||||
val W = 17
|
||||
val E = 18
|
||||
val R = 19
|
||||
val T = 20
|
||||
|
||||
val Y = 21
|
||||
val U = 22
|
||||
val I = 23
|
||||
@@ -63,7 +68,6 @@ object Key {
|
||||
val D = 32
|
||||
val F = 33
|
||||
val G = 34
|
||||
|
||||
val H = 35
|
||||
val J = 36
|
||||
val K = 37
|
||||
@@ -75,7 +79,6 @@ object Key {
|
||||
val C = 46
|
||||
val V = 47
|
||||
val B = 48
|
||||
|
||||
val N = 49
|
||||
val M = 50
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ interface InventoryItem {
|
||||
var scale: Double
|
||||
|
||||
/**
|
||||
* Effects applied while in pocket
|
||||
* Effects applied continuously while in pocket
|
||||
* @param gc
|
||||
* *
|
||||
* @param delta_t
|
||||
@@ -41,7 +41,7 @@ interface InventoryItem {
|
||||
fun effectWhenPickedUp(gc: GameContainer, delta_t: Int)
|
||||
|
||||
/**
|
||||
* Effects applied while primary button (usually left mouse button) is down
|
||||
* Effects applied (continuously or not) while primary button (usually left mouse button) is down
|
||||
* @param gc
|
||||
* *
|
||||
* @param delta_t
|
||||
@@ -49,7 +49,7 @@ interface InventoryItem {
|
||||
fun primaryUse(gc: GameContainer, delta_t: Int)
|
||||
|
||||
/**
|
||||
* Effects applied while secondary button (usually right mouse button) is down
|
||||
* Effects applied (continuously or not) while secondary button (usually right mouse button) is down
|
||||
* @param gc
|
||||
* *
|
||||
* @param delta_t
|
||||
@@ -62,5 +62,5 @@ interface InventoryItem {
|
||||
* *
|
||||
* @param delta_t
|
||||
*/
|
||||
fun effectWhenThrownAway(gc: GameContainer, delta_t: Int)
|
||||
fun effectWhenThrown(gc: GameContainer, delta_t: Int)
|
||||
}
|
||||
@@ -33,7 +33,7 @@ class TileAsItem(tileNum: Int) : InventoryItem {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun effectWhenThrownAway(gc: GameContainer, delta_t: Int) {
|
||||
override fun effectWhenThrown(gc: GameContainer, delta_t: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ package net.torvald.terrarum.gamemap
|
||||
import org.dyn4j.geometry.Vector2
|
||||
import org.newdawn.slick.SlickException
|
||||
|
||||
class GameMap
|
||||
class GameWorld
|
||||
/**
|
||||
* @param width
|
||||
* *
|
||||
@@ -36,7 +36,7 @@ constructor(//properties
|
||||
var gravitation: Vector2 = Vector2(0.0, 9.8)
|
||||
/** RGB in Integer */
|
||||
var globalLight: Int = 0
|
||||
val worldTime: WorldTime
|
||||
val time: WorldTime
|
||||
|
||||
var generatorSeed: Long = 0
|
||||
|
||||
@@ -50,8 +50,7 @@ constructor(//properties
|
||||
terrainDamage = PairedMapLayer(width, height)
|
||||
wallDamage = PairedMapLayer(width, height)
|
||||
|
||||
globalLight = 0.toChar().toInt()
|
||||
worldTime = WorldTime()
|
||||
time = WorldTime()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,7 +168,7 @@ constructor(//properties
|
||||
}
|
||||
|
||||
fun updateWorldTime(delta: Int) {
|
||||
worldTime.update(delta)
|
||||
time.update(delta)
|
||||
}
|
||||
|
||||
fun terrainIterator(): Iterator<Int> {
|
||||
@@ -1,8 +1,10 @@
|
||||
package net.torvald.terrarum.itemproperties
|
||||
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.gameactors.CanBeAnItem
|
||||
import net.torvald.terrarum.gameitem.InventoryItem
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import org.newdawn.slick.GameContainer
|
||||
import java.util.*
|
||||
|
||||
@@ -20,6 +22,7 @@ object ItemPropCodex {
|
||||
private lateinit var itemCodex: Array<InventoryItem>
|
||||
|
||||
const val ITEM_UNIQUE_MAX = 32768
|
||||
val TILE_MAX = GameWorld.TILES_SUPPORTED
|
||||
|
||||
init {
|
||||
itemCodex = arrayOf<InventoryItem>()
|
||||
|
||||
@@ -20,7 +20,8 @@ object Lang {
|
||||
*
|
||||
* HashMap<"$key_$language", Value>
|
||||
*/
|
||||
private var langpack: HashMap<String, String>
|
||||
var langpack: HashMap<String, String>
|
||||
private set
|
||||
private val FALLBACK_LANG_CODE = "en"
|
||||
|
||||
private val HANGUL_SYL_START = 0xAC00
|
||||
|
||||
195
src/net/torvald/terrarum/mapdrawer/Light10B.kt
Normal file
@@ -0,0 +1,195 @@
|
||||
package net.torvald.terrarum.mapdrawer
|
||||
|
||||
import com.jme3.math.FastMath
|
||||
import org.newdawn.slick.Color
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-07-08.
|
||||
*/
|
||||
|
||||
class Light10B {
|
||||
|
||||
private var data = 0
|
||||
|
||||
constructor(r: Int, g: Int, b: Int) {
|
||||
data = constructRGBFromInt(r, g, b)
|
||||
}
|
||||
|
||||
constructor(r: Float, g: Float, b: Float) {
|
||||
if (r < 0 || r > 1.0f) throw IllegalArgumentException("Red: out of range ($r)")
|
||||
if (g < 0 || g > 1.0f) throw IllegalArgumentException("Green: out of range ($g)")
|
||||
if (b < 0 || b > 1.0f) throw IllegalArgumentException("Blue: out of range ($b)")
|
||||
|
||||
val intR = (r * CHANNEL_MAX).floor()
|
||||
val intG = (g * CHANNEL_MAX).floor()
|
||||
val intB = (b * CHANNEL_MAX).floor()
|
||||
|
||||
data = constructRGBFromInt(intR, intG, intB)
|
||||
}
|
||||
|
||||
constructor(raw: Int) {
|
||||
data = raw
|
||||
}
|
||||
|
||||
constructor(color: Color) {
|
||||
data = constructRGBFromInt(color.red, color.green, color.blue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigners
|
||||
*/
|
||||
fun fromRGB(r: Int, g: Int, b: Int): Light10B {
|
||||
data = constructRGBFromInt(r, g, b)
|
||||
return this
|
||||
}
|
||||
|
||||
fun fromInt(raw: Int): Light10B {
|
||||
data = raw
|
||||
return this
|
||||
}
|
||||
|
||||
fun fromSlickColor(color: Color): Light10B {
|
||||
data = constructRGBFromInt(color.red, color.green, color.blue)
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun toInt(): Int = data
|
||||
|
||||
fun constructRGBFromInt(r: Int, g: Int, b: Int): Int {
|
||||
if (r !in 0..CHANNEL_MAX) throw IllegalArgumentException("Red: out of range ($r)")
|
||||
if (g !in 0..CHANNEL_MAX) throw IllegalArgumentException("Green: out of range ($g)")
|
||||
if (b !in 0..CHANNEL_MAX) throw IllegalArgumentException("Blue: out of range ($b)")
|
||||
return (r * STEPS_2 + g * STEPS + b)
|
||||
}
|
||||
|
||||
val STEPS = 1024
|
||||
val STEPS_2 = STEPS * STEPS
|
||||
val CHANNEL_MAX = STEPS - 1
|
||||
val CHANNEL_MAX_FLOAT = CHANNEL_MAX.toFloat()
|
||||
val CHANNEL_MAX_DECIMAL = 4f
|
||||
val COLOUR_RANGE_SIZE = STEPS * STEPS_2
|
||||
|
||||
override fun toString() = "10BitCol:$data"
|
||||
|
||||
fun rawR() = data / STEPS_2
|
||||
fun rawG() = data % STEPS_2 / STEPS
|
||||
fun rawB() = data % STEPS
|
||||
|
||||
fun r(): Float = this.rawR() / CHANNEL_MAX_FLOAT
|
||||
fun g(): Float = this.rawG() / CHANNEL_MAX_FLOAT
|
||||
fun b(): Float = this.rawB() / CHANNEL_MAX_FLOAT
|
||||
|
||||
fun Float.floor() = FastMath.floor(this)
|
||||
private fun Float.clampChannel() = if (this < 0) 0f else if (this > CHANNEL_MAX_DECIMAL) CHANNEL_MAX_DECIMAL else this
|
||||
private fun Int.clampChannel() = if (this < 0) 0 else if (this > CHANNEL_MAX) CHANNEL_MAX else this
|
||||
|
||||
operator fun plus(other: Light10B) =
|
||||
Light10B(
|
||||
rawR().plus(other.rawR()).clampChannel(),
|
||||
rawG().plus(other.rawG()).clampChannel(),
|
||||
rawB().plus(other.rawB()).clampChannel()
|
||||
)
|
||||
operator fun minus(other: Light10B) =
|
||||
Light10B(
|
||||
rawR().minus(other.rawR()).clampChannel(),
|
||||
rawG().minus(other.rawG()).clampChannel(),
|
||||
rawB().minus(other.rawB()).clampChannel()
|
||||
)
|
||||
operator fun times(other: Light10B) =
|
||||
Light10B(
|
||||
r().times(other.r()).clampChannel(),
|
||||
g().times(other.g()).clampChannel(),
|
||||
b().times(other.b()).clampChannel()
|
||||
)
|
||||
infix fun darken(other: Light10B): Light10B {
|
||||
if (other.toInt() < 0 || other.toInt() >= COLOUR_RANGE_SIZE)
|
||||
throw IllegalArgumentException("darken: out of range ($other)")
|
||||
|
||||
val r = this.r() * (1f - other.r() * 6) // 6: Arbitrary value
|
||||
val g = this.g() * (1f - other.g() * 6) // TODO gamma correction?
|
||||
val b = this.b() * (1f - other.b() * 6)
|
||||
|
||||
return Light10B(r.clampChannel(), g.clampChannel(), b.clampChannel())
|
||||
}
|
||||
infix fun darken(darken: Int): Light10B {
|
||||
if (darken < 0 || darken > CHANNEL_MAX)
|
||||
throw IllegalArgumentException("darken: out of range ($darken)")
|
||||
|
||||
val darkenColoured = constructRGBFromInt(darken, darken, darken)
|
||||
return (this darken darkenColoured)
|
||||
}
|
||||
infix fun brighten(other: Light10B): Light10B {
|
||||
if (other.toInt() < 0 || other.toInt() >= COLOUR_RANGE_SIZE)
|
||||
throw IllegalArgumentException("brighten: out of range ($other)")
|
||||
|
||||
val r = this.r() * (1f + other.r() * 6) // 6: Arbitrary value
|
||||
val g = this.g() * (1f + other.g() * 6) // TODO gamma correction?
|
||||
val b = this.b() * (1f + other.b() * 6)
|
||||
|
||||
return Light10B(r.clampChannel(), g.clampChannel(), b.clampChannel())
|
||||
}
|
||||
/**
|
||||
* Darken or brighten colour by 'brighten' argument
|
||||
*
|
||||
* @param data Raw channel value (0-255) per channel
|
||||
* @param brighten (-1.0 - 1.0) negative means darkening
|
||||
* @return processed colour
|
||||
*/
|
||||
fun alterBrightnessUniform(data: Light10B, brighten: Float): Light10B {
|
||||
val modifier = if (brighten < 0)
|
||||
Light10B(-brighten, -brighten, -brighten)
|
||||
else
|
||||
Light10B(brighten, brighten, brighten)
|
||||
return if (brighten < 0)
|
||||
data darken modifier
|
||||
else
|
||||
data brighten modifier
|
||||
}
|
||||
|
||||
/** Get each channel from two RGB values, return new RGB that has max value of each channel
|
||||
* @param rgb
|
||||
* @param rgb2
|
||||
* @return
|
||||
*/
|
||||
infix fun maxBlend(other: Light10B): Light10B {
|
||||
val r1 = this.rawR()
|
||||
val r2 = other.rawR()
|
||||
val newR = if (r1 > r2) r1 else r2
|
||||
val g1 = this.rawG()
|
||||
val g2 = other.rawG()
|
||||
val newG = if (g1 > g2) g1 else g2
|
||||
val b1 = this.rawB()
|
||||
val b2 = other.rawB()
|
||||
val newB = if (b1 > b2) b1 else b2
|
||||
|
||||
return Light10B(newR, newG, newB)
|
||||
}
|
||||
|
||||
infix fun screenBlend(other: Light10B): Light10B {
|
||||
val r1 = this.r()
|
||||
val r2 = other.r()
|
||||
val newR = 1 - (1 - r1) * (1 - r2)
|
||||
val g1 = this.g()
|
||||
val g2 = other.g()
|
||||
val newG = 1 - (1 - g1) * (1 - g2)
|
||||
val b1 = this.b()
|
||||
val b2 = other.b()
|
||||
val newB = 1 - (1 - b1) * (1 - b2)
|
||||
|
||||
return Light10B(newR, newG, newB)
|
||||
}
|
||||
|
||||
private infix fun colSub(other: Light10B) = Light10B(
|
||||
(this.rawR() - other.rawR()).clampChannel() ,
|
||||
(this.rawG() - other.rawG()).clampChannel() ,
|
||||
(this.rawB() - other.rawB()).clampChannel()
|
||||
)
|
||||
|
||||
private infix fun colAdd(other: Light10B) = Light10B(
|
||||
(this.rawR() + other.rawR()).clampChannel() ,
|
||||
(this.rawG() + other.rawG()).clampChannel() ,
|
||||
(this.rawB() + other.rawB()).clampChannel()
|
||||
)
|
||||
}
|
||||
@@ -228,11 +228,11 @@ object LightmapRenderer {
|
||||
|
||||
private fun calculate(x: Int, y: Int, doNotCalculateAmbient: Boolean): Int {
|
||||
var lightLevelThis: Int = 0
|
||||
val thisTerrain = Terrarum.ingame.map.getTileFromTerrain(x, y)
|
||||
val thisWall = Terrarum.ingame.map.getTileFromWall(x, y)
|
||||
val thisTerrain = Terrarum.ingame.world.getTileFromTerrain(x, y)
|
||||
val thisWall = Terrarum.ingame.world.getTileFromWall(x, y)
|
||||
val thisTileLuminosity = TilePropCodex.getProp(thisTerrain).luminosity
|
||||
val thisTileOpacity = TilePropCodex.getProp(thisTerrain).opacity
|
||||
val sunLight = Terrarum.ingame.map.globalLight
|
||||
val sunLight = Terrarum.ingame.world.globalLight
|
||||
|
||||
// MIX TILE
|
||||
// open air
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.torvald.terrarum.mapdrawer
|
||||
|
||||
import net.torvald.terrarum.gamemap.GameMap
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.gamemap.PairedMapLayer
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.tileproperties.TileNameCode
|
||||
@@ -20,7 +20,7 @@ import java.util.*
|
||||
* Created by minjaesong on 16-01-19.
|
||||
*/
|
||||
object MapCamera {
|
||||
val map: GameMap = Terrarum.ingame.map;
|
||||
val WORLD: GameWorld = Terrarum.ingame.world;
|
||||
|
||||
var cameraX = 0
|
||||
private set
|
||||
@@ -38,9 +38,9 @@ object MapCamera {
|
||||
var tilesetBook: Array<SpriteSheet> = arrayOf(tilesWall, tilesTerrain, tilesWire)
|
||||
private set
|
||||
|
||||
val WALL = GameMap.WALL
|
||||
val TERRAIN = GameMap.TERRAIN
|
||||
val WIRE = GameMap.WIRE
|
||||
val WALL = GameWorld.WALL
|
||||
val TERRAIN = GameWorld.TERRAIN
|
||||
val WIRE = GameWorld.WIRE
|
||||
|
||||
var renderWidth: Int = 0
|
||||
private set
|
||||
@@ -236,9 +236,9 @@ object MapCamera {
|
||||
|
||||
// position - (WH / 2)
|
||||
cameraX = Math.round(FastMath.clamp(
|
||||
player.hitbox.centeredX.toFloat() - renderWidth / 2, TSIZE.toFloat(), map.width * TSIZE - renderWidth - TSIZE.toFloat()))
|
||||
player.hitbox.centeredX.toFloat() - renderWidth / 2, TSIZE.toFloat(), WORLD.width * TSIZE - renderWidth - TSIZE.toFloat()))
|
||||
cameraY = Math.round(FastMath.clamp(
|
||||
player.hitbox.centeredY.toFloat() - renderHeight / 2, TSIZE.toFloat(), map.height * TSIZE - renderHeight - TSIZE.toFloat()))
|
||||
player.hitbox.centeredY.toFloat() - renderHeight / 2, TSIZE.toFloat(), WORLD.height * TSIZE - renderHeight - TSIZE.toFloat()))
|
||||
}
|
||||
|
||||
fun renderBehind(gc: GameContainer, g: Graphics) {
|
||||
@@ -272,11 +272,11 @@ object MapCamera {
|
||||
|
||||
val thisTile: Int?
|
||||
if (mode % 3 == MapCamera.WALL)
|
||||
thisTile = MapCamera.map.getTileFromWall(x, y)
|
||||
thisTile = MapCamera.WORLD.getTileFromWall(x, y)
|
||||
else if (mode % 3 == MapCamera.TERRAIN)
|
||||
thisTile = MapCamera.map.getTileFromTerrain(x, y)
|
||||
thisTile = MapCamera.WORLD.getTileFromTerrain(x, y)
|
||||
else if (mode % 3 == MapCamera.WIRE)
|
||||
thisTile = MapCamera.map.getTileFromWire(x, y)
|
||||
thisTile = MapCamera.WORLD.getTileFromWire(x, y)
|
||||
else
|
||||
throw IllegalArgumentException()
|
||||
|
||||
@@ -352,10 +352,10 @@ object MapCamera {
|
||||
*/
|
||||
fun getNearbyTilesInfo(x: Int, y: Int, mode: Int, mark: Int?): Int {
|
||||
val nearbyTiles = IntArray(4)
|
||||
nearbyTiles[NEARBY_TILE_KEY_LEFT] = map.getTileFrom(mode, x - 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = map.getTileFrom(mode, x + 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_UP] = map.getTileFrom(mode, x, y - 1) ?: 4906
|
||||
nearbyTiles[NEARBY_TILE_KEY_DOWN] = map.getTileFrom(mode, x, y + 1) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_LEFT] = WORLD.getTileFrom(mode, x - 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = WORLD.getTileFrom(mode, x + 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_UP] = WORLD.getTileFrom(mode, x, y - 1) ?: 4906
|
||||
nearbyTiles[NEARBY_TILE_KEY_DOWN] = WORLD.getTileFrom(mode, x, y + 1) ?: 4096
|
||||
|
||||
// try for
|
||||
var ret = 0
|
||||
@@ -370,10 +370,10 @@ object MapCamera {
|
||||
|
||||
fun getNearbyTilesInfoNonSolid(x: Int, y: Int, mode: Int): Int {
|
||||
val nearbyTiles = IntArray(4)
|
||||
nearbyTiles[NEARBY_TILE_KEY_LEFT] = map.getTileFrom(mode, x - 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = map.getTileFrom(mode, x + 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_UP] = map.getTileFrom(mode, x, y - 1) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_DOWN] = map.getTileFrom(mode, x, y + 1) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_LEFT] = WORLD.getTileFrom(mode, x - 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = WORLD.getTileFrom(mode, x + 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_UP] = WORLD.getTileFrom(mode, x, y - 1) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_DOWN] = WORLD.getTileFrom(mode, x, y + 1) ?: 4096
|
||||
|
||||
// try for
|
||||
var ret = 0
|
||||
@@ -393,10 +393,10 @@ object MapCamera {
|
||||
fun getNearbyTilesInfoWallSticker(x: Int, y: Int): Int {
|
||||
val nearbyTiles = IntArray(4)
|
||||
val NEARBY_TILE_KEY_BACK = NEARBY_TILE_KEY_UP
|
||||
nearbyTiles[NEARBY_TILE_KEY_LEFT] = map.getTileFrom(TERRAIN, x - 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = map.getTileFrom(TERRAIN, x + 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_DOWN] = map.getTileFrom(TERRAIN, x, y + 1) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_BACK] = map.getTileFrom(WALL, x, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_LEFT] = WORLD.getTileFrom(TERRAIN, x - 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = WORLD.getTileFrom(TERRAIN, x + 1, y) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_DOWN] = WORLD.getTileFrom(TERRAIN, x, y + 1) ?: 4096
|
||||
nearbyTiles[NEARBY_TILE_KEY_BACK] = WORLD.getTileFrom(WALL, x, y) ?: 4096
|
||||
|
||||
try {
|
||||
if (TilePropCodex.getProp(nearbyTiles[NEARBY_TILE_KEY_DOWN]).isSolid)
|
||||
@@ -442,8 +442,8 @@ object MapCamera {
|
||||
fun clampW(x: Int): Int {
|
||||
if (x < 0) {
|
||||
return 0
|
||||
} else if (x > map.width * TSIZE) {
|
||||
return map.width * TSIZE
|
||||
} else if (x > WORLD.width * TSIZE) {
|
||||
return WORLD.width * TSIZE
|
||||
} else {
|
||||
return x
|
||||
}
|
||||
@@ -452,8 +452,8 @@ object MapCamera {
|
||||
fun clampH(x: Int): Int {
|
||||
if (x < 0) {
|
||||
return 0
|
||||
} else if (x > map.height * TSIZE) {
|
||||
return map.height * TSIZE
|
||||
} else if (x > WORLD.height * TSIZE) {
|
||||
return WORLD.height * TSIZE
|
||||
} else {
|
||||
return x
|
||||
}
|
||||
@@ -462,8 +462,8 @@ object MapCamera {
|
||||
fun clampWTile(x: Int): Int {
|
||||
if (x < 0) {
|
||||
return 0
|
||||
} else if (x > map.width) {
|
||||
return map.width
|
||||
} else if (x > WORLD.width) {
|
||||
return WORLD.width
|
||||
} else {
|
||||
return x
|
||||
}
|
||||
@@ -472,8 +472,8 @@ object MapCamera {
|
||||
fun clampHTile(x: Int): Int {
|
||||
if (x < 0) {
|
||||
return 0
|
||||
} else if (x > map.height) {
|
||||
return map.height
|
||||
} else if (x > WORLD.height) {
|
||||
return WORLD.height
|
||||
} else {
|
||||
return x
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.torvald.terrarum.mapdrawer
|
||||
|
||||
import net.torvald.terrarum.gamemap.GameMap
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.tileproperties.TileNameCode
|
||||
import net.torvald.terrarum.tilestats.TileStats
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.torvald.terrarum.mapgenerator
|
||||
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.gamemap.GameMap
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.tileproperties.TileNameCode
|
||||
import com.jme3.math.FastMath
|
||||
import com.sudoplay.joise.Joise
|
||||
@@ -13,13 +13,13 @@ import java.util.*
|
||||
|
||||
object MapGenerator {
|
||||
|
||||
internal lateinit var map: GameMap
|
||||
internal lateinit var world: GameWorld
|
||||
internal lateinit var random: Random
|
||||
//private static float[] noiseArray;
|
||||
var SEED: Long = 0
|
||||
set(value) {
|
||||
field = value
|
||||
map.generatorSeed = value
|
||||
world.generatorSeed = value
|
||||
}
|
||||
var WIDTH: Int = 0
|
||||
var HEIGHT: Int = 0
|
||||
@@ -65,10 +65,10 @@ object MapGenerator {
|
||||
|
||||
internal val TILE_MACRO_ALL = -1
|
||||
|
||||
fun attachMap(map: GameMap) {
|
||||
this.map = map
|
||||
WIDTH = map.width
|
||||
HEIGHT = map.height
|
||||
fun attachMap(world: GameWorld) {
|
||||
this.world = world
|
||||
WIDTH = world.width
|
||||
HEIGHT = world.height
|
||||
|
||||
val widthMulFactor = WIDTH / 8192f
|
||||
|
||||
@@ -154,7 +154,7 @@ object MapGenerator {
|
||||
//wire layer
|
||||
for (i in 0..HEIGHT - 1) {
|
||||
for (j in 0..WIDTH - 1) {
|
||||
map.wireArray[i][j] = 0
|
||||
world.wireArray[i][j] = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,11 +486,11 @@ object MapGenerator {
|
||||
for (i in 0..HEIGHT - pillarOffset - 1) {
|
||||
|
||||
if (i < DIRT_LAYER_DEPTH) {
|
||||
map.setTileTerrain(x, i + pillarOffset, TileNameCode.DIRT)
|
||||
map.setTileWall(x, i + pillarOffset, TileNameCode.DIRT)
|
||||
world.setTileTerrain(x, i + pillarOffset, TileNameCode.DIRT)
|
||||
world.setTileWall(x, i + pillarOffset, TileNameCode.DIRT)
|
||||
} else {
|
||||
map.setTileTerrain(x, i + pillarOffset, TileNameCode.STONE)
|
||||
map.setTileWall(x, i + pillarOffset, TileNameCode.STONE)
|
||||
world.setTileTerrain(x, i + pillarOffset, TileNameCode.STONE)
|
||||
world.setTileWall(x, i + pillarOffset, TileNameCode.STONE)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -560,8 +560,8 @@ object MapGenerator {
|
||||
val tile =
|
||||
if (y < dirtStoneLine[x]) TileNameCode.DIRT
|
||||
else TileNameCode.STONE
|
||||
map.setTileTerrain(x, y, tile)
|
||||
map.setTileWall(x, y, tile)
|
||||
world.setTileTerrain(x, y, tile)
|
||||
world.setTileWall(x, y, tile)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,7 +603,7 @@ object MapGenerator {
|
||||
}
|
||||
|
||||
if (noise > filter.getGrad(y, filterStart, filterEnd) * scarcity) {
|
||||
map.setTileTerrain(x, y, tile)
|
||||
world.setTileTerrain(x, y, tile)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -633,8 +633,8 @@ object MapGenerator {
|
||||
}
|
||||
|
||||
if (noise > filter.getGrad(y, filterStart, filterEnd) * scarcity
|
||||
&& map.getTileFromTerrain(x, y) == replaceFrom) {
|
||||
map.setTileTerrain(x, y, replaceTo)
|
||||
&& world.getTileFromTerrain(x, y) == replaceFrom) {
|
||||
world.setTileTerrain(x, y, replaceTo)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -663,8 +663,8 @@ object MapGenerator {
|
||||
else -> throw(IllegalArgumentException("[mapgenerator] Unknown noise module type '${noisemap.javaClass.simpleName}': Only the 'Joise' or 'TaggedSimplexNoise' is valid."))
|
||||
}
|
||||
|
||||
if (noise > filter.getGrad(y, filterStart, filterEnd) * scarcity && map.getTileFromTerrain(x, y) == replaceFrom) {
|
||||
map.setTileTerrain(x, y, tile[random.nextInt(tile.size)])
|
||||
if (noise > filter.getGrad(y, filterStart, filterEnd) * scarcity && world.getTileFromTerrain(x, y) == replaceFrom) {
|
||||
world.setTileTerrain(x, y, tile[random.nextInt(tile.size)])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -721,8 +721,8 @@ object MapGenerator {
|
||||
private fun generateFloatingIslands() {
|
||||
println("[mapgenerator] Placing floating islands...")
|
||||
|
||||
val nIslandsMax = Math.round(map.width * 6f / 8192f)
|
||||
val nIslandsMin = Math.max(2, Math.round(map.width * 4f / 8192f))
|
||||
val nIslandsMax = Math.round(world.width * 6f / 8192f)
|
||||
val nIslandsMin = Math.max(2, Math.round(world.width * 4f / 8192f))
|
||||
val nIslands = random.nextInt(nIslandsMax - nIslandsMin) + nIslandsMin
|
||||
val prevIndex = -1
|
||||
|
||||
@@ -735,13 +735,13 @@ object MapGenerator {
|
||||
}
|
||||
val island = FloatingIslandsPreset.generatePreset(currentIndex, random)
|
||||
|
||||
val startingPosX = random.nextInt(map.width - 2048) + 1024
|
||||
val startingPosX = random.nextInt(world.width - 2048) + 1024
|
||||
val startingPosY = minimumFloatingIsleHeight + random.nextInt(minimumFloatingIsleHeight)
|
||||
|
||||
for (j in island.indices) {
|
||||
for (k in 0..island[0].size - 1) {
|
||||
if (island[j][k] > 0) {
|
||||
map.setTileTerrain(k + startingPosX, j + startingPosY, tiles[island[j][k]])
|
||||
world.setTileTerrain(k + startingPosX, j + startingPosY, tiles[island[j][k]])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -754,8 +754,8 @@ object MapGenerator {
|
||||
println("[mapgenerator] Flooding bottom lava...")
|
||||
for (i in HEIGHT * 14 / 15..HEIGHT - 1) {
|
||||
for (j in 0..WIDTH - 1) {
|
||||
if (map.terrainArray[i][j].toInt() == 0) {
|
||||
map.setTileTerrain(j, i, TileNameCode.LAVA)
|
||||
if (world.terrainArray[i][j].toInt() == 0) {
|
||||
world.setTileTerrain(j, i, TileNameCode.LAVA)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -773,18 +773,18 @@ object MapGenerator {
|
||||
*/
|
||||
|
||||
for (y in TERRAIN_AVERAGE_HEIGHT - TERRAIN_UNDULATION..TERRAIN_AVERAGE_HEIGHT + TERRAIN_UNDULATION - 1) {
|
||||
for (x in 0..map.width - 1) {
|
||||
for (x in 0..world.width - 1) {
|
||||
|
||||
val thisTile = map.getTileFromTerrain(x, y)
|
||||
val thisTile = world.getTileFromTerrain(x, y)
|
||||
|
||||
for (i in 0..8) {
|
||||
var nearbyWallTile: Int?
|
||||
nearbyWallTile = map.getTileFromWall(x + i % 3 - 1, y + i / 3 - 1)
|
||||
nearbyWallTile = world.getTileFromWall(x + i % 3 - 1, y + i / 3 - 1)
|
||||
|
||||
if (nearbyWallTile == null) break;
|
||||
|
||||
if (i != 4 && thisTile == TileNameCode.DIRT && nearbyWallTile == TileNameCode.AIR) {
|
||||
map.setTileTerrain(x, y, TileNameCode.GRASS)
|
||||
world.setTileTerrain(x, y, TileNameCode.GRASS)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -794,18 +794,18 @@ object MapGenerator {
|
||||
}
|
||||
|
||||
private fun isGrassOrDirt(x: Int, y: Int): Boolean {
|
||||
return map.getTileFromTerrain(x, y) == TileNameCode.GRASS || map.getTileFromTerrain(x, y) == TileNameCode.DIRT
|
||||
return world.getTileFromTerrain(x, y) == TileNameCode.GRASS || world.getTileFromTerrain(x, y) == TileNameCode.DIRT
|
||||
}
|
||||
|
||||
private fun replaceIfTerrain(ifTileRaw: Int, x: Int, y: Int, replaceTileRaw: Int) {
|
||||
if (map.getTileFromTerrain(x, y) == ifTileRaw) {
|
||||
map.setTileTerrain(x, y, replaceTileRaw)
|
||||
if (world.getTileFromTerrain(x, y) == ifTileRaw) {
|
||||
world.setTileTerrain(x, y, replaceTileRaw)
|
||||
}
|
||||
}
|
||||
|
||||
private fun replaceIfWall(ifTileRaw: Int, x: Int, y: Int, replaceTileRaw: Int) {
|
||||
if (map.getTileFromWall(x, y) == ifTileRaw) {
|
||||
map.setTileWall(x, y, replaceTileRaw)
|
||||
if (world.getTileFromWall(x, y) == ifTileRaw) {
|
||||
world.setTileWall(x, y, replaceTileRaw)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -837,11 +837,11 @@ object MapGenerator {
|
||||
if (ix < OCEAN_WIDTH) {
|
||||
if (worldOceanPosition == TYPE_OCEAN_LEFT) {
|
||||
for (y in getTerrainHeightFromHeightMap(OCEAN_WIDTH)..getTerrainHeightFromHeightMap(ix) - 1) {
|
||||
map.setTileTerrain(ix, y, TileNameCode.WATER)
|
||||
world.setTileTerrain(ix, y, TileNameCode.WATER)
|
||||
}
|
||||
} else if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
|
||||
for (y in getTerrainHeightFromHeightMap(map.width - 1 - OCEAN_WIDTH)..getTerrainHeightFromHeightMap(map.width - 1 - ix) - 1) {
|
||||
map.setTileTerrain(map.width - 1 - ix, y, TileNameCode.WATER)
|
||||
for (y in getTerrainHeightFromHeightMap(world.width - 1 - OCEAN_WIDTH)..getTerrainHeightFromHeightMap(world.width - 1 - ix) - 1) {
|
||||
world.setTileTerrain(world.width - 1 - ix, y, TileNameCode.WATER)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -852,15 +852,15 @@ object MapGenerator {
|
||||
val terrainPoint = getTerrainHeightFromHeightMap(ix)
|
||||
|
||||
|
||||
map.setTileTerrain(ix, terrainPoint + iy, thisSand)
|
||||
world.setTileTerrain(ix, terrainPoint + iy, thisSand)
|
||||
// clear grass and make the sheet thicker
|
||||
map.setTileTerrain(ix, terrainPoint + iy - 1, thisSand)
|
||||
world.setTileTerrain(ix, terrainPoint + iy - 1, thisSand)
|
||||
} else if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
|
||||
val terrainPoint = getTerrainHeightFromHeightMap(map.width - 1 - ix)
|
||||
val terrainPoint = getTerrainHeightFromHeightMap(world.width - 1 - ix)
|
||||
|
||||
map.setTileTerrain(map.width - 1 - ix, terrainPoint + iy, thisSand)
|
||||
world.setTileTerrain(world.width - 1 - ix, terrainPoint + iy, thisSand)
|
||||
// clear grass and make the sheet thicker
|
||||
map.setTileTerrain(map.width - 1 - ix, terrainPoint + iy - 1, thisSand)
|
||||
world.setTileTerrain(world.width - 1 - ix, terrainPoint + iy - 1, thisSand)
|
||||
}
|
||||
}
|
||||
ix++
|
||||
@@ -868,7 +868,7 @@ object MapGenerator {
|
||||
}
|
||||
|
||||
private fun freeze() {
|
||||
for (y in 0..map.height - 1 - 1) {
|
||||
for (y in 0..world.height - 1 - 1) {
|
||||
for (x in 0..getFrozenAreaWidth(y) - 1) {
|
||||
if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
|
||||
replaceIfTerrain(TileNameCode.DIRT, x, y, TileNameCode.SNOW)
|
||||
@@ -877,11 +877,11 @@ object MapGenerator {
|
||||
replaceIfWall(TileNameCode.DIRT, x, y, TileNameCode.SNOW)
|
||||
replaceIfWall(TileNameCode.STONE, x, y, TileNameCode.ICE_NATURAL)
|
||||
} else {
|
||||
replaceIfTerrain(TileNameCode.DIRT, map.width - 1 - x, y, TileNameCode.SNOW)
|
||||
replaceIfTerrain(TileNameCode.STONE, map.width - 1 - x, y, TileNameCode.ICE_NATURAL)
|
||||
replaceIfTerrain(TileNameCode.DIRT, world.width - 1 - x, y, TileNameCode.SNOW)
|
||||
replaceIfTerrain(TileNameCode.STONE, world.width - 1 - x, y, TileNameCode.ICE_NATURAL)
|
||||
|
||||
replaceIfWall(TileNameCode.DIRT, map.width - 1 - x, y, TileNameCode.SNOW)
|
||||
replaceIfWall(TileNameCode.STONE, map.width - 1 - x, y, TileNameCode.ICE_NATURAL)
|
||||
replaceIfWall(TileNameCode.DIRT, world.width - 1 - x, y, TileNameCode.SNOW)
|
||||
replaceIfWall(TileNameCode.STONE, world.width - 1 - x, y, TileNameCode.ICE_NATURAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -899,7 +899,7 @@ object MapGenerator {
|
||||
if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
|
||||
height = getTerrainHeightFromHeightMap(width)
|
||||
} else {
|
||||
height = getTerrainHeightFromHeightMap(map.width - 1 - width)
|
||||
height = getTerrainHeightFromHeightMap(world.width - 1 - width)
|
||||
}
|
||||
val k = width / FastMath.sqrt(height.toFloat())
|
||||
|
||||
@@ -948,8 +948,8 @@ object MapGenerator {
|
||||
&& Math.round(j + pointerX - halfBrushSize) < WIDTH - brushSize
|
||||
&& Math.round(i + pointerY - halfBrushSize) > brushSize
|
||||
&& Math.round(i + pointerY - halfBrushSize) < HEIGHT - brushSize) {
|
||||
if (map.terrainArray[Math.round(i + pointerY - halfBrushSize)][Math.round(j + pointerX - halfBrushSize)] == fillFrom.toByte()) {
|
||||
map.terrainArray[Math.round(i + pointerY - halfBrushSize)][Math.round(j + pointerX - halfBrushSize)] = fill.toByte()
|
||||
if (world.terrainArray[Math.round(i + pointerY - halfBrushSize)][Math.round(j + pointerX - halfBrushSize)] == fillFrom.toByte()) {
|
||||
world.terrainArray[Math.round(i + pointerY - halfBrushSize)][Math.round(j + pointerX - halfBrushSize)] = fill.toByte()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,15 +38,15 @@ class ThreadProcessNoiseLayers(val startIndex: Int, val endIndex: Int,
|
||||
for (i in 0..fromTerr.size - 1) {
|
||||
val fromTerrVariable = fromTerr[i]
|
||||
|
||||
if ((MapGenerator.map.getTileFromTerrain(x, y) == fromTerrVariable || fromTerrVariable == MapGenerator.TILE_MACRO_ALL)
|
||||
&& (MapGenerator.map.getTileFromWall(x, y) == fromWall || fromWall == MapGenerator.TILE_MACRO_ALL)) {
|
||||
MapGenerator.map.setTileTerrain(x, y, to)
|
||||
if ((MapGenerator.world.getTileFromTerrain(x, y) == fromTerrVariable || fromTerrVariable == MapGenerator.TILE_MACRO_ALL)
|
||||
&& (MapGenerator.world.getTileFromWall(x, y) == fromWall || fromWall == MapGenerator.TILE_MACRO_ALL)) {
|
||||
MapGenerator.world.setTileTerrain(x, y, to)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((MapGenerator.map.getTileFromTerrain(x, y) == fromTerr || fromTerr == MapGenerator.TILE_MACRO_ALL)
|
||||
&& (MapGenerator.map.getTileFromWall(x, y) == fromWall || fromWall == MapGenerator.TILE_MACRO_ALL)) {
|
||||
MapGenerator.map.setTileTerrain(x, y, to)
|
||||
else if ((MapGenerator.world.getTileFromTerrain(x, y) == fromTerr || fromTerr == MapGenerator.TILE_MACRO_ALL)
|
||||
&& (MapGenerator.world.getTileFromWall(x, y) == fromWall || fromWall == MapGenerator.TILE_MACRO_ALL)) {
|
||||
MapGenerator.world.setTileTerrain(x, y, to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ object RealEstateCodex {
|
||||
*
|
||||
* Note that a tile can have only ONE owner (as an Actor or Faction ID)
|
||||
*/
|
||||
private var ownershipRegistry: HashMap<Long, Long> = HashMap()
|
||||
private var ownershipRegistry: HashMap<Long, Int> = HashMap()
|
||||
|
||||
fun setOwner(tileX: Int, tileY: Int, refID: Long) {
|
||||
fun setOwner(tileX: Int, tileY: Int, refID: Int) {
|
||||
ownershipRegistry[RealEstateUtility.getAbsoluteTileNumber(tileX, tileY)] = refID
|
||||
}
|
||||
|
||||
@@ -22,6 +22,6 @@ object RealEstateCodex {
|
||||
ownershipRegistry.remove(RealEstateUtility.getAbsoluteTileNumber(tileX, tileY))
|
||||
}
|
||||
|
||||
fun getOwner(tileX: Int, tileY: Int): Long? =
|
||||
fun getOwner(tileX: Int, tileY: Int): Int? =
|
||||
ownershipRegistry[RealEstateUtility.getAbsoluteTileNumber(tileX, tileY)]
|
||||
}
|
||||
@@ -8,10 +8,10 @@ import net.torvald.terrarum.gameactors.faction.FactionCodex
|
||||
*/
|
||||
object RealEstateUtility {
|
||||
fun getAbsoluteTileNumber(x: Int, y: Int): Long =
|
||||
(Terrarum.ingame.map.width * y).toLong() + x
|
||||
(Terrarum.ingame.world.width * y).toLong() + x
|
||||
|
||||
fun resolveAbsoluteTileNumber(t: Long): Pair<Int, Int> =
|
||||
Pair((t % Terrarum.ingame.map.width).toInt(), (t / Terrarum.ingame.map.width).toInt())
|
||||
Pair((t % Terrarum.ingame.world.width).toInt(), (t / Terrarum.ingame.world.width).toInt())
|
||||
|
||||
/**
|
||||
* Get owner ID as an Actor/Faction
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gamemap.WorldTime
|
||||
import net.torvald.terrarum.mapdrawer.LightmapRenderer
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-06-16.
|
||||
@@ -92,8 +93,8 @@ object TilePropUtil {
|
||||
fun getDynamicLumFunc(baseLum: Int, type: Int): Int {
|
||||
return when (type) {
|
||||
1 -> getTorchFlicker(baseLum)
|
||||
2 -> Terrarum.ingame.map.globalLight // current global light
|
||||
3 -> Terrarum.ingame.globalLightByTime(WorldTime.DAY_LENGTH / 2) // daylight at noon
|
||||
2 -> Terrarum.ingame.world.globalLight // current global light
|
||||
3 -> WeatherMixer.getGlobalLightOfTime(WorldTime.DAY_LENGTH / 2).toInt() // daylight at noon
|
||||
4 -> getSlowBreath(baseLum)
|
||||
5 -> getPulsate(baseLum)
|
||||
else -> baseLum
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.torvald.terrarum.tilestats
|
||||
|
||||
import net.torvald.terrarum.gameactors.Player
|
||||
import net.torvald.terrarum.gamemap.GameMap
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.gamemap.MapLayer
|
||||
import net.torvald.terrarum.mapdrawer.MapCamera
|
||||
import net.torvald.terrarum.mapdrawer.MapDrawer
|
||||
@@ -15,7 +15,7 @@ import java.util.Arrays
|
||||
*/
|
||||
object TileStats {
|
||||
|
||||
private val tilestat = ShortArray(GameMap.TILES_SUPPORTED)
|
||||
private val tilestat = ShortArray(GameWorld.TILES_SUPPORTED)
|
||||
|
||||
private val TSIZE = MapDrawer.TILE_SIZE
|
||||
|
||||
@@ -27,7 +27,7 @@ object TileStats {
|
||||
|
||||
// Get stats on no-zoomed screen area. In other words, will behave as if screen zoom were 1.0
|
||||
// no matter how the screen is zoomed.
|
||||
val map = Terrarum.ingame.map
|
||||
val map = Terrarum.ingame.world
|
||||
val player = Terrarum.ingame.player
|
||||
|
||||
val renderWidth = FastMath.ceil(Terrarum.WIDTH.toFloat())
|
||||
|
||||
@@ -114,7 +114,7 @@ class BasicDebugInfoWindow:UICanvas {
|
||||
printLine(g, 7, "light@cursor $ccG$lightVal")
|
||||
|
||||
val tileNo: String
|
||||
val tileNumRaw = Terrarum.ingame.map.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1
|
||||
val tileNumRaw = Terrarum.ingame.world.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1
|
||||
val tilenum = tileNumRaw / PairedMapLayer.RANGE
|
||||
val tiledmg = tileNumRaw % PairedMapLayer.RANGE
|
||||
tileNo = if (tileNumRaw == -1) "—" else "$tilenum:$tiledmg"
|
||||
@@ -127,8 +127,8 @@ class BasicDebugInfoWindow:UICanvas {
|
||||
|
||||
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.ingame.map.worldTime.elapsedSeconds()}" +
|
||||
" (${Terrarum.ingame.map.worldTime.getFormattedTime()})")
|
||||
printLineColumn(g, 2, 5, "Time $ccG${Terrarum.ingame.world.time.elapsedSeconds()}" +
|
||||
" (${Terrarum.ingame.world.time.getFormattedTime()})")
|
||||
printLineColumn(g, 2, 6, "Mass $ccG${player.mass}")
|
||||
|
||||
drawHistogram(g, LightmapRenderer.histogram,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.ui
|
||||
|
||||
import net.torvald.gadgets.HistoryArray
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.console.CommandInterpreter
|
||||
@@ -16,16 +17,16 @@ class ConsoleWindow : UICanvas, UITypable {
|
||||
|
||||
internal var UIColour = Color(0xCC000000.toInt())
|
||||
|
||||
private var commandInputPool: StringBuilder? = null
|
||||
private var prevCommand: String? = null
|
||||
|
||||
private var inputCursorPos: Int = 0
|
||||
|
||||
private val MESSAGES_MAX = 5000
|
||||
private val COMMAND_HISTORY_MAX = 100
|
||||
private var messages = Array(MESSAGES_MAX, {""})
|
||||
private var messageDisplayPos: Int = 0
|
||||
private var messagesCount: Int = 0
|
||||
|
||||
private var commandInputPool: StringBuilder? = null
|
||||
private var commandHistory = HistoryArray<String>(COMMAND_HISTORY_MAX)
|
||||
|
||||
private val LINE_HEIGHT = 20
|
||||
private val MESSAGES_DISPLAY_COUNT = 9
|
||||
|
||||
@@ -38,6 +39,9 @@ class ConsoleWindow : UICanvas, UITypable {
|
||||
private var drawOffY: Float = -height.toFloat()
|
||||
private var openingTimeCounter = 0
|
||||
|
||||
|
||||
private var historyIndex = -1
|
||||
|
||||
init {
|
||||
reset()
|
||||
}
|
||||
@@ -70,15 +74,25 @@ class ConsoleWindow : UICanvas, UITypable {
|
||||
|
||||
|
||||
override fun keyPressed(key: Int, c: Char) {
|
||||
// history
|
||||
if (key == Key.UP && historyIndex < commandHistory.history.size)
|
||||
historyIndex++
|
||||
else if (key == Key.DOWN && historyIndex >= 0)
|
||||
historyIndex--
|
||||
else if (key != Key.UP && key != Key.DOWN)
|
||||
historyIndex = -1
|
||||
|
||||
// execute
|
||||
if (key == Key.RET && commandInputPool!!.length > 0) {
|
||||
prevCommand = commandInputPool!!.toString()
|
||||
commandHistory.add(commandInputPool!!.toString())
|
||||
executeCommand()
|
||||
commandInputPool = StringBuilder()
|
||||
}
|
||||
else if (key == Key.BKSP && commandInputPool!!.length > 0) {
|
||||
// erase last letter
|
||||
else if (key == Key.BACKSPACE && commandInputPool!!.length > 0) {
|
||||
commandInputPool!!.deleteCharAt(commandInputPool!!.length - 1)
|
||||
}
|
||||
// append acceptable letter
|
||||
else if (key >= 2 && key <= 13
|
||||
|| key >= 16 && key <= 27
|
||||
|| key >= 30 && key <= 40
|
||||
@@ -87,20 +101,25 @@ class ConsoleWindow : UICanvas, UITypable {
|
||||
commandInputPool!!.append(c)
|
||||
inputCursorPos += 1
|
||||
}
|
||||
else if (key == Key.UP) {
|
||||
// scroll
|
||||
else if (key == Key.UP || key == Key.DOWN) {
|
||||
// create new stringbuilder
|
||||
commandInputPool = StringBuilder()
|
||||
commandInputPool!!.append(prevCommand)
|
||||
if (historyIndex >= 0) // just leave blank if index is -1
|
||||
commandInputPool!!.append(commandHistory[historyIndex] ?: "")
|
||||
}
|
||||
// delete input
|
||||
else if (key == Key.DELETE) {
|
||||
commandInputPool = StringBuilder()
|
||||
}
|
||||
// message scroll up
|
||||
else if (key == Key.PGUP) {
|
||||
setDisplayPos(-MESSAGES_DISPLAY_COUNT + 1)
|
||||
}
|
||||
// message scroll down
|
||||
else if (key == Key.PGDN) {
|
||||
setDisplayPos(MESSAGES_DISPLAY_COUNT - 1)
|
||||
}// scroll down
|
||||
// scroll up
|
||||
// prev command
|
||||
// get input
|
||||
// backspace
|
||||
}
|
||||
}
|
||||
|
||||
override fun keyReleased(key: Int, c: Char) {
|
||||
@@ -148,7 +167,7 @@ class ConsoleWindow : UICanvas, UITypable {
|
||||
messageDisplayPos = 0
|
||||
messagesCount = 0
|
||||
inputCursorPos = 0
|
||||
prevCommand = ""
|
||||
commandHistory = HistoryArray<String>(COMMAND_HISTORY_MAX)
|
||||
commandInputPool = StringBuilder()
|
||||
|
||||
if (Terrarum.ingame.auth.b()) sendMessage(Lang["DEV_MESSAGE_CONSOLE_CODEX"])
|
||||
|
||||
@@ -54,7 +54,8 @@ constructor(val UI: UICanvas) {
|
||||
println("[UIHandler] Creating UI '${UI.javaClass.simpleName}'")
|
||||
|
||||
UIDrawnCanvas = Image(
|
||||
FastMath.nearestPowerOfTwo(UI.width), FastMath.nearestPowerOfTwo(UI.height))
|
||||
//FastMath.nearestPowerOfTwo(UI.width), FastMath.nearestPowerOfTwo(UI.height))
|
||||
UI.width, UI.height)
|
||||
|
||||
UIGraphicInstance = UIDrawnCanvas.graphics
|
||||
}
|
||||
|
||||
18
src/net/torvald/terrarum/weather/BaseModularWeather.kt
Normal file
@@ -0,0 +1,18 @@
|
||||
package net.torvald.terrarum.weather
|
||||
|
||||
import org.newdawn.slick.Image
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Note: Colour maps are likely to have sparse data points
|
||||
* (i.e., they have 2 475 px in width and you'll need 79 200 data points for a day)
|
||||
* so between two must be interpolated.
|
||||
*
|
||||
* Created by minjaesong on 16-07-11.
|
||||
*/
|
||||
data class BaseModularWeather(
|
||||
val globalLightColourMap: Image,
|
||||
var skyboxGradColourMap: Image,
|
||||
val classification: String,
|
||||
var extraImages: ArrayList<Image>
|
||||
)
|
||||
155
src/net/torvald/terrarum/weather/WeatherMixer.kt
Normal file
@@ -0,0 +1,155 @@
|
||||
package net.torvald.terrarum.weather
|
||||
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.JsonFetcher
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gamemap.WorldTime
|
||||
import net.torvald.terrarum.mapdrawer.Light10B
|
||||
import org.newdawn.slick.Color
|
||||
import org.newdawn.slick.GameContainer
|
||||
import org.newdawn.slick.Graphics
|
||||
import org.newdawn.slick.Image
|
||||
import org.newdawn.slick.fills.GradientFill
|
||||
import org.newdawn.slick.geom.Rectangle
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Current, next are there for cross-fading two weathers
|
||||
*
|
||||
* Created by minjaesong on 16-07-11.
|
||||
*/
|
||||
object WeatherMixer {
|
||||
lateinit var weatherList: ArrayList<BaseModularWeather>
|
||||
|
||||
lateinit var currentWeather: BaseModularWeather
|
||||
lateinit var nextWeather: BaseModularWeather
|
||||
|
||||
private var skyBoxCurrent = Rectangle(0f, 0f, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
||||
private var skyBoxNext = Rectangle(0f, 0f, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
||||
val globalLightNow = Light10B(0)
|
||||
|
||||
// Weather indices
|
||||
const val WEATHER_GENERIC = 0
|
||||
// TODO add weather indices manually
|
||||
|
||||
const val RAW_DIR = "./res/raw/weathers"
|
||||
|
||||
init {
|
||||
weatherList = ArrayList()
|
||||
|
||||
// TODO read weather descriptions from res/weather (modular weather)
|
||||
// test: read only one
|
||||
weatherList.add(readFromJson("$RAW_DIR/WeatherGeneric.json"))
|
||||
|
||||
// initialise
|
||||
currentWeather = weatherList[WEATHER_GENERIC]
|
||||
// nextWeather = %&)(@$*%&$(*%
|
||||
}
|
||||
|
||||
fun update(gc: GameContainer, delta: Int) {
|
||||
currentWeather = weatherList[WEATHER_GENERIC]
|
||||
|
||||
}
|
||||
|
||||
fun render(g: Graphics) {
|
||||
|
||||
// we will not care for nextSkybox for now
|
||||
val timeNow = Terrarum.ingame.world.time.elapsedSeconds()
|
||||
val skyboxColourMap = currentWeather.skyboxGradColourMap
|
||||
val lightColourMap = currentWeather.globalLightColourMap
|
||||
|
||||
// draw skybox to provided (should be main) graphics instance
|
||||
val skyColourFill = GradientFill(
|
||||
0f, 0f,
|
||||
getGradientColour(skyboxColourMap, 0, timeNow),
|
||||
0f, Terrarum.HEIGHT.toFloat(),
|
||||
getGradientColour(skyboxColourMap, 1, timeNow)
|
||||
)
|
||||
g.fill(skyBoxCurrent, skyColourFill)
|
||||
|
||||
// calculate global light
|
||||
globalLightNow.fromSlickColor(getGradientColour(lightColourMap, 0, timeNow))
|
||||
}
|
||||
|
||||
fun getGlobalLightOfTime(timeInSec: Int): Light10B =
|
||||
Light10B(getGradientColour(currentWeather.globalLightColourMap, 0, timeInSec))
|
||||
|
||||
fun getGradientColour(image: Image, row: Int, timeInSec: Int): Color {
|
||||
val gradMapWidth = image.width
|
||||
val phaseThis = Math.round(
|
||||
timeInSec.toFloat() / WorldTime.DAY_LENGTH.toFloat() * gradMapWidth
|
||||
)
|
||||
val phaseNext = (phaseThis + 1) % WorldTime.DAY_LENGTH
|
||||
val dataPointDistance = WorldTime.DAY_LENGTH / image.width
|
||||
|
||||
val colourThis = image.getColor(phaseThis, row)
|
||||
val colourNext = image.getColor(phaseNext, row)
|
||||
|
||||
// interpolate R, G and B
|
||||
val scale = (timeInSec % dataPointDistance).toFloat() / dataPointDistance
|
||||
val retColour = Color(0)
|
||||
retColour.r = FastMath.interpolateLinear(scale, colourThis.r, colourNext.r)
|
||||
retColour.g = FastMath.interpolateLinear(scale, colourThis.g, colourNext.g)
|
||||
retColour.b = FastMath.interpolateLinear(scale, colourThis.b, colourNext.b)
|
||||
|
||||
return retColour
|
||||
}
|
||||
|
||||
fun readFromJson(path: String): BaseModularWeather {
|
||||
/* JSON structure:
|
||||
{
|
||||
"globalLight": "colourmap/sky_colour.png", // integer for static, string (path to image) for dynamic
|
||||
"skyboxGradColourMap": "colourmap/sky_colour.png", // integer for static, string (path to image) for dynamic
|
||||
"extraImages": [
|
||||
// if any, it will be like:
|
||||
sun01.png,
|
||||
clouds01.png,
|
||||
clouds02.png,
|
||||
auroraBlueViolet.png
|
||||
]
|
||||
}
|
||||
*/
|
||||
val pathToImage = "./res/graphics/weathers"
|
||||
|
||||
val JSON = JsonFetcher.readJson(path)
|
||||
|
||||
val globalLightInJson = JSON.get("globalLight").asJsonPrimitive
|
||||
val skyboxInJson = JSON.get("skyboxGradColourMap").asJsonPrimitive
|
||||
val extraImagesPath = JSON.getAsJsonArray("extraImages")
|
||||
|
||||
val globalLight: Image
|
||||
val skybox: Image
|
||||
val extraImages = ArrayList<Image>()
|
||||
val classification = JSON.get("classification").asJsonPrimitive.asString
|
||||
|
||||
// parse globalLight
|
||||
if (globalLightInJson.isString)
|
||||
globalLight = Image("$pathToImage/${globalLightInJson.asString}")
|
||||
else if (globalLightInJson.isNumber) {
|
||||
// make 1x1 image with specified colour
|
||||
globalLight = Image(1, 1)
|
||||
globalLight.graphics.color = Color(globalLightInJson.asNumber.toInt())
|
||||
globalLight.graphics.fillRect(0f, 0f, 1f, 1f)
|
||||
}
|
||||
else
|
||||
throw IllegalStateException("In weather descriptor $path -- globalLight seems malformed.")
|
||||
|
||||
// parse skyboxGradColourMap
|
||||
if (skyboxInJson.isString)
|
||||
skybox = Image("$pathToImage/${skyboxInJson.asString}")
|
||||
else if (globalLightInJson.isNumber) {
|
||||
// make 1x2 image with specified colour
|
||||
skybox = Image(1, 2)
|
||||
skybox.graphics.color = Color(skyboxInJson.asNumber.toInt())
|
||||
skybox.graphics.fillRect(0f, 0f, 1f, 2f)
|
||||
}
|
||||
else
|
||||
throw IllegalStateException("In weather descriptor $path -- skyboxGradColourMap seems malformed.")
|
||||
|
||||
// get extra images
|
||||
for (i in extraImagesPath)
|
||||
extraImages.add(Image("$pathToImage/$i"))
|
||||
|
||||
return BaseModularWeather(globalLight, skybox, classification, extraImages)
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,12 @@
|
||||
</imagelayer>
|
||||
<layer name="Wall" width="512" height="100">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzt2TEOwjAQRcEYTsL9L4loECBsLGC9gZ2RfpUi7p6jbBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQ4dTaddWeAUBVe+qx/gNAjNseVhsAVJXd4MwBQFXZDc4cAFSV3eDMAUBV2Q2+rB3vt+q9AFDVqtY+22P3V98DAKCq6Mb29qr9K+4AAFBVZF9H038AyBPZ19H0HwDyRPZ1NP0HgDyRfR1N/wEgT6+Lo2Z+49ls/yPPAgBV6T8A1KP/AFBPr5HR8/8fAPJE9nU0/QeAtSKbOjv9B4C1Ips6O/0HgLUimzo7/QeAtSKbOrs2ucgzAMCva4d2t1mRfR3N9z8AfO7d/u+d/gNAn/5rPwD1/Gv/AYA+/QcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPnEGIseuBw==
|
||||
eJzt2TEOwjAURMEYTsT9L4egQKQwigD7G3ZG2spNuufI2wYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUuLT2WNoZAKRaqcf6DwBjPPcwbQCQqrrB+g8A81U3WP8BYL7qBus/AMxX3eDb2nk//QeAsVbq/ux7AACkWrX9M+4AAJBK/wEgj/4DQB79B4A8+g8AeXpdfNXMb5wd7f/IbwGAVPoPAHn0HwDy9Bo5et7/AaCO/gNAhqrm6z8A1Kluv/4DwHzV7dd/AJivuv33/h+c/gNAXzu13Y7y/w8Av+vd/q9O/wGgT/+1H4A8/9p/AKBP/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAT1wBJRX8Bw==
|
||||
</data>
|
||||
</layer>
|
||||
<layer name="Terrain" width="512" height="100">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzt3WtrE0EYhuHdtKhEWvCAYL7VA1LB///3TNDFsG7SPUx23p25brjwS9VASZ7ZNEmbRpIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSVIJvd/lvgWSJGntTvvvDCBJUj2ddr+1/5IkVZX9lySprrrtb50BJEmqpv7+OwNIklR2Q9vf7b8zgCRJZXZp/50BpHr72TbNl6Nvbe5bIukWXdt+PweQ6u35uPtPR1/tv1RU3XX9S9vvDCDVmf2XymvK7jsDSHVm/6Vt1F3PjzFn+9vev9H/fyWVlf2X4rdk01OcBTw3IJWX/ZfitvR6PvV5QFI5Rdv//V3TvPrr/i73rZHyFWn77b9UXlH2v9v912eb/+AcoEqLtv3OAFJ55d7/x4Hd7/fgDKCKirr99l8qq9z7P7a39l+FF3n3nQGk8rL/Up5SvWfPGUDSnOy/dL3D7v+tHnKtlO/Rj8D+S9sv5/5/2DfNp/2fbf94/PPdBd3XSGt3mLiJt/hMnojsv7T9Ilz/j9l2+68cfQ6wtVGNfe5Dqq2t3C/svzTclGv/2m3l8U5K1Zjn+iLdL7rf9Xvuyf5Lg7n2dwaQ+s35mV6Ens/2vs/+S/9y7Z/+DOBsoK2V6nU8Efp13PjvF/zIvP9e/6co2f40Z4Chx03PEShSa71mV8M9vvDZf12nzwB84wygG3ZIfJ/n+vkgUlN+t/KU930qfxHekyMpbq75850Dcu5rii1wFohXtPfdSopT/zN9cj8+cNmSa/O1P5PhlrfV8xDD5byuH0vSul373L7cjweQUmnnhZxnuCjfn9T67/3r263g/ux1hvuFf19lNvbzdkt4XIBccu+R++66Lr33r7PW7ei2vJ3JOWFeqXbVfR9gW6Ls/1qWPj9R2u7m/n4AkEdt+z/X3J9t2F0AIrL/AFAf+w8A9bH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAq/AQvXoTU=
|
||||
eJzt3dtu00AUhlG7rQAFtRJQIZG34Ir3fzOIiqViHMdxJt7bM+uTlrjhEKlK/nFOdJ0kSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZKkGvr6EH0LJEnS1p323xlAkqR2Ou1+b/8lSWoq+y9JUlsN2987A0iS1Ezj/XcGkCSp7qa2f9h/ZwBJkurs3P47A0jt9rN/86uPviWS7tHc9nsdQGo3+y/V2XBdf2n7nQGkNrP/Un1ds/vOAFKb2X9pHw3X80us2f5+9HeM/11JdWX/pfzdsuklzgKeG5Dqy/5Lebv1er70eUBSPWXb/8Nj13346+kx+tZIcWXafvsv1VeW/R92/+O7zX92DlCjZdt+ZwCpvqL3/2Vi98c9OwOoobJuv/2X6ip6/5f22f6r8jLvvjOAVF/2X4qp1Gf2nAEkrcn+S/MdH/7f6ilzlfyMfgb2X9p/kfv/7dB13w9v2/7659cvZwy/R9q645WbeI/v5MnI/kv7L8P1/5Jtt/+K6EeCrc1q6XMfUmvt5X5h/6Xprrn2b91eHu+kUi15ri/T/WLY+in2X/o31/7OANK4Na/pZcj+S8ty7V/+DOBsoL1V6n08Gcq8/97/pyzZ/jJngKnHTc8RKFNbvWdX071c+O6/odN3AH5yBtAdOxa+zzN/PsjUNf+38jWf+1R8GT6TIylvrvnjzgGR+1piC5wF8pXtc7eS8jT+Tp/oxwfOu+XafOvvZLjnbfU8xHSR1/VLSdq2ue/ti348gJJqOy9EnuGy/HxKm3v/38nDBp7evc/wcOOfV50t/b7dGh4XIEr0HrnvbuvS/m91O4Yt71dyTlhXqV113wfYlyz7v5Vbn5+obXejfx4AxGht/9da+9qG3QUgI/sPAO2x/wDQHvsPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlPAbDVyojQ==
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
||||
|
||||