font bug sorta fixed, new splash: warning health and safety
Former-commit-id: f79503873f57e781480fa742ed1a058becb6c7a1 Former-commit-id: daeeed816b339958786746c3717670c724676a44
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 872 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 123 B |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 122 B |
BIN
assets/graphics/gui/health_distance.png
Normal file
|
After Width: | Height: | Size: 504 B |
BIN
assets/graphics/gui/health_take_a_break.png
Normal file
|
After Width: | Height: | Size: 579 B |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
assets/graphics/weathers/raindrop.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
10
assets/raw/weathers/WeatherGenericRain.json.asrtinears
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"globalLight": "generic_light.png",
|
||||
"skyboxGradColourMap": "generic_skybox.png",
|
||||
"classification": "genericrain",
|
||||
"extraImages": [
|
||||
"raindrop.png"
|
||||
],
|
||||
"mixFrom": "__CURRENTWEATHER",
|
||||
"mixPercentage": 80.0
|
||||
}
|
||||
1
assets/sounds/test/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.{psd,tga,ogg} filter=lfs diff=lfs merge=lfs -text
|
||||
BIN
assets/sounds/test/2ND_PM.xm
Normal file
BIN
assets/sounds/test/GSLINGER.MOD
Normal file
BIN
assets/sounds/test/bad_apple.xm
Normal file
BIN
assets/sounds/test/bb.xm
Normal file
BIN
assets/sounds/test/keys_to_imagination.mod
Normal file
BIN
assets/sounds/test/zelda_fds.xm
Normal file
@@ -154,11 +154,6 @@ constructor() : Font {
|
||||
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)
|
||||
@@ -168,8 +163,8 @@ constructor() : Font {
|
||||
for (i in 0..endIndex - 1) {
|
||||
val ctype = getSheetType(s[i])
|
||||
|
||||
if (i > 0 && s[i].toInt() > 0x20) {
|
||||
// Unihan-hangul Kerning
|
||||
/*if (i > 0 && s[i].toInt() > 0x20) {
|
||||
// inter-Unihan-hangul Kerning
|
||||
val cpre = getSheetType(s[i - 1])
|
||||
if ((unihanWidthSheets.contains(cpre) || cpre == SHEET_HANGUL) && !(unihanWidthSheets.contains(ctype) || ctype == SHEET_HANGUL)
|
||||
|
||||
@@ -182,18 +177,22 @@ constructor() : Font {
|
||||
len += 1
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
if (zeroWidthSheets.contains(ctype))
|
||||
len += 0
|
||||
else if (narrowWidthSheets.contains(ctype))
|
||||
len += W_LATIN_NARROW
|
||||
else if (cjkWidthSheets.contains(ctype))
|
||||
len += W_CJK
|
||||
else if (ctype == SHEET_CJK_PUNCT)
|
||||
len += W_ASIAN_PUNCT
|
||||
else if (ctype == SHEET_HANGUL)
|
||||
len += W_HANGUL
|
||||
else if (ctype == SHEET_KANA)
|
||||
len += W_KANA
|
||||
else if (unihanWidthSheets.contains(ctype))
|
||||
len += W_UNIHAN
|
||||
else if (isThaiDiacritics(s[i]))
|
||||
len = len // set width of the glyph as -W_LATIN_WIDE
|
||||
len += 0 // set width of the glyph as -W_LATIN_WIDE
|
||||
else
|
||||
len += W_LATIN_WIDE
|
||||
|
||||
@@ -237,7 +236,7 @@ constructor() : Font {
|
||||
val jungRow = getHanMedialRow(hIndex)
|
||||
val jongRow = getHanFinalRow(hIndex)
|
||||
|
||||
val glyphW = getWidth("" + ch)
|
||||
val glyphW = getWidth(ch.toString())
|
||||
|
||||
/*// initials
|
||||
hangulSheet.renderInUse(
|
||||
@@ -453,11 +452,11 @@ constructor() : Font {
|
||||
sheetX, sheetY
|
||||
)*/
|
||||
sheetKey[prevInstance]!!.getSubImage(sheetX, sheetY).draw(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat() // Interchar: pull punct right next to hangul to the left
|
||||
+ if (i > 0 && isHangul(s[i - 1])) -3f
|
||||
else 0f,
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
|
||||
// to deal with the height difference of the sheets
|
||||
Math.round(y).toFloat() + (if (prevInstance == SHEET_CJK_PUNCT) -1
|
||||
|
||||
else if (prevInstance == SHEET_FW_UNI) (H - H_HANGUL) / 2
|
||||
else 0).toFloat(),
|
||||
|
||||
@@ -589,10 +588,13 @@ constructor() : Font {
|
||||
internal val JUNG_COUNT = 21
|
||||
internal val JONG_COUNT = 28
|
||||
|
||||
internal val W_CJK = 10
|
||||
internal val W_ASIAN_PUNCT = 10
|
||||
internal val W_HANGUL = 11
|
||||
internal val W_KANA = 12
|
||||
internal val W_UNIHAN = 16
|
||||
internal val W_LATIN_WIDE = 9 // width of regular letters, including m
|
||||
internal val W_LATIN_NARROW = 5 // width of letter f, t, i, l
|
||||
|
||||
internal val H = 20
|
||||
internal val H_HANGUL = 16
|
||||
internal val H_UNIHAN = 16
|
||||
|
||||
@@ -12,7 +12,7 @@ constructor() : GameFontBase() {
|
||||
init {
|
||||
|
||||
GameFontBase.hangulSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/han_johab.png", GameFontBase.W_CJK, GameFontBase.H_HANGUL)
|
||||
"./assets/graphics/fonts/han_johab.png", GameFontBase.W_HANGUL, GameFontBase.H_HANGUL)
|
||||
GameFontBase.asciiSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/ascii_fullwidth.png", GameFontBase.W_LATIN_WIDE, GameFontBase.H)
|
||||
GameFontBase.asciiSheetEF = SpriteSheet(
|
||||
@@ -24,9 +24,9 @@ constructor() : GameFontBase() {
|
||||
GameFontBase.extASheetEF = SpriteSheet(
|
||||
"./assets/graphics/fonts/LatinExtA_ef.png", GameFontBase.W_LATIN_NARROW, GameFontBase.H)
|
||||
GameFontBase.kanaSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/kana.png", GameFontBase.W_CJK, GameFontBase.H_KANA)
|
||||
"./assets/graphics/fonts/kana.png", GameFontBase.W_KANA, GameFontBase.H_KANA)
|
||||
GameFontBase.cjkPunct = SpriteSheet(
|
||||
"./assets/graphics/fonts/cjkpunct.png", GameFontBase.W_CJK, GameFontBase.H_KANA)
|
||||
"./assets/graphics/fonts/cjkpunct.png", GameFontBase.W_ASIAN_PUNCT, GameFontBase.H_KANA)
|
||||
/*uniHan = new SpriteSheet(
|
||||
"./assets/graphics/fonts/unifont_unihan"
|
||||
+ ((!terrarum.gameLocale.contains("zh"))
|
||||
|
||||
@@ -58,6 +58,8 @@ object DefaultConfig {
|
||||
|
||||
jsonObject.addProperty("pcgamepadenv", "console")
|
||||
|
||||
jsonObject.addProperty("safetywarning", true)
|
||||
|
||||
|
||||
return jsonObject
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import net.torvald.imagefont.GameFontWhite
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import org.newdawn.slick.Font
|
||||
import org.newdawn.slick.GameContainer
|
||||
import org.newdawn.slick.Graphics
|
||||
@@ -20,6 +21,8 @@ class StateFontTester : BasicGameState() {
|
||||
canvas = Graphics(1024, 1024)
|
||||
|
||||
gameFont = GameFontWhite()
|
||||
|
||||
Terrarum.gameLocale = "fiFI"
|
||||
}
|
||||
|
||||
override fun update(gc: GameContainer, game: StateBasedGame, delta: Int) {
|
||||
@@ -28,7 +31,21 @@ class StateFontTester : BasicGameState() {
|
||||
|
||||
override fun render(gc: GameContainer, game: StateBasedGame, g: Graphics) {
|
||||
g.font = gameFont
|
||||
g.drawString(textToPrint, 10f, 10f)
|
||||
|
||||
val text = arrayOf(
|
||||
Lang["APP_WARNING_HEALTH_AND_SAFETY"],
|
||||
"",
|
||||
"90’ 10’ 20” 50 cm",
|
||||
"",
|
||||
"",
|
||||
Lang["MENU_LABEL_PRESS_ANYKEY_CONTINUE"],
|
||||
"DGB금융지주의 자회사. 대구광역시에서 쓰는 교통카드인 원패스와 탑패스 그리고 만악의 근원 대경교통카드를 판매 및 정산하고 있다. 본사는",
|
||||
"Atlantic Records, it features production from Nick Hexum of 311, Tony Kanal of No Doubt, and Sublime producer Paul Leary."
|
||||
)
|
||||
|
||||
for (i in 0..text.size - 1) {
|
||||
g.drawString(text[i], 10f, 10f + (g.font.lineHeight * i))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getID(): Int = Terrarum.SCENE_ID_TEST_FONT
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.torvald.terrarum.gamecontroller.Key
|
||||
import net.torvald.terrarum.gamecontroller.KeyMap
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.gamemap.WorldSimulator
|
||||
import net.torvald.terrarum.gamemap.WorldTime
|
||||
import net.torvald.terrarum.mapdrawer.LightmapRenderer
|
||||
import net.torvald.terrarum.mapdrawer.MapCamera
|
||||
@@ -161,38 +162,56 @@ constructor() : BasicGameState() {
|
||||
|
||||
setAppTitle()
|
||||
|
||||
///////////////////////////
|
||||
// world-related updates //
|
||||
///////////////////////////
|
||||
world.updateWorldTime(delta)
|
||||
|
||||
WorldSimulator(world, player, delta)
|
||||
WeatherMixer.update(gc, delta)
|
||||
|
||||
world.globalLight = globalLightByTime.toInt()
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// input-related updates //
|
||||
///////////////////////////
|
||||
GameController.processInput(gc.input)
|
||||
uiContainer.forEach { it.processInput(gc.input) }
|
||||
|
||||
|
||||
TileStats.update()
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// camera-related updates //
|
||||
////////////////////////////
|
||||
MapDrawer.update(gc, delta)
|
||||
MapCamera.update(gc, delta)
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// actor-related updates //
|
||||
///////////////////////////
|
||||
// determine whether the inactive actor should be re-active
|
||||
wakeDormantActors()
|
||||
|
||||
// determine whether the actor should be active or dormant
|
||||
InactivateDistantActors()
|
||||
|
||||
updateActors(gc, delta)
|
||||
|
||||
// TODO thread pool(?)
|
||||
CollisionSolver.process()
|
||||
|
||||
|
||||
////////////////////////
|
||||
// ui-related updates //
|
||||
////////////////////////
|
||||
uiContainer.forEach { ui -> ui.update(gc, delta) }
|
||||
consoleHandler.update(gc, delta)
|
||||
debugWindow.update(gc, delta)
|
||||
|
||||
|
||||
notifier.update(gc, delta)
|
||||
|
||||
|
||||
/////////////////////////
|
||||
// app-related updates //
|
||||
/////////////////////////
|
||||
Terrarum.appgc.setVSync(Terrarum.appgc.fps >= Terrarum.VSYNC_TRIGGER_THRESHOLD)
|
||||
}
|
||||
|
||||
@@ -204,8 +223,6 @@ constructor() : BasicGameState() {
|
||||
}
|
||||
|
||||
override fun render(gc: GameContainer, sbg: StateBasedGame, g: Graphics) {
|
||||
g.setAntiAlias(true)
|
||||
|
||||
setBlendNormal()
|
||||
|
||||
// determine if lightmap blending should be done
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.ui.Typesetter
|
||||
import net.torvald.terrarum.ui.Typography
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.ui.UIHandler
|
||||
import net.torvald.terrarum.ui.KeyboardControlled
|
||||
@@ -113,24 +113,24 @@ class StateMonitorCheck : BasicGameState() {
|
||||
|
||||
// labels
|
||||
g.color = Color.white
|
||||
Typesetter.printCentered(
|
||||
Lang["MENU_MONITOR_CALI_TITLE"],
|
||||
Typography.printCentered(
|
||||
g, Lang["MENU_MONITOR_CALI_TITLE"],
|
||||
titleY,
|
||||
this, g
|
||||
this
|
||||
)
|
||||
|
||||
(1..12).forEach {
|
||||
Typesetter.printCentered(
|
||||
Lang["MENU_MONITOR_CALI_LABEL_$it"],
|
||||
Typography.printCentered(
|
||||
g, Lang["MENU_MONITOR_CALI_LABEL_$it"],
|
||||
instructionY + it.minus(2).times(g.font.lineHeight),
|
||||
this, g
|
||||
this
|
||||
)
|
||||
}
|
||||
|
||||
Typesetter.printCentered(
|
||||
Lang["MENU_LABEL_PRESS_ANYKEY_CONTINUE"],
|
||||
Typography.printCentered(
|
||||
g, Lang["MENU_LABEL_PRESS_ANYKEY_CONTINUE"],
|
||||
anykeyY,
|
||||
this, g
|
||||
this
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
139
src/net/torvald/terrarum/StateSplash.kt
Normal file
@@ -0,0 +1,139 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.terrarum.gameactors.roundInt
|
||||
import net.torvald.terrarum.gamecontroller.Key
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.ui.DrawUtil
|
||||
import net.torvald.terrarum.ui.Typography
|
||||
import org.newdawn.slick.Color
|
||||
import org.newdawn.slick.GameContainer
|
||||
import org.newdawn.slick.Graphics
|
||||
import org.newdawn.slick.Image
|
||||
import org.newdawn.slick.state.BasicGameState
|
||||
import org.newdawn.slick.state.StateBasedGame
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-08-04.
|
||||
*/
|
||||
class StateSplash : BasicGameState() {
|
||||
|
||||
val pictogramCollection = ArrayList<Image>()
|
||||
|
||||
val virtualImageHeight = 100
|
||||
var imageBoardHeight = 0
|
||||
var imageBoardOffset = 0
|
||||
|
||||
lateinit var fadeSheet: Image
|
||||
lateinit var thisG: Graphics
|
||||
|
||||
var opacity = 0f
|
||||
|
||||
val fadeTime = 500
|
||||
var fadeTimer = 0
|
||||
|
||||
var anykey_hit = false
|
||||
|
||||
val backgroundColour = Color(0x303030)
|
||||
|
||||
var delta = 0
|
||||
val deltathre = 500
|
||||
|
||||
val auto_dismiss = 5000
|
||||
|
||||
var opened = false
|
||||
|
||||
override fun init(container: GameContainer?, game: StateBasedGame?) {
|
||||
// pre-load lang
|
||||
Lang["MENU_LANGUAGE_THIS"]
|
||||
|
||||
pictogramCollection.add(Image("./assets/graphics/gui/health_take_a_break.png"))
|
||||
pictogramCollection.add(Image("./assets/graphics/gui/health_distance.png"))
|
||||
|
||||
fadeSheet = Image(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||
thisG = fadeSheet.graphics
|
||||
thisG.font = Terrarum.gameFont
|
||||
}
|
||||
|
||||
override fun update(container: GameContainer, game: StateBasedGame, delta: Int) {
|
||||
this.delta = delta
|
||||
|
||||
// next splash or load next scene
|
||||
if (anykey_hit && opacity == 0f) {
|
||||
System.exit(0)
|
||||
}
|
||||
|
||||
// fade-in
|
||||
if (delta < deltathre) {
|
||||
if (opacity < 1f && !anykey_hit) {
|
||||
opacity = FastMath.interpolateLinear(
|
||||
fadeTimer.toFloat() / fadeTime, 0f, 1f
|
||||
)
|
||||
}
|
||||
else if (opacity > 0f && anykey_hit) {
|
||||
opacity = FastMath.interpolateLinear(
|
||||
fadeTimer.toFloat() / fadeTime, 1f, 0f
|
||||
)
|
||||
}
|
||||
|
||||
if (!opened && fadeTimer >= fadeTime && !anykey_hit) {
|
||||
fadeTimer = 0
|
||||
opened = true
|
||||
}
|
||||
}
|
||||
|
||||
// auto dismiss
|
||||
if (opened && fadeTimer >= auto_dismiss)
|
||||
doAnykeyThingy()
|
||||
|
||||
fadeTimer += delta
|
||||
}
|
||||
|
||||
override fun getID(): Int = Terrarum.SCENE_ID_SPLASH
|
||||
|
||||
override fun render(container: GameContainer?, game: StateBasedGame?, g: Graphics) {
|
||||
|
||||
imageBoardHeight = Terrarum.HEIGHT - thisG.font.lineHeight.times(6)
|
||||
imageBoardOffset = thisG.font.lineHeight.times(3)
|
||||
|
||||
thisG.color = backgroundColour
|
||||
thisG.fillRect(0f, 0f, fadeSheet.width.toFloat(), fadeSheet.height.toFloat())
|
||||
|
||||
thisG.color = Color.white
|
||||
|
||||
Typography.printCentered(thisG, Lang["APP_WARNING_HEALTH_AND_SAFETY"],
|
||||
thisG.font.lineHeight * 2)
|
||||
|
||||
Typography.printCentered(thisG, Lang["MENU_LABEL_PRESS_ANYKEY_CONTINUE"],
|
||||
Terrarum.HEIGHT - thisG.font.lineHeight.times(3))
|
||||
|
||||
pictogramCollection.forEachIndexed { i, image ->
|
||||
DrawUtil.drawCentered(thisG, image, knowYourPlace(i) + imageBoardOffset)
|
||||
}
|
||||
|
||||
g.drawImage(fadeSheet, 0f, 0f, Color(1f, 1f, 1f, opacity))
|
||||
}
|
||||
|
||||
private fun knowYourPlace(i: Int): Int {
|
||||
val gutter = (imageBoardHeight - virtualImageHeight.times(pictogramCollection.size)).toFloat().div(
|
||||
pictogramCollection.size + 1f
|
||||
)
|
||||
return (gutter * i.plus(1) + virtualImageHeight * i).roundInt()
|
||||
}
|
||||
|
||||
override fun keyPressed(key: Int, c: Char) {
|
||||
doAnykeyThingy()
|
||||
}
|
||||
|
||||
override fun controllerButtonPressed(controller: Int, button: Int) {
|
||||
doAnykeyThingy()
|
||||
}
|
||||
|
||||
private fun doAnykeyThingy() {
|
||||
if (delta < deltathre && !anykey_hit) {
|
||||
anykey_hit = true
|
||||
fadeTimer = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,9 +73,13 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
||||
}
|
||||
}
|
||||
|
||||
gc.graphics.clear() // clean up any 'dust' in the buffer
|
||||
|
||||
ingame = StateInGame()
|
||||
//addState(ingame)
|
||||
addState(StateMonitorCheck())
|
||||
//addState(StateMonitorCheck())
|
||||
//addState(StateFontTester())
|
||||
addState(StateSplash())
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -103,8 +107,8 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
||||
|
||||
lateinit var appgc: AppGameContainer
|
||||
|
||||
val WIDTH = 1072
|
||||
val HEIGHT = 742 // IMAX ratio
|
||||
var WIDTH = 1072
|
||||
var HEIGHT = 742 // IMAX ratio
|
||||
var VSYNC = true
|
||||
val VSYNC_TRIGGER_THRESHOLD = 56
|
||||
|
||||
@@ -141,6 +145,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
||||
// 0x0 - 0xF: Game-related
|
||||
// 0x10 - 0x1F: Config
|
||||
// 0x100 and onward: unit tests for dev
|
||||
val SCENE_ID_SPLASH = 0x0
|
||||
val SCENE_ID_HOME = 0x1
|
||||
val SCENE_ID_GAME = 0x3
|
||||
val SCENE_ID_CONFIG_CALIBRATE = 0x11
|
||||
@@ -362,7 +367,7 @@ fun main(args: Array<String>) = Terrarum.main(args)
|
||||
|
||||
fun setBlendMul() {
|
||||
GL11.glEnable(GL11.GL_BLEND)
|
||||
GL11.glColorMask(true, true, true, true)
|
||||
GL11.glColorMask(true, true, true, false)
|
||||
GL11.glBlendFunc(GL11.GL_DST_COLOR, GL11.GL_ONE_MINUS_SRC_ALPHA)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.gameactors
|
||||
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.gamemap.GameWorld
|
||||
import net.torvald.terrarum.mapdrawer.MapDrawer
|
||||
@@ -971,10 +972,12 @@ open class ActorWithBody : Actor(), Visible {
|
||||
}
|
||||
|
||||
fun Double.floorInt() = Math.floor(this).toInt()
|
||||
fun Float.floorInt() = FastMath.floor(this).toInt()
|
||||
fun Double.round() = Math.round(this).toDouble()
|
||||
fun Double.floor() = Math.floor(this)
|
||||
fun Double.ceil() = this.floor() + 1.0
|
||||
fun Double.roundInt(): Int = Math.round(this).toInt()
|
||||
fun Float.roundInt(): Int = Math.round(this).toInt()
|
||||
fun Double.abs() = Math.abs(this)
|
||||
fun Double.sqr() = this * this
|
||||
fun Int.abs() = if (this < 0) -this else this
|
||||
|
||||
@@ -46,27 +46,6 @@ class MDLInterpreterState {
|
||||
// push, pop, +, -, *, /, %, dup, swap, drop
|
||||
}
|
||||
|
||||
class MagicOrInt() {
|
||||
private var magic: MagicWords? = null
|
||||
private var number: Int? = null
|
||||
|
||||
constructor(kynngi: MagicWords): this() {
|
||||
magic = kynngi
|
||||
}
|
||||
|
||||
constructor(integer: Int) : this() {
|
||||
number = integer
|
||||
}
|
||||
|
||||
fun toMagic() = if (magic != null) magic!! else throw TypeCastException("$this: cannot be cast to MagicWord")
|
||||
fun toInt() = if (number != null) number!! else throw TypeCastException("$this: cannot be cast to MagicWord")
|
||||
|
||||
fun isMagic() = (magic != null)
|
||||
fun isInt() = (number != null)
|
||||
|
||||
override fun toString(): String = if (magic != null && number == null) "$magic" else if (magic == null && number != null) "$number" else "INVALID"
|
||||
}
|
||||
|
||||
class MagicArrayStack {
|
||||
/**
|
||||
* Number of elements in the stack
|
||||
@@ -81,28 +60,28 @@ class MDLInterpreterState {
|
||||
else deflate(data.size - newSize)
|
||||
}
|
||||
|
||||
private lateinit var data: Array<MagicOrInt?>
|
||||
private lateinit var data: Array<Int?>
|
||||
|
||||
constructor(stackSize: Int) {
|
||||
data = Array(stackSize, { null })
|
||||
}
|
||||
|
||||
constructor(arr: Array<MagicOrInt?>) {
|
||||
constructor(arr: Array<Int?>) {
|
||||
data = arr.copyOf()
|
||||
depth = size
|
||||
}
|
||||
|
||||
fun push(v: MagicOrInt) {
|
||||
fun push(v: Int) {
|
||||
if (depth >= data.size) throw StackOverflowError()
|
||||
data[depth++] = v
|
||||
}
|
||||
|
||||
fun pop(): MagicOrInt {
|
||||
fun pop(): Int {
|
||||
if (depth == 0) throw EmptyStackException()
|
||||
return data[--depth]!!
|
||||
}
|
||||
|
||||
fun peek(): MagicOrInt? {
|
||||
fun peek(): Int? {
|
||||
if (depth == 0) return null
|
||||
return data[depth - 1]
|
||||
}
|
||||
@@ -126,7 +105,7 @@ class MDLInterpreterState {
|
||||
--depth
|
||||
}
|
||||
|
||||
fun defineFromArray(arr: Array<MagicOrInt?>) { data = arr.copyOf() }
|
||||
fun defineFromArray(arr: Array<Int?>) { data = arr.copyOf() }
|
||||
|
||||
/**
|
||||
* Increase the stack size by a factor.
|
||||
@@ -157,10 +136,10 @@ class MDLInterpreterState {
|
||||
|
||||
fun equalTo(other: MagicArrayStack) = (this.asArray() == other.asArray())
|
||||
|
||||
fun plus() { if (data[depth - 2]!!.isInt() && peek()!!.isInt()) data[depth - 2] = MagicOrInt(data[depth - 2]!!.toInt() + (pop().toInt())) else throw RuntimeException("${data[depth - 2]}: Cannot do arithmetic operation on non-numeric type.") }
|
||||
fun minus() { if (data[depth - 2]!!.isInt() && peek()!!.isInt()) data[depth - 2] = MagicOrInt(data[depth - 2]!!.toInt() - (pop().toInt())) else throw RuntimeException("${data[depth - 2]}: Cannot do arithmetic operation on non-numeric type.") }
|
||||
fun times() { if (data[depth - 2]!!.isInt() && peek()!!.isInt()) data[depth - 2] = MagicOrInt(data[depth - 2]!!.toInt() * (pop().toInt())) else throw RuntimeException("${data[depth - 2]}: Cannot do arithmetic operation on non-numeric type.") }
|
||||
fun div() { if (data[depth - 2]!!.isInt() && peek()!!.isInt()) data[depth - 2] = MagicOrInt(data[depth - 2]!!.toInt() / (pop().toInt())) else throw RuntimeException("${data[depth - 2]}: Cannot do arithmetic operation on non-numeric type.") }
|
||||
fun mod() { if (data[depth - 2]!!.isInt() && peek()!!.isInt()) data[depth - 2] = MagicOrInt(data[depth - 2]!!.toInt() % (pop().toInt())) else throw RuntimeException("${data[depth - 2]}: Cannot do arithmetic operation on non-numeric type.") }
|
||||
fun plus() { data[depth - 2] = data[depth - 2]!! + (pop().toInt()) }
|
||||
fun minus() { data[depth - 2] = data[depth - 2]!! - (pop().toInt()) }
|
||||
fun times() { data[depth - 2] = data[depth - 2]!! * (pop().toInt()) }
|
||||
fun div() { data[depth - 2] = data[depth - 2]!! / (pop().toInt()) }
|
||||
fun mod() { data[depth - 2] = data[depth - 2]!! % (pop().toInt()) }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
|
||||
package net.torvald.terrarum.gamemap
|
||||
|
||||
import net.torvald.terrarum.gameactors.Player
|
||||
import net.torvald.terrarum.gameactors.roundInt
|
||||
import net.torvald.terrarum.mapdrawer.MapDrawer
|
||||
import org.dyn4j.geometry.Vector2
|
||||
import org.newdawn.slick.SlickException
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ class MapLayer(var width: Int, var height: Int) : Iterable<Byte> {
|
||||
data[y][x] = tile
|
||||
}
|
||||
|
||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||
|
||||
private fun uint8ToInt32(x: Byte): Int = java.lang.Byte.toUnsignedInt(x)
|
||||
|
||||
companion object {
|
||||
|
||||
188
src/net/torvald/terrarum/gamemap/WorldSimulator.kt
Normal file
@@ -0,0 +1,188 @@
|
||||
package net.torvald.terrarum.gamemap
|
||||
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.gameactors.Player
|
||||
import net.torvald.terrarum.gameactors.roundInt
|
||||
import net.torvald.terrarum.mapdrawer.MapDrawer
|
||||
import net.torvald.terrarum.tileproperties.TileNameCode
|
||||
import net.torvald.terrarum.tileproperties.TilePropCodex
|
||||
import org.newdawn.slick.Graphics
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-08-03.
|
||||
*/
|
||||
object WorldSimulator {
|
||||
/**
|
||||
* In tiles;
|
||||
* square width/height = field * 2
|
||||
*/
|
||||
const val FLUID_UPDATING_SQUARE_RADIUS = 128
|
||||
const private val DOUBLE_RADIUS = FLUID_UPDATING_SQUARE_RADIUS * 2
|
||||
|
||||
private val fluidMap = Array<IntArray>(DOUBLE_RADIUS, { IntArray(DOUBLE_RADIUS) })
|
||||
|
||||
const val DISPLACE_CAP = 4
|
||||
const val FLUID_MAX = 16
|
||||
|
||||
operator fun invoke(world: GameWorld, p: Player, delta: Int) {
|
||||
moveFluids(world, p, delta)
|
||||
}
|
||||
|
||||
/**
|
||||
* displace fluids. Note that the code assumes the gravity pulls things downward ONLY,
|
||||
* which means you'll need to modify the code A LOT if you're going to implement zero- or
|
||||
* reverse-gravity.
|
||||
*/
|
||||
fun moveFluids(world: GameWorld, p: Player, delta: Int) {
|
||||
val updateXFrom = p.hitbox.centeredX.div(MapDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
|
||||
val updateYFrom = p.hitbox.centeredY.div(MapDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
|
||||
val updateXTo = updateXFrom + 1 * FLUID_UPDATING_SQUARE_RADIUS
|
||||
val updateYTo = updateYFrom + 1 * FLUID_UPDATING_SQUARE_RADIUS
|
||||
|
||||
/**
|
||||
* @return amount of fluid actually drained.
|
||||
* (intended drainage - this) will give you how much fluid is not yet drained.
|
||||
*/
|
||||
fun drain(x: Int, y: Int, amount: Int): Int {
|
||||
val displacement = Math.min(fluidMap[y - updateYFrom][x - updateXFrom], amount)
|
||||
|
||||
fluidMap[y - updateYFrom][x - updateXFrom] -= displacement
|
||||
|
||||
return displacement
|
||||
}
|
||||
|
||||
fun pour(x: Int, y: Int, amount: Int) {
|
||||
fun pourInternal(xpos: Int, ypos: Int, volume: Int): Int {
|
||||
var spil = 0
|
||||
|
||||
val addrX = xpos - updateXFrom
|
||||
val addrY = ypos - updateYFrom
|
||||
|
||||
if (addrX >= 0 && addrY >= 0 && addrX < DOUBLE_RADIUS && addrY < DOUBLE_RADIUS) {
|
||||
fluidMap[addrY][addrX] += volume
|
||||
if (fluidMap[addrY][addrX] > FLUID_MAX) {
|
||||
spil = fluidMap[addrY][addrX] - FLUID_MAX
|
||||
fluidMap[addrY][addrX] = FLUID_MAX
|
||||
}
|
||||
}
|
||||
|
||||
return spil
|
||||
}
|
||||
|
||||
// pour the fluid
|
||||
var spillage = pourInternal(x, y, amount)
|
||||
|
||||
if (spillage == 0) return
|
||||
|
||||
// deal with the spillage
|
||||
|
||||
val tileUp = world.getTileFromTerrain(x - updateXFrom, y - updateYFrom - 1)
|
||||
val tileDown = world.getTileFromTerrain(x - updateXFrom, y - updateYFrom + 1)
|
||||
|
||||
// try to fill downward
|
||||
if (tileDown != null && !tileDown.isSolid()) {
|
||||
spillage = pourInternal(x, y + 1, spillage)
|
||||
}
|
||||
// else, try to fill upward. if there is no space, just discard
|
||||
if (tileUp != null && !tileUp.isSolid()) {
|
||||
pourInternal(x, y - 1, spillage)
|
||||
}
|
||||
}
|
||||
|
||||
purgeFluidMap()
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// displace fluids. Record displacements into the fluidMap //
|
||||
/////////////////////////////////////////////////////////////
|
||||
for (y in updateYFrom..updateYTo) {
|
||||
for (x in updateXFrom..updateXTo) {
|
||||
val tile = world.getTileFromTerrain(x, y)
|
||||
val tileBottom = world.getTileFromTerrain(x, y + 1)
|
||||
val tileLeft = world.getTileFromTerrain(x - 1, y)
|
||||
val tileRight = world.getTileFromTerrain(x + 1, y)
|
||||
if (tile != null && tile.isFluid()) {
|
||||
|
||||
// move down if not obstructed
|
||||
if (tileBottom != null && !tileBottom.isSolid()) {
|
||||
val drainage = drain(x, y, DISPLACE_CAP)
|
||||
pour(x, y + 1, drainage)
|
||||
}
|
||||
// left and right both open (null is considered as open)
|
||||
else if ((tileLeft != null && tileRight != null && !tileLeft.isSolid() && !tileRight.isSolid()) ||
|
||||
tileLeft == null && tileRight == null) {
|
||||
// half-breaker
|
||||
val moreToTheRight = HQRNG().nextBoolean()
|
||||
val displacement = drain(x, y, DISPLACE_CAP)
|
||||
|
||||
if (displacement.isEven()) {
|
||||
pour(x - 1, y, displacement shr 1)
|
||||
pour(x + 1, y, displacement shr 1)
|
||||
}
|
||||
else {
|
||||
pour(x - 1, y, (displacement shr 1) + if (moreToTheRight) 0 else 1)
|
||||
pour(x + 1, y, (displacement shr 1) + if (moreToTheRight) 1 else 0)
|
||||
}
|
||||
}
|
||||
// left open (null is considered as open)
|
||||
else if ((tileLeft != null && !tileLeft.isSolid()) || tileLeft == null) {
|
||||
val displacement = drain(x, y, DISPLACE_CAP)
|
||||
pour(x - 1, y, displacement)
|
||||
}
|
||||
// right open (null is considered as open)
|
||||
else if ((tileRight != null && !tileRight.isSolid()) || tileRight == null) {
|
||||
val displacement = drain(x, y, DISPLACE_CAP)
|
||||
pour(x + 1, y, displacement)
|
||||
}
|
||||
// nowhere open; do default (fill top)
|
||||
else {
|
||||
pour(x, y - 1, DISPLACE_CAP)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////
|
||||
// replace fluids in the map according to fluidMap //
|
||||
/////////////////////////////////////////////////////
|
||||
for (y in 0..fluidMap.size - 1) {
|
||||
for (x in 0..fluidMap[0].size - 1) {
|
||||
placeFluid(world, updateXFrom + x, updateYFrom + y, WATER, fluidMap[y][x].minus(1))
|
||||
// FIXME test code: deals with water only!
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun drawFluidMapDebug(p: Player, g: Graphics) {
|
||||
for (y in 0..fluidMap.size - 1) {
|
||||
for (x in 0..fluidMap[0].size - 1) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun purgeFluidMap() {
|
||||
for (y in 1..DOUBLE_RADIUS)
|
||||
for (x in 1..DOUBLE_RADIUS)
|
||||
fluidMap[y - 1][x - 1] = 0
|
||||
}
|
||||
|
||||
fun Int.isFluid() = TilePropCodex.getProp(this).isFluid
|
||||
fun Int.isSolid() = TilePropCodex.getProp(this).isSolid
|
||||
//fun Int.viscosity() = TilePropCodex.getProp(this).
|
||||
fun Int.fluidLevel() = this % FLUID_MAX
|
||||
fun Int.isEven() = (this and 0x01) == 0
|
||||
|
||||
private fun placeFluid(world: GameWorld, x: Int, y: Int, tileFluid: Int, amount: Int) {
|
||||
if (world.layerTerrain.isInBound(x, y)) {
|
||||
if (amount > 0 && !world.getTileFromTerrain(x, y)!!.isSolid()) {
|
||||
world.setTileTerrain(x, y, amount.minus(1).plus(tileFluid))
|
||||
}
|
||||
else if (amount == 0 && world.getTileFromTerrain(x, y)!!.isFluid()) {
|
||||
world.setTileTerrain(x, y, TileNameCode.AIR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val LAVA = TileNameCode.LAVA_1
|
||||
val WATER = TileNameCode.WATER_1
|
||||
}
|
||||
@@ -381,7 +381,8 @@ object MapCamera {
|
||||
var ret = 0
|
||||
for (i in 0..3) {
|
||||
try {
|
||||
if (!TilePropCodex.getProp(nearbyTiles[i]).isSolid) {
|
||||
if (!TilePropCodex.getProp(nearbyTiles[i]).isSolid &&
|
||||
!TilePropCodex.getProp(nearbyTiles[i]).isFluid) {
|
||||
ret += (1 shl i) // add 1, 2, 4, 8 for i = 0, 1, 2, 3
|
||||
}
|
||||
} catch (e: ArrayIndexOutOfBoundsException) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"id";"dmg";"name" ; "opacity";"strength";"dsty";"fluid";"solid";"wall"; "lumcolor";"drop";"ddmg";"fall";"dlfn";"friction"
|
||||
"0"; "0";"TILE_AIR" ; "8396808"; "0"; "1"; "1"; "0"; "0"; "0"; "0"; "0"; "0"; "0";"4"
|
||||
"0"; "0";"TILE_AIR" ; "8396808"; "0"; "1"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0";"4"
|
||||
"1"; "0";"TILE_STONE" ; "33587232"; "25";"2400"; "0"; "1"; "1"; "0"; "1"; "0"; "0"; "0";"16"
|
||||
"1"; "1";"TILE_STONE_QUARRIED" ; "33587232"; "25";"2400"; "0"; "1"; "1"; "0"; "1"; "1"; "0"; "0";"16"
|
||||
"1"; "2";"TILE_STONE_TILE_WHITE" ; "33587232"; "25";"2400"; "0"; "1"; "1"; "0"; "1"; "2"; "0"; "0";"16"
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 1 and column 18.
|
17
src/net/torvald/terrarum/ui/DrawUtil.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package net.torvald.terrarum.ui
|
||||
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import org.newdawn.slick.Graphics
|
||||
import org.newdawn.slick.Image
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-08-04.
|
||||
*/
|
||||
object DrawUtil {
|
||||
fun drawCentered(g: Graphics, image: Image, screenPosY: Int, ui: UICanvas? = null) {
|
||||
val imageW = image.width
|
||||
val targetW = if (ui == null) Terrarum.WIDTH else ui.width
|
||||
|
||||
g.drawImage(image, targetW.minus(imageW).ushr(1).toFloat(), screenPosY.toFloat())
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
package net.torvald.terrarum.ui
|
||||
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import org.newdawn.slick.Graphics
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-07-06.
|
||||
*/
|
||||
object Typesetter {
|
||||
fun printCentered(string: String, screenPosY: Int, ui: UICanvas, g: Graphics) {
|
||||
object Typography {
|
||||
fun printCentered(g: Graphics, string: String, screenPosY: Int, ui: UICanvas? = null) {
|
||||
val stringW = g.font.getWidth(string)
|
||||
val targetW = ui.width
|
||||
val targetW = if (ui == null) Terrarum.WIDTH else ui.width
|
||||
|
||||
g.drawString(string, targetW.minus(stringW).ushr(1).toFloat(), screenPosY.toFloat())
|
||||
}
|
||||
@@ -14,5 +14,7 @@ data class BaseModularWeather(
|
||||
val globalLightColourMap: Image,
|
||||
var skyboxGradColourMap: Image,
|
||||
val classification: String,
|
||||
var extraImages: ArrayList<Image>
|
||||
var extraImages: ArrayList<Image>,
|
||||
val mixFrom: String? = null,
|
||||
val mixPercentage: Double? = null
|
||||
)
|
||||
@@ -27,12 +27,15 @@ object WeatherMixer {
|
||||
lateinit var currentWeather: BaseModularWeather
|
||||
lateinit var nextWeather: BaseModularWeather
|
||||
|
||||
lateinit var mixedWeather: 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 = "generic"
|
||||
const val WEATHER_GENERIC_RAIN = "genericrain"
|
||||
// TODO add weather classification indices manually
|
||||
|
||||
const val RAW_DIR = "./assets/raw/weathers"
|
||||
@@ -169,6 +172,12 @@ object WeatherMixer {
|
||||
val skybox: Image
|
||||
val extraImages = ArrayList<Image>()
|
||||
val classification = JSON.get("classification").asJsonPrimitive.asString
|
||||
val mixFrom: String?
|
||||
try { mixFrom = JSON.get("mixFrom").asJsonPrimitive.asString }
|
||||
catch (e: NullPointerException) { mixFrom = null }
|
||||
val mixPercentage: Double?
|
||||
try { mixPercentage = JSON.get("mixPercentage").asJsonPrimitive.asDouble }
|
||||
catch (e: NullPointerException) { mixPercentage = null }
|
||||
|
||||
// parse globalLight
|
||||
if (globalLightInJson.isString)
|
||||
@@ -196,7 +205,10 @@ object WeatherMixer {
|
||||
|
||||
// get extra images
|
||||
for (i in extraImagesPath)
|
||||
extraImages.add(Image("$pathToImage/$i"))
|
||||
extraImages.add(Image("$pathToImage/${i.asString}"))
|
||||
|
||||
// get mix from
|
||||
|
||||
|
||||
return BaseModularWeather(globalLight, skybox, classification, extraImages)
|
||||
}
|
||||
|
||||