new noisegen for ores/gems, need some test, error-proof ActorValue addressing, more comments for ActorWithBody.kt

Former-commit-id: a3441e31f11fa89283babee4c9749680495af923
Former-commit-id: 4092ed362f4f8c28685f82a70ee49e0bee0f0a13
This commit is contained in:
Song Minjae
2016-04-04 23:55:00 +09:00
parent 1573851130
commit bad4afe247
20 changed files with 349 additions and 227 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -56,7 +56,7 @@ class Col216 : LimitedColours {
}
private fun assertRaw(i: Int) {
if (i >= COLOUR_DOMAIN_SIZE || i < 0) {
if (i >= COLOUR_RANGE_SIZE || i < 0) {
println("i: " + i.toString())
throw IllegalArgumentException()
}
@@ -77,6 +77,6 @@ class Col216 : LimitedColours {
const val MUL = 6
const val MUL_2 = MUL * MUL
const val MAX_STEP = MUL - 1
const val COLOUR_DOMAIN_SIZE = MUL_2 * MUL
const val COLOUR_RANGE_SIZE = MUL_2 * MUL
}
}

View File

@@ -7,7 +7,6 @@ import org.newdawn.slick.Color
*/
interface LimitedColours {
fun createSlickColor(raw: Int): Color
fun createSlickColor(r: Int, g: Int, b: Int): Color

View File

@@ -180,13 +180,13 @@ constructor() : Font {
val glyphW = getWidth("" + ch)
// chosung
// initials
hangulSheet.renderInUse(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW), Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f), indexCho, choRow)
// jungseong
// medials
hangulSheet.renderInUse(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW), Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f), indexJung, jungRow)
// jongseong
// finals
hangulSheet.renderInUse(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW), Math.round(((H - H_HANGUL) / 2).toFloat() + y + 1f), indexJong, jongRow)
}
@@ -231,6 +231,7 @@ constructor() : Font {
}
wenQuanYi_1.endUse()
// WenQuanYi 2
wenQuanYi_2.startUse()
for (i in 0..s.length - 1) {
@@ -249,7 +250,7 @@ constructor() : Font {
wenQuanYi_2.endUse()
//ascii fonts
// regular fonts
var prevInstance = -1
for (i in 0..s.length - 1) {
val ch = s[i]
@@ -313,16 +314,20 @@ constructor() : Font {
}
val glyphW = getWidth("" + ch)
sheetKey[prevInstance].renderInUse(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW) // Interchar: pull punct right next to hangul to the left
+ if (i > 0 && isHangul(s[i - 1])) -3 else 0, Math.round(y) +
if (prevInstance == SHEET_CJK_PUNCT)
-1
else if (prevInstance == SHEET_FW_UNI)
(H - H_HANGUL) / 2
else 0,
sheetX, sheetY)
try {
sheetKey[prevInstance].renderInUse(
Math.round(x + getWidthSubstr(s, i + 1) - glyphW) // Interchar: pull punct right next to hangul to the left
+ if (i > 0 && isHangul(s[i - 1])) -3 else 0, Math.round(y) +
if (prevInstance == SHEET_CJK_PUNCT)
-1
else if (prevInstance == SHEET_FW_UNI)
(H - H_HANGUL) / 2
else 0,
sheetX, sheetY)
}
catch (e: ArrayIndexOutOfBoundsException) {
// character that does not exist in the sheet. No render, pass.
}
}
}

View File

@@ -1,6 +1,6 @@
package com.torvald.terrarum.itemproperties
import com.torvald.terrarum.gameactors.CanBeStoredAsItem
import com.torvald.terrarum.gameactors.CanBeAnItem
import com.torvald.terrarum.gameitem.InventoryItem
import com.torvald.terrarum.Terrarum
import org.newdawn.slick.GameContainer
@@ -34,7 +34,7 @@ object ItemPropCodex {
return itemCodex[(code and 0xFFFFFFFF).toInt()]
else {
for (actor in Terrarum.game.actorContainer) {
if (actor is CanBeStoredAsItem && actor.referenceID.equals(code))
if (actor is CanBeAnItem && actor.referenceID.equals(code))
return actor.itemData
}

View File

@@ -39,26 +39,51 @@ open class KVHashMap {
}
fun getAsInt(key: String): Int? {
val value = get(key)
if (value is JsonPrimitive)
return value.asInt
return get(key) as Int?
}
fun getAsFloat(key: String): Float? {
val value = get(key)
if (value is Int)
return value.toFloat()
else if (value is JsonPrimitive) return value.asFloat
else if (value is JsonPrimitive)
return value.asFloat
return value as Float?
}
fun getAsDouble(key: String): Double? {
val value = get(key)
if (value is Int)
return value.toDouble()
else if (value is JsonPrimitive)
return value.asDouble
return value as Double?
}
fun getAsString(key: String): String? {
val value = get(key)
if (value is JsonPrimitive) return value.asString
if (value is JsonPrimitive)
return value.asString
return value as String?
}
fun getAsBoolean(key: String): Boolean? {
val value = get(key)
if (value is JsonPrimitive) return value.asBoolean
if (value is JsonPrimitive)
return value.asBoolean
return value as Boolean?
}

View File

@@ -35,18 +35,18 @@ object LightmapRenderer {
private val OFFSET_G = 1
private val OFFSET_B = 0
private val TSIZE = MapDrawer.TILE_SIZE
private const val TSIZE = MapDrawer.TILE_SIZE
// color model related vars
// color model related constants
const val MUL = 256 // modify this to 1024 to implement 30-bit RGB
const val MUL_2 = MUL * MUL
const val CHANNEL_MAX = MUL - 1
const val CHANNEL_MAX_FLOAT = CHANNEL_MAX.toFloat()
const val COLOUR_DOMAIN_SIZE = MUL * MUL_2
const val COLOUR_RANGE_SIZE = MUL * MUL_2
private const val deprecatedFeatureDebatable = "The usage of this feature is debatable. Do not use it yet."
@Deprecated(deprecatedFeatureDebatable)
fun addLantern(x: Int, y: Int, intensity: Int) {
val thisLantern = LightmapLantern(x, y, intensity)
@@ -77,6 +77,7 @@ object LightmapRenderer {
fun getLight(x: Int, y: Int): Int? =
if (x !in 0..Terrarum.game.map.width - 1 || y !in 0..Terrarum.game.map.height - 1)
// if out of range then
null
else
java.lang.Byte.toUnsignedInt(lightMapLSB!![y][x]) or (lightMapMSB!![y][x].toInt() shl 8)
@@ -336,7 +337,7 @@ object LightmapRenderer {
// calculate ambient
var ambient: Int = 0
var nearby: Int = 0
findNearbyBrightest@ for (yoff in -1..1) {
for (yoff in -1..1) {
for (xoff in -1..1) {
/**
* filter for 'v's as:
@@ -393,9 +394,8 @@ object LightmapRenderer {
* @return darkened data (0-39) per channel
*/
fun darkenColoured(data: Int, darken: Int): Int {
if (darken.toInt() < 0 || darken.toInt() >= COLOUR_DOMAIN_SIZE) {
throw IllegalArgumentException("darken: out of " + "range")
}
if (darken.toInt() < 0 || darken.toInt() >= COLOUR_RANGE_SIZE)
throw IllegalArgumentException("darken: out of range ($darken)")
val r = clampZero(getR(data) - getR(darken))
val g = clampZero(getG(data) - getG(darken))
@@ -416,9 +416,8 @@ object LightmapRenderer {
* @return
*/
fun darkenUniformFloat(data: Int, darken: Float): Int {
if (darken < 0 || darken > 1f) {
throw IllegalArgumentException("darken: out of " + "range")
}
if (darken < 0 || darken > 1f)
throw IllegalArgumentException("darken: out of range ($darken)")
val r = clampZero(getR(data) - darken)
val g = clampZero(getG(data) - darken)
@@ -438,9 +437,8 @@ object LightmapRenderer {
* @return
*/
fun darkenUniformInt(data: Int, darken: Int): Int {
if (darken < 0 || darken > CHANNEL_MAX) {
throw IllegalArgumentException("darken: out of " + "range")
}
if (darken < 0 || darken > CHANNEL_MAX)
throw IllegalArgumentException("darken: out of range ($darken)")
val r = clampZero(getRawR(data) - darken)
val g = clampZero(getRawG(data) - darken)
@@ -463,9 +461,8 @@ object LightmapRenderer {
* @return brightened data [0-39] per channel
*/
private fun brightenColoured(data: Int, brighten: Int): Int {
if (brighten.toInt() < 0 || brighten.toInt() >= COLOUR_DOMAIN_SIZE) {
throw IllegalArgumentException("brighten: out of " + "range")
}
if (brighten.toInt() < 0 || brighten.toInt() >= COLOUR_RANGE_SIZE)
throw IllegalArgumentException("brighten: out of range ($brighten)")
val r = clampFloat(getR(data) + getR(brighten))
val g = clampFloat(getG(data) + getG(brighten))
@@ -530,12 +527,10 @@ object LightmapRenderer {
* @return
*/
fun getRaw(RGB: Int, offset: Int): Int {
if (offset == OFFSET_R) return getRawR(RGB)
if (offset == OFFSET_G) return getRawG(RGB)
if (offset == OFFSET_B)
return getRawB(RGB)
else
throw IllegalArgumentException("Channel offset out of range")
if (offset == OFFSET_R) return getRawR(RGB)
else if (offset == OFFSET_G) return getRawG(RGB)
else if (offset == OFFSET_B) return getRawB(RGB)
else throw IllegalArgumentException("Channel offset out of range")
}
private fun getR(rgb: Int): Float {
@@ -559,28 +554,16 @@ object LightmapRenderer {
}
fun constructRGBFromInt(r: Int, g: Int, b: Int): Int {
if (r < 0 || r > CHANNEL_MAX) {
throw IllegalArgumentException("Red: out of range")
}
if (g < 0 || g > CHANNEL_MAX) {
throw IllegalArgumentException("Green: out of range")
}
if (b < 0 || b > CHANNEL_MAX) {
throw IllegalArgumentException("Blue: out of range")
}
if (r !in 0..CHANNEL_MAX) throw IllegalArgumentException("Red: out of range")
if (g !in 0..CHANNEL_MAX) throw IllegalArgumentException("Green: out of range")
if (b !in 0..CHANNEL_MAX) throw IllegalArgumentException("Blue: out of range")
return (r * MUL_2 + g * MUL + b)
}
fun constructRGBFromFloat(r: Float, g: Float, b: Float): Int {
if (r < 0 || r > 1.0f) {
throw IllegalArgumentException("Red: out of range")
}
if (g < 0 || g > 1.0f) {
throw IllegalArgumentException("Green: out of range")
}
if (b < 0 || b > 1.0f) {
throw IllegalArgumentException("Blue: out of range")
}
if (r < 0 || r > 1.0f) throw IllegalArgumentException("Red: out of range")
if (g < 0 || g > 1.0f) throw IllegalArgumentException("Green: out of range")
if (b < 0 || b > 1.0f) throw IllegalArgumentException("Blue: out of range")
val intR = Math.round(r * CHANNEL_MAX)
val intG = Math.round(g * CHANNEL_MAX)
@@ -622,10 +605,10 @@ object LightmapRenderer {
}
private fun outOfBounds(x: Int, y: Int): Boolean =
x < 0 || y < 0 || x >= Terrarum.game.map.width || y >= Terrarum.game.map.height
x !in 0..Terrarum.game.map.width - 1 || y !in 0..Terrarum.game.map.height - 1
private fun outOfMapBounds(x: Int, y: Int): Boolean =
x < 0 || y < 0 || x >= lightMapMSB!![0].size || y >= lightMapMSB!!.size
x !in 0..lightMapMSB!![0].size - 1 || y !in 0..lightMapMSB!!.size - 1
private fun clampZero(i: Int): Int = if (i < 0) 0 else i

View File

@@ -11,14 +11,14 @@ import org.newdawn.slick.*
* Created by minjaesong on 15-12-31.
*/
object MapDrawer {
@JvmStatic val TILE_SIZE = 16
const val TILE_SIZE = 16
private var envOverlayColourmap: Image = Image("./res/graphics/black_body_col_1000_40000_K.png")
@JvmStatic private val ENV_COLTEMP_LOWEST = 5500
@JvmStatic private val ENV_COLTEMP_HIGHEST = 7500
private val ENV_COLTEMP_LOWEST = 5500
private val ENV_COLTEMP_HIGHEST = 7500
@JvmStatic val ENV_COLTEMP_NOON = 6500
val ENV_COLTEMP_NOON = 6500
private var colTemp: Int = 0

View File

@@ -24,8 +24,11 @@ object MapGenerator {
var TERRAIN_AVERAGE_HEIGHT: Int = 0
private var minimumFloatingIsleHeight: Int = 0
private val noiseGradientStart = 0.67f
private val noiseGradientEnd = 0.56f
private val NOISE_GRAD_START = 0.67f
private val NOISE_GRAD_END = 0.56f
private val NOISE_SIMPLEX_ORE_START = 1.42f
private val NOISE_SIMPLEX_ORE_END = 1.28f
private val HILL_WIDTH = 256 // power of two!
//private val MAX_HILL_HEIGHT = 100
@@ -106,46 +109,32 @@ object MapGenerator {
*/
val noiseArray = arrayOf(
TaggedJoise("Carving caves", noiseRidged(1.7f, 1.4f), 1f, TILE_MACRO_ALL, TILE_MACRO_ALL, TileNameCode.AIR, NoiseFilterSqrt, CAVEGEN_THRE_START, CAVEGEN_THRE_END),
TaggedJoise("Collapsing caves", noiseBlobs(0.5f, 0.5f), 0.3f, TileNameCode.AIR, TileNameCode.STONE, TileNameCode.STONE, NoiseFilterUniform)
TaggedJoise("Carving caves", noiseRidged(1.7f, 1.4f), 1f, TILE_MACRO_ALL, TILE_MACRO_ALL, TileNameCode.AIR, NoiseFilterSqrt, CAVEGEN_THRE_START, CAVEGEN_THRE_END)
, TaggedJoise("Collapsing caves", noiseBlobs(0.5f, 0.5f), 0.3f, TileNameCode.AIR, TileNameCode.STONE, TileNameCode.STONE, NoiseFilterUniform)
// random stone patches on grounds
//TaggedJoise(noiseBlobs(0.25f, 0.25f), 1.02f, TileNameCode.DIRT, TileNameCode.STONE, NoiseFilterQuadratic, noiseGradientEnd, noiseGradientStart),
// random dirt spots in caves
//TaggedJoise(noiseBlobs(2.5f, 2.5f), 0.98f, TileNameCode.STONE, TileNameCode.DIRT, NoiseFilterQuadratic, noiseGradientEnd, noiseGradientStart),
// random gravels in caves
//TaggedJoise(noiseBlobs(2.5f, 2.5f), 0.98f, TileNameCode.STONE, TileNameCode.GRAVEL, NoiseFilterQuadratic, noiseGradientEnd, noiseGradientStart),
//, TaggedJoise("Putting stone patches on the ground", noiseBlobs(0.8f, 0.8f), 1.02f, TileNameCode.DIRT, TileNameCode.DIRT, TileNameCode.STONE, NoiseFilterQuadratic, noiseGradientEnd, noiseGradientStart)
//, TaggedJoise("Placing dirt spots in the cave", noiseBlobs(0.5f, 0.5f), 0.98f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.DIRT, NoiseFilterQuadratic, noiseGradientEnd, noiseGradientStart)
//, TaggedJoise("Quarrying some stone into gravels", noiseBlobs(0.5f, 0.5f), 0.98f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.GRAVEL, NoiseFilterQuadratic, noiseGradientEnd, noiseGradientStart)
// copper veins
//TaggedJoise(noiseRidged(2.2f, 2.2f), 1.67f, TileNameCode.STONE, TileNameCode.ORE_COPPER),
// separate copper veins
//TaggedJoise(noiseBlobs(1.3f, 1.3f), 0.75f, TileNameCode.ORE_COPPER, TileNameCode.STONE),
//, TaggedJoise("Growing copper veins", noiseRidged(1.7f, 1.7f), 1.68f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.ORE_COPPER)
//, TaggedJoise("Cutting copper veins", noiseBlobs(0.4f, 0.4f), 0.26f, TileNameCode.ORE_COPPER, TileNameCode.STONE, TileNameCode.STONE)
// iron veins
//TaggedJoise(noiseRidged(2.2f, 2.2f), 1.69f, TileNameCode.STONE, TileNameCode.ORE_IRON),
// separate iron veins
//TaggedJoise(noiseBlobs(1.3f, 1.3f), 0.75f, TileNameCode.ORE_IRON, TileNameCode.STONE),
//, TaggedJoise("Growing iron veins", noiseRidged(1.7f, 1.7f), 1.68f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.ORE_IRON)
//, TaggedJoise("Cutting iron veins", noiseBlobs(0.7f, 0.7f), 0.26f, TileNameCode.ORE_IRON, TileNameCode.STONE, TileNameCode.STONE)
// silver veins
//TaggedJoise(noiseRidged(2.2f, 2.2f), 1.70f, TileNameCode.STONE, TileNameCode.ORE_SILVER),
// separate silver veins
//TaggedJoise(noiseBlobs(1.3f, 1.3f), 0.75f, TileNameCode.ORE_SILVER, TileNameCode.STONE),
//, TaggedJoise("Growing silver veins", noiseRidged(1.7f, 1.7f), 1.71f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.ORE_SILVER)
//, TaggedJoise("Cutting silver veins", noiseBlobs(0.7f, 0.7f), 0.26f, TileNameCode.ORE_SILVER, TileNameCode.STONE, TileNameCode.STONE)
// gold veins
//TaggedJoise(noiseRidged(2.2f, 2.2f), 1.71f, TileNameCode.STONE, TileNameCode.ORE_GOLD),
// separate gold veins
//TaggedJoise(noiseBlobs(1.3f, 1.3f), 0.75f, TileNameCode.ORE_GOLD, TileNameCode.STONE),
//, TaggedJoise("Growing gold veins", noiseRidged(1.7f, 1.7f), 1.73f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.ORE_GOLD)
//, TaggedJoise("Cutting gold veins", noiseBlobs(0.7f, 0.7f), 0.26f, TileNameCode.ORE_GOLD, TileNameCode.STONE, TileNameCode.STONE)
// topaz
//TaggedJoise(noiseBlobs(1.55f, 1.55f), 1.5f, TileNameCode.STONE, TileNameCode.RAW_TOPAZ),
// ruby/sapphire
//TaggedJoise(noiseBlobs(1.55f, 1.55f), 1.5f, TileNameCode.STONE, intArrayOf(TileNameCode.RAW_RUBY, TileNameCode.RAW_SAPPHIRE)),
// emerald
//TaggedJoise(noiseBlobs(1.55f, 1.55f), 1.5f, TileNameCode.STONE, TileNameCode.RAW_EMERALD),
// diamond
//TaggedJoise(noiseBlobs(1.45f, 1.45f), 1.5f, TileNameCode.STONE, TileNameCode.RAW_DIAMOND),
// amethyst
//TaggedJoise(noiseBlobs(1.45f, 1.45f), 1.5f, TileNameCode.STONE, TileNameCode.RAW_AMETHYST)
////, TaggedJoise("Growing topaz clusters", noiseBlobs(0.9f, 0.9f), 2f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.RAW_TOPAZ)
//, TaggedJoise("Growing aluminium oxide clusters", noiseBlobs(0.9f, 0.9f), 1.7f, TileNameCode.STONE, TileNameCode.STONE, intArrayOf(TileNameCode.RAW_RUBY, TileNameCode.RAW_SAPPHIRE))
//, TaggedJoise("Growing emerald clusters", noiseBlobs(0.9f, 0.9f), 1,7f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.RAW_EMERALD)
//, TaggedJoise("Growing hearts of white", noiseBlobs(0.9f, 0.9f), 1.83f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.RAW_DIAMOND)
//, TaggedJoise("Growing hearts of violet", noiseRidged(2.5f, 2.5f), 1.75f, TileNameCode.STONE, TileNameCode.STONE, TileNameCode.RAW_AMETHYST)
//, TaggedJoise("Cutting over-grown hearts", noiseBlobs(0.7f, 0.7f), 0.17f, TileNameCode.RAW_AMETHYST, TileNameCode.STONE, TileNameCode.STONE)
)
processNoiseLayers(noiseArray)
@@ -195,7 +184,7 @@ object MapGenerator {
private fun noiseBlobs(xStretch: Float, yStretch: Float): Joise {
val gradval = ModuleBasisFunction()
gradval.seed = SEED
gradval.seed = SEED xor random.nextLong()
gradval.setType(ModuleBasisFunction.BasisType.GRADVAL)
gradval.setInterpolation(ModuleBasisFunction.InterpolationType.QUINTIC)
@@ -207,6 +196,25 @@ object MapGenerator {
return Joise(gradval_scale)
}
/**
* Note:
* * Threshold 1.4 for rarer gem clusters, 1.35 for ores
*/
private fun noiseSimplex(xStretch: Float, yStretch: Float): Joise {
val simplex = ModuleFractal()
simplex.seed = SEED
simplex.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.SIMPLEX)
simplex.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.LINEAR)
simplex.setNumOctaves(2)
simplex.setFrequency(1.0)
val simplex_scale = ModuleScaleDomain()
simplex_scale.setScaleX(1.0 / xStretch)
simplex_scale.setScaleY(1.0 / yStretch)
simplex_scale.setSource(simplex)
return Joise(simplex_scale)
}
private fun generateOcean(noiseArrayLocal: IntArray): IntArray {
val oceanLeftP1 = noiseArrayLocal[OCEAN_WIDTH]
@@ -571,8 +579,8 @@ object MapGenerator {
*/
private fun carveByMap(noisemap: Any, scarcity: Float, tile: Int, message: String,
filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = noiseGradientStart,
filterEnd: Float = noiseGradientEnd) {
filterStart: Float = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) {
println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) {
@@ -601,8 +609,8 @@ object MapGenerator {
private fun fillByMap(noisemap: Any, scarcity: Float, replaceFrom: Int, replaceTo: Int, message: String,
filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = noiseGradientStart,
filterEnd: Float = noiseGradientEnd) {
filterStart: Float = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) {
println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) {
@@ -632,8 +640,8 @@ object MapGenerator {
private fun fillByMap(noisemap: Any, scarcity: Float, replaceFrom: Int, tile: IntArray, message: String,
filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = noiseGradientStart,
filterEnd: Float = noiseGradientEnd) {
filterStart: Float = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) {
println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) {
@@ -943,6 +951,6 @@ object MapGenerator {
var replaceFromTerrain: Int, var replaceFromWall: Int,
var replaceTo: Any,
var filter: NoiseFilter = NoiseFilterQuadratic,
var filterArg1: Float = noiseGradientStart,
var filterArg2: Float = noiseGradientEnd)
var filterArg1: Float = NOISE_GRAD_START,
var filterArg2: Float = NOISE_GRAD_END)
}

View File

@@ -12,9 +12,14 @@ import org.newdawn.slick.GameContainer
import org.newdawn.slick.SlickException
import org.newdawn.slick.state.StateBasedGame
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
import java.util.logging.FileHandler
import java.util.logging.Level
import java.util.logging.Logger
import java.util.logging.SimpleFormatter
/**
* Created by minjaesong on 15-12-30.
@@ -120,7 +125,22 @@ constructor(gamename: String) : StateBasedGame(gamename) {
appgc.start()
}
catch (ex: SlickException) {
Logger.getLogger(Terrarum::class.java.name).log(Level.SEVERE, null, ex)
val logger = Logger.getLogger(Terrarum::class.java.name)
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
val calendar = Calendar.getInstance()
val filepath = "$defaultDir/crashlog-${dateFormat.format(calendar.time)}.txt"
val fileHandler = FileHandler(filepath)
logger.addHandler(fileHandler)
val formatter = SimpleFormatter()
fileHandler.formatter = formatter
//logger.info()
println("The game has been crashed!")
println("Crash log were saved to $filepath.")
println("================================================================================")
logger.log(Level.SEVERE, null, ex)
}
}

View File

@@ -133,6 +133,8 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
@Transient private val map: GameMap
@Transient private val MASS_DEFAULT = 60f
init {
// referenceID = HQRNG().nextLong() // renew ID just in case
map = Terrarum.game.map
@@ -172,25 +174,41 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
x - (baseHitboxW / 2 - hitboxTranslateX) * scale, y - (baseHitboxH - hitboxTranslateY) * scale, baseHitboxW * scale, baseHitboxH * scale)
}
private fun updatePhysicalInfos() {
scale = actorValue.getAsFloat(AVKey.SCALE) ?: 1f
mass = (actorValue.getAsFloat(AVKey.BASEMASS) ?: MASS_DEFAULT) * FastMath.pow(scale, 3f)
if (elasticity != 0f) elasticity = 0f
}
override fun update(gc: GameContainer, delta_t: Int) {
if (isUpdate) {
updatePhysicalInfos()
/**
* Update variables
*/
// make NoClip work for player
if (this is Player) {
isNoSubjectToGrav = isPlayerNoClip
isNoCollideWorld = isPlayerNoClip
isNoSubjectToFluidResistance = isPlayerNoClip
}
if (mass < MASS_LOWEST) mass = MASS_LOWEST // clamp to minimum possible mass
// clamp to the minimum possible mass
if (mass < MASS_LOWEST) mass = MASS_LOWEST
// set sprite dimension vars if there IS sprite for the actor
if (sprite != null) {
baseSpriteHeight = sprite!!.height
baseSpriteWidth = sprite!!.width
}
// copy gravitational constant from the map the actor is in
gravitation = map.gravitation
// Auto climb rate. Clamp to TSIZE
AUTO_CLIMB_RATE = Math.min(TSIZE / 8 * FastMath.sqrt(scale), TSIZE.toFloat()).toInt()
// Actors are subject to the gravity and the buoyancy if they are not levitating
if (!isNoSubjectToGrav) {
applyGravitation()
applyBuoyancy()
@@ -207,7 +225,7 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
//}
// Set 'next' positions to fiddle with
// Set 'next' position (hitbox) to fiddle with
updateNextHitboxFromVelo()
@@ -217,15 +235,16 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
// updateHorizontalPos();
//}
//else {
// compensate for colliding
updateHorizontalPos()
updateVerticalPos()
//}
// apply our compensation to actual hitbox
updateHitboxX()
updateHitboxY()
// make sure the actor does not go out of the map
clampNextHitbox()
clampHitbox()
}
@@ -259,29 +278,30 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
private fun updateVerticalPos() {
if (!isNoCollideWorld) {
// check downward
if (veloY >= 0) {
// order of the if-elseif chain is IMPORTANT
if (isColliding(CONTACT_AREA_BOTTOM)) {
if (veloY >= 0) { // check downward
if (isColliding(CONTACT_AREA_BOTTOM)) { // the ground has dug into the body
adjustHitBottom()
elasticReflectY()
grounded = true
} else if (isColliding(CONTACT_AREA_BOTTOM, 0, 1)) {
}
else if (isColliding(CONTACT_AREA_BOTTOM, 0, 1)) { // the actor is standing ON the ground
elasticReflectY()
grounded = true
} else {
}
else { // the actor is not grounded at all
grounded = false
}
} else if (veloY < 0) {
}
else if (veloY < 0) { // check upward
grounded = false
// order of the if-elseif chain is IMPORTANT
if (isColliding(CONTACT_AREA_TOP)) {
if (isColliding(CONTACT_AREA_TOP)) { // the ceiling has dug into the body
adjustHitTop()
elasticReflectY()
} else if (isColliding(CONTACT_AREA_TOP, 0, -1)) {
elasticReflectY() // for reversed gravity
} else {
}
else if (isColliding(CONTACT_AREA_TOP, 0, -1)) { // the actor is touching the ceiling
elasticReflectY() // reflect on ceiling, for reversed gravity
}
else { // the actor is not grounded at all
}
}
}
@@ -294,6 +314,7 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
var newYOff = 0 // always positive
// count up Y offset until the actor is not touching the ground
var colliding: Boolean
do {
newYOff += 1
@@ -311,6 +332,7 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
var newYOff = 0 // always positive
// count up Y offset until the actor is not touching the ceiling
var colliding: Boolean
do {
newYOff += 1
@@ -323,49 +345,57 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
private fun updateHorizontalPos() {
if (!isNoCollideWorld) {
// check right
if (veloX >= 0.5) {
// order of the if-elseif chain is IMPORTANT
if (veloX >= 0.5) { // check right
if (isColliding(CONTACT_AREA_RIGHT) && !isColliding(CONTACT_AREA_LEFT)) {
// the actor is embedded to the wall
adjustHitRight()
elasticReflectX()
} else if (isColliding(CONTACT_AREA_RIGHT, 1, 0) && !isColliding(CONTACT_AREA_LEFT, -1, 0)) {
elasticReflectX()
} else {
}
} else if (veloX <= -0.5) {
else if (isColliding(CONTACT_AREA_RIGHT, 1, 0) && !isColliding(CONTACT_AREA_LEFT, -1, 0)) {
// the actor is touching the wall
elasticReflectX()
}
else {
}
}
else if (veloX <= -0.5) { // check left
// System.out.println("collidingleft");
// order of the if-elseif chain is IMPORTANT
if (isColliding(CONTACT_AREA_LEFT) && !isColliding(CONTACT_AREA_RIGHT)) {
// the actor is embedded to the wall
adjustHitLeft()
elasticReflectX()
} else if (isColliding(CONTACT_AREA_LEFT, -1, 0) && !isColliding(CONTACT_AREA_RIGHT, 1, 0)) {
elasticReflectX()
} else {
}
} else {
else if (isColliding(CONTACT_AREA_LEFT, -1, 0) && !isColliding(CONTACT_AREA_RIGHT, 1, 0)) {
// the actor is touching the wall
elasticReflectX()
}
else {
}
}
else { // check both sides?
// System.out.println("updatehorizontal - |velo| < 0.5");
if (isColliding(CONTACT_AREA_LEFT) || isColliding(CONTACT_AREA_RIGHT)) {
elasticReflectX()
}
//if (isColliding(CONTACT_AREA_LEFT) || isColliding(CONTACT_AREA_RIGHT)) {
// elasticReflectX()
//}
}
}
}
private fun adjustHitRight() {
val newY = nextHitbox!!.posY // look carefully, getPos or getPointed
val newY = nextHitbox!!.posY // look carefully, posY or pointedY
// int-ify posY of nextHitbox
nextHitbox!!.setPositionX(FastMath.floor(nextHitbox!!.posX + nextHitbox!!.width) - nextHitbox!!.width)
var newXOff = 0 // always positive
// count up Y offset until the actor is not touching the wall
var colliding: Boolean
do {
newXOff += 1
colliding = isColliding(CONTACT_AREA_BOTTOM, -newXOff, 0)
} while (newXOff < TSIZE && colliding)
val newX = nextHitbox!!.posX - newXOff
val newX = nextHitbox!!.posX - newXOff -1 // -1: Q&D way to prevent the actor sticking to the wall and won't detach
nextHitbox!!.setPosition(newX, newY)
}
@@ -376,14 +406,15 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
var newXOff = 0 // always positive
// count up Y offset until the actor is not touching the wall
var colliding: Boolean
do {
newXOff += 1
colliding = isColliding(CONTACT_AREA_TOP, newXOff, 0)
} while (newXOff < TSIZE && colliding)
val newX = nextHitbox!!.posX + newXOff
nextHitbox!!.setPosition(newX, newY) // + 1; float-point rounding compensation (i think...)
val newX = nextHitbox!!.posX + newXOff +1 // +1: Q&D way to prevent the actor sticking to the wall and won't detach
nextHitbox!!.setPosition(newX, newY)
}
private fun elasticReflectX() {
@@ -394,9 +425,7 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
if (veloY != 0f) veloY = -veloY * elasticity
}
private fun isColliding(side: Int, tx: Int = 0, ty: Int = 0): Boolean {
return getContactingArea(side, tx, ty) > 1
}
private fun isColliding(side: Int, tx: Int = 0, ty: Int = 0): Boolean = getContactingArea(side, tx, ty) > 1
private fun getContactingArea(side: Int, translateX: Int = 0, translateY: Int = 0): Int {
var contactAreaCounter = 0
@@ -408,19 +437,23 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
tileX = div16TruncateToMapWidth(Math.round(nextHitbox!!.hitboxStart.x)
+ i + translateX)
tileY = div16TruncateToMapHeight(Math.round(nextHitbox!!.hitboxEnd.y) + translateY)
} else if (side == CONTACT_AREA_TOP) {
}
else if (side == CONTACT_AREA_TOP) {
tileX = div16TruncateToMapWidth(Math.round(nextHitbox!!.hitboxStart.x)
+ i + translateX)
tileY = div16TruncateToMapHeight(Math.round(nextHitbox!!.hitboxStart.y) + translateY)
} else if (side == CONTACT_AREA_RIGHT) {
}
else if (side == CONTACT_AREA_RIGHT) {
tileX = div16TruncateToMapWidth(Math.round(nextHitbox!!.hitboxEnd.x) + translateX)
tileY = div16TruncateToMapHeight(Math.round(nextHitbox!!.hitboxStart.y)
+ i + translateY)
} else if (side == CONTACT_AREA_LEFT) {
}
else if (side == CONTACT_AREA_LEFT) {
tileX = div16TruncateToMapWidth(Math.round(nextHitbox!!.hitboxStart.x) + translateX)
tileY = div16TruncateToMapHeight(Math.round(nextHitbox!!.hitboxStart.y)
+ i + translateY)
} else {
}
else {
throw IllegalArgumentException(side.toString() + ": Wrong side input")
}
@@ -443,19 +476,23 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
tileX = div16TruncateToMapWidth(Math.round(nextHitbox!!.hitboxStart.x)
+ i + translateX)
tileY = div16TruncateToMapHeight(Math.round(nextHitbox!!.hitboxEnd.y) + translateY)
} else if (side == CONTACT_AREA_TOP) {
}
else if (side == CONTACT_AREA_TOP) {
tileX = div16TruncateToMapWidth(Math.round(nextHitbox!!.hitboxStart.x)
+ i + translateX)
tileY = div16TruncateToMapHeight(Math.round(nextHitbox!!.hitboxStart.y) + translateY)
} else if (side == CONTACT_AREA_RIGHT) {
}
else if (side == CONTACT_AREA_RIGHT) {
tileX = div16TruncateToMapWidth(Math.round(nextHitbox!!.hitboxEnd.x) + translateX)
tileY = div16TruncateToMapHeight(Math.round(nextHitbox!!.hitboxStart.y)
+ i + translateY)
} else if (side == CONTACT_AREA_LEFT) {
}
else if (side == CONTACT_AREA_LEFT) {
tileX = div16TruncateToMapWidth(Math.round(nextHitbox!!.hitboxStart.x) + translateX)
tileY = div16TruncateToMapHeight(Math.round(nextHitbox!!.hitboxStart.y)
+ i + translateY)
} else {
}
else {
throw IllegalArgumentException(side.toString() + ": Wrong side input")
}

View File

@@ -2,11 +2,11 @@ package com.torvald.terrarum.gameactors
import com.torvald.JsonFetcher
import com.torvald.random.Fudge3
import com.torvald.random.HQRNG
import com.torvald.terrarum.langpack.Lang
import com.google.gson.JsonObject
import org.newdawn.slick.SlickException
import java.io.IOException
import java.security.SecureRandom
/**
* Created by minjaesong on 16-03-25.
@@ -14,7 +14,7 @@ import java.io.IOException
object CreatureRawInjector {
const val JSONPATH = "./res/raw/creatures/"
private const val MULTIPLIER_RAW_ELEM_SUFFIX = "mult"
private const val MULTIPLIER_RAW_ELEM_SUFFIX = AVKey.MULTIPLIER_SUFFIX
/**
* 'Injects' creature raw ActorValue to the ActorValue reference provided.
@@ -26,10 +26,10 @@ object CreatureRawInjector {
fun inject(actorValueRef: ActorValue, jsonFileName: String) {
val jsonObj = JsonFetcher.readJson(JSONPATH + jsonFileName)
val elementsString = arrayOf("racename", "racenameplural")
val elementsFloat = arrayOf("baseheight", "basemass", "accel", "toolsize", "encumbrance")
val elementsFloatVariable = arrayOf("strength", "speed", "jumppower", "scale", "speed")
val elementsBoolean = arrayOf("intelligent")
val elementsString = arrayOf(AVKey.RACENAME, AVKey.RACENAMEPLURAL)
val elementsFloat = arrayOf(AVKey.BASEHEIGHT, AVKey.BASEMASS, AVKey.ACCEL, AVKey.TOOLSIZE, AVKey.ENCUMBRANCE)
val elementsFloatVariable = arrayOf(AVKey.STRENGTH, AVKey.SPEED, AVKey.JUMPPOWER, AVKey.SCALE, AVKey.SPEED)
val elementsBoolean = arrayOf(AVKey.INTELLIGENT)
// val elementsMultiplyFromOne = arrayOf()
setAVStrings(actorValueRef, elementsString, jsonObj)
@@ -38,8 +38,8 @@ object CreatureRawInjector {
// setAVMultiplyFromOne(actorValueRef, elementsMultiplyFromOne, jsonObj)
setAVBooleans(actorValueRef, elementsBoolean, jsonObj)
actorValueRef["accel"] = Player.WALK_ACCEL_BASE
actorValueRef["accelmult"] = 1f
actorValueRef[AVKey.ACCEL] = Player.WALK_ACCEL_BASE
actorValueRef[AVKey.ACCELMULT] = 1f
}
/**
@@ -54,7 +54,7 @@ object CreatureRawInjector {
for (s in elemSet) {
val baseValue = jsonObject.get(s).asFloat
// roll fudge dice and get value [-3, 3] as [0, 6]
val varSelected = Fudge3(HQRNG()).rollForArray()
val varSelected = Fudge3(SecureRandom()).rollForArray()
// get multiplier from json. Assuming percentile
val multiplier = jsonObject.get(s + MULTIPLIER_RAW_ELEM_SUFFIX).asJsonArray.get(varSelected).asInt
val realValue = baseValue * multiplier / 100f
@@ -106,7 +106,7 @@ object CreatureRawInjector {
for (s in elemSet) {
val baseValue = 1f
// roll fudge dice and get value [-3, 3] as [0, 6]
val varSelected = Fudge3(HQRNG()).rollForArray()
val varSelected = Fudge3(SecureRandom()).rollForArray()
// get multiplier from json. Assuming percentile
val multiplier = jsonObject.get(s).asJsonArray.get(varSelected).asInt
val realValue = baseValue * multiplier / 100f

View File

@@ -12,7 +12,7 @@ import java.util.*
* Created by minjaesong on 16-03-14.
*/
open class NPCIntelligentBase : ActorWithBody()
, AIControlled, Pocketed, CanBeStoredAsItem, Factionable, LandHolder {
, AIControlled, Pocketed, CanBeAnItem, Factionable, LandHolder {
override var itemData: InventoryItem = object : InventoryItem {
override var itemID = HQRNG().nextLong()

View File

@@ -1,6 +1,7 @@
package com.torvald.terrarum.gameactors
import com.torvald.spriteanimation.SpriteAnimation
import com.torvald.terrarum.mapdrawer.MapDrawer
/**
* Created by minjaesong on 16-03-25.
@@ -20,9 +21,9 @@ object PFCynthia {
p.sprite!!.setRowsAndFrames(1, 1)
p.sprite!!.setAsVisible()
p.setHitboxDimension(15, 40, 9, 0)
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT) ?: Player.BASE_HEIGHT, 9, 0)
p.setPosition((4096 * 16).toFloat(), (300 * 16).toFloat())
p.setPosition((4096 * MapDrawer.TILE_SIZE).toFloat(), (300 * 16).toFloat())
return p
}

View File

@@ -5,6 +5,7 @@ import com.torvald.terrarum.gameactors.faction.Faction
import com.torvald.spriteanimation.SpriteAnimation
import com.google.gson.JsonObject
import com.torvald.terrarum.gameactors.faction.FactionFactory
import com.torvald.terrarum.mapdrawer.MapDrawer
import org.newdawn.slick.SlickException
import java.io.IOException
@@ -32,38 +33,36 @@ object PFSigrid {
p.spriteGlow!!.setAsVisible()
p.actorValue = ActorValue()
p.actorValue["scale"] = 1.0f
p.actorValue["speed"] = 4.0f
p.actorValue["speedmult"] = 1.0f
p.actorValue["accel"] = Player.WALK_ACCEL_BASE
p.actorValue["accelmult"] = 1.0f
p.actorValue[AVKey.SCALE] = 1.0f
p.actorValue[AVKey.SPEED] = 4.0f
p.actorValue[AVKey.SPEEDMULT] = 1.0f
p.actorValue[AVKey.ACCEL] = Player.WALK_ACCEL_BASE
p.actorValue[AVKey.ACCELMULT] = 1.0f
p.actorValue[AVKey.JUMPPOWER] = 5f
p.actorValue["jumppower"] = 5f
p.actorValue["basemass"] = 80f
p.actorValue["physiquemult"] = 1 // Constant 1.0 for player, meant to be used by random mobs
p.actorValue[AVKey.BASEMASS] = 80f
p.actorValue[AVKey.PHYSIQUEMULT] = 1 // Constant 1.0 for player, meant to be used by random mobs
/**
* fixed value, or 'base value', from creature strength of Dwarf Fortress.
* Human race uses 1000. (see CreatureHuman.json)
*/
p.actorValue["strength"] = 1414
p.actorValue["encumbrance"] = 1000
p.actorValue[AVKey.STRENGTH] = 1414
p.actorValue[AVKey.ENCUMBRANCE] = 1000
p.actorValue[AVKey.BASEHEIGHT] = 46
p.actorValue["name"] = "Sigrid"
p.actorValue[AVKey.NAME] = "Sigrid"
p.actorValue["intelligent"] = true
p.actorValue[AVKey.INTELLIGENT] = true
p.actorValue["luminosity"] = 5980540
p.actorValue[AVKey.LUMINOSITY] = 5980540
p.actorValue["selectedtile"] = 16
//p.setHitboxDimension(18, 46, 8, 0)
p.setHitboxDimension(15, 46, 10, 0)
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 10, 0)
p.inventory = ActorInventory(0x7FFFFFFF, true)
p.setPosition((4096 * 16).toFloat(), (300 * 16).toFloat())
p.setPosition((4096 * MapDrawer.TILE_SIZE).toFloat(), (300 * 16).toFloat())
p.faction.add(FactionFactory.create("FactionSigrid.json"))

View File

@@ -69,9 +69,9 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
override var houseDesignation: ArrayList<Int>? = null
override var luminosity: Int
get() = actorValue.getAsInt("luminosity") ?: 0
get() = actorValue.getAsInt(AVKey.LUMINOSITY) ?: 0
set(value) {
actorValue["luminosity"] = value
actorValue[AVKey.LUMINOSITY] = value
}
companion object {
@@ -79,7 +79,8 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
@Transient internal const val WALK_STOP_ACCEL = 0.32f
@Transient internal const val WALK_ACCEL_BASE = 0.32f
@Transient val PLAYER_REF_ID: Long = 0x51621D
@Transient const val PLAYER_REF_ID: Long = 0x51621D
@Transient const val BASE_HEIGHT = 40
}
/**
@@ -100,7 +101,6 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
if (vehicleRiding is Player)
throw RuntimeException("Attempted to 'ride' " + "player object.")
updatePhysicalInfos()
super.update(gc, delta_t)
updateSprite(delta_t)
@@ -113,12 +113,6 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
}
private fun updatePhysicalInfos() {
scale = actorValue.getAsFloat("scale")!!
mass = actorValue.getAsFloat("basemass")!! * FastMath.pow(scale, 3f)
if (elasticity != 0f) elasticity = 0f
}
/**
* @param left (even if the game is joypad controlled, you must give valid value)
@@ -128,8 +122,8 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
private fun walkHorizontal(left: Boolean, absAxisVal: Float) {
//if ((!super.isWalledLeft() && left) || (!super.isWalledRight() && !left)) {
readonly_totalX = veloX +
actorValue.getAsFloat("accel")!! *
actorValue.getAsFloat("accelmult")!! *
actorValue.getAsFloat(AVKey.ACCEL)!! *
actorValue.getAsFloat(AVKey.ACCELMULT)!! *
FastMath.sqrt(scale) *
applyAccelRealism(walkPowerCounter) *
(if (left) -1 else 1).toFloat() *
@@ -142,8 +136,8 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
}
// Clamp veloX
veloX = absClamp(veloX, actorValue.getAsFloat("speed")!!
* actorValue.getAsFloat("speedmult")!!
veloX = absClamp(veloX, actorValue.getAsFloat(AVKey.SPEED)!!
* actorValue.getAsFloat(AVKey.SPEEDMULT)!!
* FastMath.sqrt(scale))
// Heading flag
@@ -162,8 +156,8 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
*/
private fun walkVertical(up: Boolean, absAxisVal: Float) {
readonly_totalY = veloY +
actorValue.getAsFloat("accel")!! *
actorValue.getAsFloat("accelmult")!! *
actorValue.getAsFloat(AVKey.ACCEL)!! *
actorValue.getAsFloat(AVKey.ACCELMULT)!! *
FastMath.sqrt(scale) *
applyAccelRealism(walkPowerCounter) *
(if (up) -1 else 1).toFloat() *
@@ -176,8 +170,8 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
}
// Clamp veloX
veloY = absClamp(veloY, actorValue.getAsFloat("speed")!!
* actorValue.getAsFloat("speedmult")!!
veloY = absClamp(veloY, actorValue.getAsFloat(AVKey.SPEED)!!
* actorValue.getAsFloat(AVKey.SPEEDMULT)!!
* FastMath.sqrt(scale))
}
@@ -210,15 +204,15 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
private fun walkHStop() {
if (veloX > 0) {
veloX -= actorValue.getAsFloat("accel")!! *
actorValue.getAsFloat("accelmult")!! *
veloX -= actorValue.getAsFloat(AVKey.ACCEL)!! *
actorValue.getAsFloat(AVKey.ACCELMULT)!! *
FastMath.sqrt(scale)
// compensate overshoot
if (veloX < 0) veloX = 0f
} else if (veloX < 0) {
veloX += actorValue.getAsFloat("accel")!! *
actorValue.getAsFloat("accelmult")!! *
veloX += actorValue.getAsFloat(AVKey.ACCEL)!! *
actorValue.getAsFloat(AVKey.ACCELMULT)!! *
FastMath.sqrt(scale)
// compensate overshoot
@@ -233,7 +227,7 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
private fun walkVStop() {
if (veloY > 0) {
veloY -= WALK_STOP_ACCEL *
actorValue.getAsFloat("accelmult")!! *
actorValue.getAsFloat(AVKey.ACCELMULT)!! *
FastMath.sqrt(scale)
// compensate overshoot
@@ -241,7 +235,7 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
veloY = 0f
} else if (veloY < 0) {
veloY += WALK_STOP_ACCEL *
actorValue.getAsFloat("accelmult")!! *
actorValue.getAsFloat(AVKey.ACCELMULT)!! *
FastMath.sqrt(scale)
// compensate overshoot
@@ -256,12 +250,12 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
private fun updateMovementControl() {
if (!noClip) {
if (grounded) {
actorValue.set("accelmult", 1f)
actorValue.set(AVKey.ACCELMULT, 1f)
} else {
actorValue.set("accelmult", ACCEL_MULT_IN_FLIGHT)
actorValue.set(AVKey.ACCELMULT, ACCEL_MULT_IN_FLIGHT)
}
} else {
actorValue.set("accelmult", 1f)
actorValue.set(AVKey.ACCELMULT, 1f)
}
}
@@ -405,7 +399,7 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
private fun jump() {
if (jumping) {
val len = MAX_JUMP_LENGTH.toFloat()
val pwr = actorValue.getAsFloat("jumppower")!!
val pwr = actorValue.getAsFloat(AVKey.JUMPPOWER)!! * (actorValue.getAsFloat(AVKey.JUMPPOWERMULT) ?: 1f)
// increment jump counter
if (jumpCounter < len) jumpCounter += 1

View File

@@ -14,6 +14,27 @@
Arrangements in the map
Time →→→→
voice 1 → # # # # # # #
voice 2 → # # # # # # #
↑ played simultaneously along the X-axis
voice 1 → □□□□□□□□□□□□□□□□...
voice 2 → □□□□□□□□□□□□□□□□...
↑ played simultaneously along the X-axis
- Each tracker head and body are connected by placing tracks adjacent to each other or connecting them with wire.
Connect two or more tracker head to play the array of trackers play simultaneously (multi-tracking)
- Serialisation
<actorid>.json
{
0 = [long],
1 = [long],
...
47 = [long],
speed = 120
}
*long: array of bits that indicates the note is stricken (1) or not (0)
0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000
↑G5 ↑C5 ↑C4 ↑C3 ↑C2 ↑C1 E0↑
(Assuming C3 (32nd bit) as middle 'C')
*speed: in BPM

View File

@@ -29,8 +29,8 @@ class SetGlobalLightLevel : ConsoleCommand {
try {
val GL = args[1].toInt()
if (GL.toInt() < 0 || GL.toInt() >= LightmapRenderer.COLOUR_DOMAIN_SIZE) {
Echo().execute("Range: 0-" + (LightmapRenderer.COLOUR_DOMAIN_SIZE - 1))
if (GL.toInt() < 0 || GL.toInt() >= LightmapRenderer.COLOUR_RANGE_SIZE) {
Echo().execute("Range: 0-" + (LightmapRenderer.COLOUR_RANGE_SIZE - 1))
}
else {
Terrarum.game.map.globalLight = GL

View File

@@ -0,0 +1,30 @@
package com.torvald.terrarum.gameactors
/**
* Created by minjaesong on 16-04-02.
*/
object AVKey {
const val MULTIPLIER_SUFFIX = "mult"
const val SPEED = "speed"
const val SPEEDMULT = "speed$MULTIPLIER_SUFFIX"
const val ACCEL = "accel"
const val ACCELMULT = "accel$MULTIPLIER_SUFFIX"
const val SCALE = "scale"
const val BASEHEIGHT = "baseheight"
const val BASEMASS = "basemass"
const val JUMPPOWER = "jumppower"
const val JUMPPOWERMULT = "jumppower$MULTIPLIER_SUFFIX"
const val STRENGTH = "strength"
const val ENCUMBRANCE = "encumbrance"
const val LUMINOSITY = "luminosity"
const val PHYSIQUEMULT = "physique$MULTIPLIER_SUFFIX"
const val NAME = "name"
const val RACENAME = "racename"
const val RACENAMEPLURAL = "racenameplural"
const val TOOLSIZE = "toolsize"
const val INTELLIGENT = "intelligent"
}

View File

@@ -5,7 +5,7 @@ import com.torvald.terrarum.gameitem.InventoryItem
/**
* Created by minjaesong on 16-03-14.
*/
interface CanBeStoredAsItem {
interface CanBeAnItem {
fun attachItemData()