mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-14 15:46:06 +09:00
new sunlight and skybox colouring collected from real world measurements (reports TBA)
Former-commit-id: 6abaa1e16d0fd7a71f95bd0265809aad9e34a425 Former-commit-id: bb871bd87072f27b9cc29594f9eed615351df5f8
This commit is contained in:
@@ -49,6 +49,8 @@ class Point2d(var x: Double, var y: Double) : Cloneable {
|
|||||||
|
|
||||||
fun toVector() = Vector2(x, y)
|
fun toVector() = Vector2(x, y)
|
||||||
|
|
||||||
|
fun copy() = Point2d(x, y)
|
||||||
|
|
||||||
fun length(other: Point2d) = distSqr(other).sqrt()
|
fun length(other: Point2d) = distSqr(other).sqrt()
|
||||||
fun distSqr(other: Point2d) = ((this.x - other.x).sqr() + (this.y - other.y).sqr())
|
fun distSqr(other: Point2d) = ((this.x - other.x).sqr() + (this.y - other.y).sqr())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,9 +69,6 @@ constructor() : BasicGameState() {
|
|||||||
internal val player: ActorHumanoid // currently POSSESSED actor :)
|
internal val player: ActorHumanoid // currently POSSESSED actor :)
|
||||||
get() = playableActorDelegate!!.actor
|
get() = playableActorDelegate!!.actor
|
||||||
|
|
||||||
//private var GRADIENT_IMAGE: Image? = null
|
|
||||||
//private var skyBox: Rectangle? = null
|
|
||||||
|
|
||||||
var screenZoom = 1.0f
|
var screenZoom = 1.0f
|
||||||
val ZOOM_MAX = 2.0f
|
val ZOOM_MAX = 2.0f
|
||||||
val ZOOM_MIN = 0.5f
|
val ZOOM_MIN = 0.5f
|
||||||
@@ -99,7 +96,7 @@ constructor() : BasicGameState() {
|
|||||||
private val UI_INVENTORY_PLAYER = "uiInventoryPlayer"
|
private val UI_INVENTORY_PLAYER = "uiInventoryPlayer"
|
||||||
private val UI_INVENTORY_ANON = "uiInventoryAnon"
|
private val UI_INVENTORY_ANON = "uiInventoryAnon"
|
||||||
|
|
||||||
val paused: Boolean
|
var paused: Boolean = false
|
||||||
get() = consoleHandler.isOpened
|
get() = consoleHandler.isOpened
|
||||||
|
|
||||||
@Throws(SlickException::class)
|
@Throws(SlickException::class)
|
||||||
@@ -279,7 +276,11 @@ constructor() : BasicGameState() {
|
|||||||
throw IllegalArgumentException("No such actor in actorContainer: $refid")
|
throw IllegalArgumentException("No such actor in actorContainer: $refid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// take care of old delegate
|
||||||
|
playableActorDelegate!!.actor.collisionType = HumanoidNPC.DEFAULT_COLLISION_TYPE
|
||||||
|
// accept new delegate
|
||||||
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
|
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
|
||||||
|
playableActorDelegate!!.actor.collisionType = ActorWithBody.COLLISION_KINEMATIC
|
||||||
WorldSimulator(world, player, UPDATE_DELTA)
|
WorldSimulator(world, player, UPDATE_DELTA)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +299,8 @@ constructor() : BasicGameState() {
|
|||||||
blendNormal()
|
blendNormal()
|
||||||
|
|
||||||
|
|
||||||
drawSkybox(gwin)
|
drawSkybox(gwin) // drawing to gwin so that any lights from lamp wont "leak" to the skybox
|
||||||
|
// e.g. Bright blue light on sunset
|
||||||
|
|
||||||
|
|
||||||
// make camara work //
|
// make camara work //
|
||||||
@@ -306,6 +308,8 @@ constructor() : BasicGameState() {
|
|||||||
worldG.translate(-MapCamera.x.toFloat(), -MapCamera.y.toFloat())
|
worldG.translate(-MapCamera.x.toFloat(), -MapCamera.y.toFloat())
|
||||||
|
|
||||||
|
|
||||||
|
blendNormal()
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// draw map related stuffs //
|
// draw map related stuffs //
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class StateNoiseTexGen : BasicGameState() {
|
|||||||
return Joise(ridged_autocorrect)
|
return Joise(ridged_autocorrect)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun noiseSmokyFractal(): Joise {
|
private fun noiseBrownian(): Joise {
|
||||||
val ridged = ModuleFractal()
|
val ridged = ModuleFractal()
|
||||||
ridged.setType(ModuleFractal.FractalType.FBM)
|
ridged.setType(ModuleFractal.FractalType.FBM)
|
||||||
ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||||
@@ -114,7 +114,7 @@ class StateNoiseTexGen : BasicGameState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun generateNoiseImage() {
|
fun generateNoiseImage() {
|
||||||
val noiseModule = noiseBillowFractal() // change noise function here
|
val noiseModule = noiseBrownian() // change noise function here
|
||||||
|
|
||||||
for (y in 0..imagesize - 1) {
|
for (y in 0..imagesize - 1) {
|
||||||
for (x in 0..imagesize - 1) {
|
for (x in 0..imagesize - 1) {
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ internal object ExportMap : ConsoleCommand {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
RasterWriter.writePNG_RGB(
|
RasterWriter.writePNG_RGB(
|
||||||
Terrarum.ingame.world.width, Terrarum.ingame.world.height, mapData, dir + args[1] + ".tga")
|
Terrarum.ingame.world.width, Terrarum.ingame.world.height, mapData, dir + args[1] + ".png")
|
||||||
Echo("ExportMap: exported to " + args[1] + ".tga")
|
Echo("ExportMap: exported to " + args[1] + ".png")
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
|
|||||||
var scale: Double
|
var scale: Double
|
||||||
get() = (actorValue.getAsDouble(AVKey.SCALE) ?: 1.0) *
|
get() = (actorValue.getAsDouble(AVKey.SCALE) ?: 1.0) *
|
||||||
(actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
|
(actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
|
||||||
set(value) = actorValue.set(AVKey.SCALE, value / (actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0))
|
set(value) {
|
||||||
|
actorValue[AVKey.SCALE] = value / (actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
|
||||||
|
}
|
||||||
@Transient val MASS_LOWEST = 0.1 // Kilograms
|
@Transient val MASS_LOWEST = 0.1 // Kilograms
|
||||||
/** Apparent mass. Use "avBaseMass" for base mass */
|
/** Apparent mass. Use "avBaseMass" for base mass */
|
||||||
var mass: Double
|
var mass: Double
|
||||||
@@ -284,6 +286,10 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
|
|||||||
hitboxTranslateY = ty.toDouble()
|
hitboxTranslateY = ty.toDouble()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setPosition(pos: Point2d) = setPosition(pos.x, pos.y)
|
||||||
|
fun setPosition(pos: Vector2) = setPosition(pos.x, pos.y)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set hitbox position from bottom-center point
|
* Set hitbox position from bottom-center point
|
||||||
* @param x
|
* @param x
|
||||||
@@ -291,14 +297,14 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
|
|||||||
*/
|
*/
|
||||||
fun setPosition(x: Double, y: Double) {
|
fun setPosition(x: Double, y: Double) {
|
||||||
hitbox.setFromWidthHeight(
|
hitbox.setFromWidthHeight(
|
||||||
x - (baseHitboxW / 2 - hitboxTranslateX) * scale,
|
x - (baseHitboxW / 2 - hitboxTranslateX) * (1 - scale),
|
||||||
y - (baseHitboxH - hitboxTranslateY) * scale,
|
y - (baseHitboxH - hitboxTranslateY) * (1 - scale),
|
||||||
baseHitboxW * scale,
|
baseHitboxW * scale,
|
||||||
baseHitboxH * scale)
|
baseHitboxH * scale)
|
||||||
|
|
||||||
nextHitbox.setFromWidthHeight(
|
nextHitbox.setFromWidthHeight(
|
||||||
x - (baseHitboxW / 2 - hitboxTranslateX) * scale,
|
x - (baseHitboxW / 2 - hitboxTranslateX) * (1 - scale),
|
||||||
y - (baseHitboxH - hitboxTranslateY) * scale,
|
y - (baseHitboxH - hitboxTranslateY) * (1 - scale),
|
||||||
baseHitboxW * scale,
|
baseHitboxW * scale,
|
||||||
baseHitboxH * scale)
|
baseHitboxH * scale)
|
||||||
}
|
}
|
||||||
@@ -1113,9 +1119,12 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
|
|||||||
/**
|
/**
|
||||||
* Enumerations that exported to JSON
|
* Enumerations that exported to JSON
|
||||||
*/
|
*/
|
||||||
@Transient const val COLLISION_KINEMATIC = 1 // does not displaced by external forces
|
@Transient const val COLLISION_NOCOLLIDE = 0
|
||||||
|
@Transient const val COLLISION_KINEMATIC = 1 // does not displaced by external forces when collided, but it still can move (e.g. player, elevator)
|
||||||
@Transient const val COLLISION_DYNAMIC = 2 // displaced by external forces
|
@Transient const val COLLISION_DYNAMIC = 2 // displaced by external forces
|
||||||
@Transient const val COLLISION_STATIC = 3 // does not displaced by external forces, target of collision
|
@Transient const val COLLISION_STATIC = 3 // does not displaced by external forces, target of collision (e.g. nonmoving static obj)
|
||||||
|
@Transient const val COLLISION_KNOCKBACK_GIVER = 4 // mobs
|
||||||
|
@Transient const val COLLISION_KNOCKBACK_TAKER = 5 // benevolent NPCs
|
||||||
@Transient const val BLEND_NORMAL = 4
|
@Transient const val BLEND_NORMAL = 4
|
||||||
@Transient const val BLEND_SCREEN = 5
|
@Transient const val BLEND_SCREEN = 5
|
||||||
@Transient const val BLEND_MULTIPLY = 6
|
@Transient const val BLEND_MULTIPLY = 6
|
||||||
|
|||||||
@@ -30,7 +30,13 @@ open class HumanoidNPC(override val scriptPath: String, born: GameDate) : ActorH
|
|||||||
|
|
||||||
private val aiLuaAPI: AILuaAPI
|
private val aiLuaAPI: AILuaAPI
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val DEFAULT_COLLISION_TYPE = ActorWithBody.COLLISION_DYNAMIC
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
collisionType = DEFAULT_COLLISION_TYPE
|
||||||
|
|
||||||
luag["io"] = LuaValue.NIL
|
luag["io"] = LuaValue.NIL
|
||||||
luag["os"] = LuaValue.NIL
|
luag["os"] = LuaValue.NIL
|
||||||
luag["luajava"] = LuaValue.NIL
|
luag["luajava"] = LuaValue.NIL
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ object PlayerBuilderSigrid {
|
|||||||
|
|
||||||
p.actorValue[AVKey.INTELLIGENT] = true
|
p.actorValue[AVKey.INTELLIGENT] = true
|
||||||
|
|
||||||
p.actorValue[AVKey.LUMINOSITY] = Color(0x434aff).to10bit()
|
//p.actorValue[AVKey.LUMINOSITY] = Color(0x434aff).to10bit()
|
||||||
|
|
||||||
p.actorValue[AVKey.BASEDEFENCE] = 141
|
p.actorValue[AVKey.BASEDEFENCE] = 141
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import net.torvald.terrarum.gameactors.AIControlled
|
|||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.mapdrawer.LightmapRenderer
|
import net.torvald.terrarum.mapdrawer.LightmapRenderer
|
||||||
|
import net.torvald.terrarum.tileproperties.Tile
|
||||||
import net.torvald.terrarum.tileproperties.TileCodex
|
import net.torvald.terrarum.tileproperties.TileCodex
|
||||||
import org.luaj.vm2.*
|
import org.luaj.vm2.*
|
||||||
import org.luaj.vm2.lib.OneArgFunction
|
import org.luaj.vm2.lib.OneArgFunction
|
||||||
@@ -39,6 +40,8 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
|
|||||||
g["ai"]["jump"] = Jump(actor)
|
g["ai"]["jump"] = Jump(actor)
|
||||||
|
|
||||||
g["ai"]["getNearbyTiles"] = GetNearbyTiles(actor)
|
g["ai"]["getNearbyTiles"] = GetNearbyTiles(actor)
|
||||||
|
g["ai"]["getFloorsHeight"] = GetFloorsHeight(actor)
|
||||||
|
g["ai"]["getCeilingsHeight"] = GetCeilingsHeight(actor)
|
||||||
|
|
||||||
g["game"] = LuaValue.tableOf()
|
g["game"] = LuaValue.tableOf()
|
||||||
g["game"]["version"] = GameVersion()
|
g["game"]["version"] = GameVersion()
|
||||||
@@ -87,6 +90,8 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
|
|||||||
fun Int?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
|
fun Int?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
|
||||||
fun String?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
|
fun String?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
|
||||||
fun Boolean.toInt() = if (this) 1 else 0
|
fun Boolean.toInt() = if (this) 1 else 0
|
||||||
|
|
||||||
|
operator fun LuaTable.set(index: Int, value: Int) { this[index] = value.toLua() }
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetSelfActorInfo(val actor: ActorWithBody) : ZeroArgFunction() {
|
class GetSelfActorInfo(val actor: ActorWithBody) : ZeroArgFunction() {
|
||||||
@@ -215,19 +220,18 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class GetNearbyTiles(val actor: ActorWithBody) : OneArgFunction() {
|
class GetNearbyTiles(val actor: ActorWithBody) : OneArgFunction() {
|
||||||
|
/** @param radius
|
||||||
/** @param radius: lookahead
|
|
||||||
*
|
*
|
||||||
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
|
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
|
||||||
*
|
*
|
||||||
* Index: [-3: y][-3: x] ... [0: y][0: x] ... [3: y][3: x]
|
* Index: [-3: y][-3: x] ... [0: y][0: x] ... [3: y][3: x] for radius 3
|
||||||
* Return value: bitset (int 0-7)
|
* Return value: bitset (int 0-7)
|
||||||
* 1 -- solidity
|
* 1 -- solidity
|
||||||
* 2 -- liquidity
|
* 2 -- liquidity
|
||||||
* 3 -- gravity
|
* 3 -- gravity
|
||||||
*/
|
*/
|
||||||
override fun call(radius: LuaValue): LuaValue {
|
override fun call(arg: LuaValue): LuaValue {
|
||||||
val radius = radius.checkint()
|
val radius = arg.checkint()
|
||||||
|
|
||||||
if (radius < 0) {
|
if (radius < 0) {
|
||||||
return LuaValue.NONE
|
return LuaValue.NONE
|
||||||
@@ -248,8 +252,94 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
|
|||||||
val gravity = tile.isFallable.toInt()
|
val gravity = tile.isFallable.toInt()
|
||||||
val tileFlag: Int = gravity.shl(2) + liquidity.shl(1) + solidity
|
val tileFlag: Int = gravity.shl(2) + liquidity.shl(1) + solidity
|
||||||
|
|
||||||
luatable[y - feetTilePos[1]][x - feetTilePos[0]] =
|
luatable[y - feetTilePos[1]][x - feetTilePos[0]] = tileFlag.toLua()
|
||||||
LuaInteger.valueOf(tileFlag)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return luatable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetFloorsHeight(val actor: ActorWithBody) : OneArgFunction() {
|
||||||
|
/** @param radius
|
||||||
|
*
|
||||||
|
* 3 will return len:7 array, 0 will return len:1, 1 will return len:3
|
||||||
|
*
|
||||||
|
* Index: [-3] .. [0] .. [3] for radius
|
||||||
|
* Return value: floor height
|
||||||
|
* 0: body tile (legs area)
|
||||||
|
* 1: tile you can stand on
|
||||||
|
* 2+: tiles down there
|
||||||
|
*/
|
||||||
|
override fun call(arg: LuaValue): LuaValue {
|
||||||
|
val radius = arg.checkint()
|
||||||
|
|
||||||
|
val searchDownLimit = 12
|
||||||
|
|
||||||
|
if (radius < 0) {
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
else if (radius > 8) {
|
||||||
|
throw IllegalArgumentException("Radius too large -- must be 8 or less")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val luatable = LuaTable()
|
||||||
|
val feetTilePos = actor.feetPosTile
|
||||||
|
for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) {
|
||||||
|
// search down
|
||||||
|
var searchDownCounter = 0
|
||||||
|
while (true) {
|
||||||
|
val tile = Terrarum.ingame.world.getTileFromTerrain(x, feetTilePos[1] + searchDownCounter) ?: Tile.STONE
|
||||||
|
if (TileCodex[tile].isSolid || searchDownCounter >= searchDownLimit) {
|
||||||
|
luatable[x - feetTilePos[0]] = searchDownCounter
|
||||||
|
break
|
||||||
|
}
|
||||||
|
searchDownCounter++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return luatable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetCeilingsHeight(val actor: ActorWithBody) : OneArgFunction() {
|
||||||
|
/** @param radius
|
||||||
|
*
|
||||||
|
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
|
||||||
|
*
|
||||||
|
* Index: [-3] .. [0] .. [3] for radius
|
||||||
|
* Return value: floor height
|
||||||
|
* (-1): tile you can stand on
|
||||||
|
* 0: body tile (legs area)
|
||||||
|
* 1: body tile (may be vary depend on the size of the actor)
|
||||||
|
* 2+: tiles up there
|
||||||
|
*/
|
||||||
|
override fun call(arg: LuaValue): LuaValue {
|
||||||
|
val radius = arg.checkint()
|
||||||
|
|
||||||
|
val searchUpLimit = 12
|
||||||
|
|
||||||
|
if (radius < 0) {
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
else if (radius > 8) {
|
||||||
|
throw IllegalArgumentException("Radius too large -- must be 8 or less")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val luatable = LuaTable()
|
||||||
|
val feetTilePos = actor.feetPosTile
|
||||||
|
for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) {
|
||||||
|
// search up
|
||||||
|
var searchUpCounter = 0
|
||||||
|
while (true) {
|
||||||
|
val tile = Terrarum.ingame.world.getTileFromTerrain(x, feetTilePos[1] - searchUpCounter) ?: Tile.STONE
|
||||||
|
if (TileCodex[tile].isSolid || searchUpCounter >= searchUpLimit) {
|
||||||
|
luatable[x - feetTilePos[0]] = searchUpCounter
|
||||||
|
break
|
||||||
|
}
|
||||||
|
searchUpCounter++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,22 +49,26 @@ object CollisionSolver {
|
|||||||
collListX.sortBy { it.pos }
|
collListX.sortBy { it.pos }
|
||||||
|
|
||||||
// set candidateX
|
// set candidateX
|
||||||
for (it in collListX) {
|
collListX.forEach {
|
||||||
if (it.kind == STARTPOINT) {
|
if (it.kind == STARTPOINT) {
|
||||||
collCandidateStack.push(it)
|
collCandidateStack.push(it)
|
||||||
}
|
}
|
||||||
else if (it.kind == ENDPOINT) {
|
else if (it.kind == ENDPOINT) {
|
||||||
val mark_this = it
|
val mark_this = it
|
||||||
val mark_other = collCandidateStack.pop()
|
val mark_other = collCandidateStack.pop()
|
||||||
val collCandidate: Pair<ActorWithBody, ActorWithBody>
|
// make sure actor with lower ID comes first
|
||||||
if (mark_this < mark_other) // make sure actor with lower pos comes left
|
val collCandidate = if (mark_this.actor < mark_other.actor)
|
||||||
collCandidate = Pair(mark_this.actor, mark_other.actor)
|
Pair(mark_this.actor, mark_other.actor)
|
||||||
else
|
else
|
||||||
collCandidate = Pair(mark_other.actor, mark_this.actor)
|
Pair(mark_other.actor, mark_this.actor)
|
||||||
|
|
||||||
collCandidateX.add(collCandidate)
|
// filter out Pair(E, E); Pair(A, B) if Pair(B, A) exists
|
||||||
|
if (mark_this.actor != mark_other.actor) {
|
||||||
|
collCandidateX.add(collCandidate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collCandidateStack.clear()
|
collCandidateStack.clear()
|
||||||
|
|
||||||
// mark list y
|
// mark list y
|
||||||
@@ -78,7 +82,7 @@ object CollisionSolver {
|
|||||||
collListY.sortBy { it.pos }
|
collListY.sortBy { it.pos }
|
||||||
|
|
||||||
// set candidateY
|
// set candidateY
|
||||||
for (it in collListY) {
|
collListY.forEach {
|
||||||
if (it.kind == STARTPOINT) {
|
if (it.kind == STARTPOINT) {
|
||||||
collCandidateStack.push(it)
|
collCandidateStack.push(it)
|
||||||
}
|
}
|
||||||
@@ -86,12 +90,16 @@ object CollisionSolver {
|
|||||||
val mark_this = it
|
val mark_this = it
|
||||||
val mark_other = collCandidateStack.pop()
|
val mark_other = collCandidateStack.pop()
|
||||||
val collCandidate: Pair<ActorWithBody, ActorWithBody>
|
val collCandidate: Pair<ActorWithBody, ActorWithBody>
|
||||||
if (mark_this < mark_other) // make sure actor with lower pos comes left
|
// make sure actor with lower ID comes first
|
||||||
|
if (mark_this.actor < mark_other.actor)
|
||||||
collCandidate = Pair(mark_this.actor, mark_other.actor)
|
collCandidate = Pair(mark_this.actor, mark_other.actor)
|
||||||
else
|
else
|
||||||
collCandidate = Pair(mark_other.actor, mark_this.actor)
|
collCandidate = Pair(mark_other.actor, mark_this.actor)
|
||||||
|
|
||||||
collCandidateY.add(collCandidate)
|
// filter out Pair(E, E); Pair(A, B) if Pair(B, A) exists
|
||||||
|
if (mark_this.actor != mark_other.actor) {
|
||||||
|
collCandidateY.add(collCandidate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// look for overlaps in candidate X/Y and put them into collCandidates
|
// look for overlaps in candidate X/Y and put them into collCandidates
|
||||||
@@ -99,10 +107,36 @@ object CollisionSolver {
|
|||||||
collCandidateY.retainAll(collCandidateX) // list Y will have intersection of X and Y now
|
collCandidateY.retainAll(collCandidateX) // list Y will have intersection of X and Y now
|
||||||
collCandidates = collCandidateY // renaming. X and Y won't be used anyway.
|
collCandidates = collCandidateY // renaming. X and Y won't be used anyway.
|
||||||
|
|
||||||
|
//collCandidates.forEach { println(it) }
|
||||||
|
//println("-----------------------")
|
||||||
|
|
||||||
// solve collision for actors in collCandidates
|
// solve collision for actors in collCandidates
|
||||||
collCandidates.forEach { solveCollision(it.first, it.second) }
|
collCandidates.forEach { solveCollision(it.first, it.second) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun pairEqv(a: Pair<Any?, Any?>, b: Pair<Any?, Any?>) =
|
||||||
|
(a.first == b.first && a.second == b.second) ||
|
||||||
|
(a.first == b.second && a.second == b.first)
|
||||||
|
|
||||||
|
/** Mimics java's original behaviour, with user-defined equals function */
|
||||||
|
fun ArrayList<Any?>.containsByFunc(other: Any?, equalsFun: (a: Any?, b: Any?) -> Boolean): Boolean {
|
||||||
|
fun indexOfEqFn(arrayList: ArrayList<Any?>, o: Any?): Int {
|
||||||
|
if (o == null) {
|
||||||
|
for (i in 0..size - 1)
|
||||||
|
if (arrayList[i] == null)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i in 0..size - 1)
|
||||||
|
if (equalsFun(o, arrayList[i]))
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return indexOfEqFn(this, other) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
private fun solveCollision(a: ActorWithBody, b: ActorWithBody) {
|
private fun solveCollision(a: ActorWithBody, b: ActorWithBody) {
|
||||||
// some of the Pair(a, b) are either duplicates or erroneously reported.
|
// some of the Pair(a, b) are either duplicates or erroneously reported.
|
||||||
// e.g. (A, B), (B, C) and then (A, C);
|
// e.g. (A, B), (B, C) and then (A, C);
|
||||||
@@ -110,12 +144,12 @@ object CollisionSolver {
|
|||||||
// we are going to filter them
|
// we are going to filter them
|
||||||
if (a isCollidingWith b) {
|
if (a isCollidingWith b) {
|
||||||
// notify collision, but not solve it yet
|
// notify collision, but not solve it yet
|
||||||
// (e.g. player vs mob, will pass by but still takes damage)
|
|
||||||
|
|
||||||
|
//println("Collision: $a <-> $b")
|
||||||
|
// FIXME does work but has duplication
|
||||||
|
|
||||||
// if they actually makes collision (e.g. player vs ball), solve it
|
// if they actually makes collision (e.g. player vs ball), solve it
|
||||||
if (a makesCollisionWith b) {
|
if (a makesCollisionWith b) {
|
||||||
// assuming perfect elastic collision; ignoring 'var elasticity'
|
|
||||||
val ux_1 = a.veloX
|
val ux_1 = a.veloX
|
||||||
val ux_2 = b.veloX
|
val ux_2 = b.veloX
|
||||||
val uy_1 = a.veloY
|
val uy_1 = a.veloY
|
||||||
@@ -136,10 +170,10 @@ object CollisionSolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private infix fun ActorWithBody.makesCollisionWith(other: ActorWithBody): Boolean {
|
private infix fun ActorWithBody.makesCollisionWith(other: ActorWithBody) =
|
||||||
return true
|
this.collisionType != ActorWithBody.COLLISION_NOCOLLIDE &&
|
||||||
}
|
other.collisionType != ActorWithBody.COLLISION_NOCOLLIDE
|
||||||
|
|
||||||
private infix fun ActorWithBody.isCollidingWith(other: ActorWithBody): Boolean {
|
private infix fun ActorWithBody.isCollidingWith(other: ActorWithBody): Boolean {
|
||||||
val ax = this.hitbox.centeredX
|
val ax = this.hitbox.centeredX
|
||||||
val ay = this.hitbox.centeredY
|
val ay = this.hitbox.centeredY
|
||||||
@@ -168,16 +202,11 @@ object CollisionSolver {
|
|||||||
fun Double.abs() = if (this < 0) -this else this
|
fun Double.abs() = if (this < 0) -this else this
|
||||||
fun Double.sqr() = this * this
|
fun Double.sqr() = this * this
|
||||||
|
|
||||||
class CollisionMarkings(
|
data class CollisionMarkings(
|
||||||
val pos: Double,
|
val pos: Double,
|
||||||
val kind: Int,
|
val kind: Int,
|
||||||
val actor: ActorWithBody
|
val actor: ActorWithBody
|
||||||
) : Comparable<CollisionMarkings> {
|
)
|
||||||
override fun compareTo(other: CollisionMarkings): Int =
|
|
||||||
if (this.pos > other.pos) 1
|
|
||||||
else if (this.pos < other.pos) -1
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* === Some useful physics knowledge ===
|
* === Some useful physics knowledge ===
|
||||||
|
|||||||
@@ -700,45 +700,21 @@ object WorldGenerator {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadParallel.startAll()
|
ThreadParallel.startAllWaitForDie()
|
||||||
// FIXME game starts prematurely
|
|
||||||
/* Console:
|
|
||||||
[mapgenerator] Seed: 85336530
|
|
||||||
[mapgenerator] Raising and eroding terrain...
|
|
||||||
[mapgenerator] Shaping world...
|
|
||||||
[mapgenerator] Carving caves...
|
|
||||||
[mapgenerator] Carving caves...
|
|
||||||
[mapgenerator] Carving caves...
|
|
||||||
[mapgenerator] Flooding bottom lava...
|
|
||||||
[mapgenerator] Carving caves...
|
|
||||||
[mapgenerator] Planting grass...
|
|
||||||
[mapgenerator] Placing floating islands...
|
|
||||||
[UIHandler] Creating UI 'ConsoleWindow'
|
|
||||||
Mon Jun 13 00:43:57 KST 2016 INFO:Offscreen Buffers FBO=true PBUFFER=true PBUFFERRT=false
|
|
||||||
Mon Jun 13 00:43:57 KST 2016 DEBUG:Creating FBO 2048x256
|
|
||||||
[UIHandler] Creating UI 'BasicDebugInfoWindow'
|
|
||||||
Mon Jun 13 00:43:57 KST 2016 INFO:Offscreen Buffers FBO=true PBUFFER=true PBUFFERRT=false
|
|
||||||
Mon Jun 13 00:43:57 KST 2016 DEBUG:Creating FBO 2048x1024
|
|
||||||
[UIHandler] Creating UI 'Notification'
|
|
||||||
Mon Jun 13 00:43:57 KST 2016 INFO:Offscreen Buffers FBO=true PBUFFER=true PBUFFERRT=false
|
|
||||||
Mon Jun 13 00:43:57 KST 2016 DEBUG:Creating FBO 512x64
|
|
||||||
[mapgenerator] Collapsing caves...
|
|
||||||
[mapgenerator] Collapsing caves...
|
|
||||||
[mapgenerator] Collapsing caves...
|
|
||||||
[mapgenerator] Collapsing caves...
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ThreadProcessNoiseLayers(0, HEIGHT - 1, noiseRecords).run()
|
ThreadProcessNoiseLayers(0, HEIGHT - 1, noiseRecords).run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val islandSpacing = 1024
|
||||||
|
|
||||||
private fun generateFloatingIslands() {
|
private fun generateFloatingIslands() {
|
||||||
println("[mapgenerator] Placing floating islands...")
|
println("[mapgenerator] Placing floating islands...")
|
||||||
|
|
||||||
val nIslandsMax = Math.round(world.width * 6f / 8192f)
|
val nIslandsMax = Math.round(world.width * 6f / 8192f)
|
||||||
val nIslandsMin = Math.max(2, Math.round(world.width * 4f / 8192f))
|
val nIslandsMin = Math.max(2, Math.round(world.width * 4f / 8192f))
|
||||||
val nIslands = random.nextInt(nIslandsMax - nIslandsMin) + nIslandsMin
|
val nIslands = random.nextInt(Math.max(1, nIslandsMax - nIslandsMin)) + nIslandsMin
|
||||||
val prevIndex = -1
|
val prevIndex = -1
|
||||||
|
|
||||||
val tiles = intArrayOf(Tile.AIR, Tile.STONE, Tile.DIRT, Tile.GRASS)
|
val tiles = intArrayOf(Tile.AIR, Tile.STONE, Tile.DIRT, Tile.GRASS)
|
||||||
@@ -750,7 +726,7 @@ object WorldGenerator {
|
|||||||
}
|
}
|
||||||
val island = FloatingIslandsPreset.generatePreset(currentIndex, random)
|
val island = FloatingIslandsPreset.generatePreset(currentIndex, random)
|
||||||
|
|
||||||
val startingPosX = random.nextInt(world.width - 2048) + 1024
|
val startingPosX = random.nextInt(islandSpacing) + islandSpacing * i
|
||||||
val startingPosY = minimumFloatingIsleHeight + random.nextInt(minimumFloatingIsleHeight)
|
val startingPosY = minimumFloatingIsleHeight + random.nextInt(minimumFloatingIsleHeight)
|
||||||
|
|
||||||
for (j in island.indices) {
|
for (j in island.indices) {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import net.torvald.colourutil.CIEXYZUtil
|
|||||||
import net.torvald.colourutil.ColourUtil
|
import net.torvald.colourutil.ColourUtil
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.blendMul
|
||||||
|
import net.torvald.terrarum.blendNormal
|
||||||
import net.torvald.terrarum.gameworld.WorldTime
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.getPixel
|
import net.torvald.terrarum.getPixel
|
||||||
import org.newdawn.slick.Color
|
import org.newdawn.slick.Color
|
||||||
@@ -85,26 +87,30 @@ object WeatherMixer {
|
|||||||
val skyboxColourMap = currentWeather.skyboxGradColourMap
|
val skyboxColourMap = currentWeather.skyboxGradColourMap
|
||||||
val lightColourMap = currentWeather.globalLightColourMap
|
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(),// / Terrarum.ingame.screenZoom,
|
|
||||||
getGradientColour(skyboxColourMap, 1, timeNow)
|
|
||||||
)
|
|
||||||
g.fill(Rectangle(
|
|
||||||
0f, 0f,
|
|
||||||
Terrarum.WIDTH.toFloat(),// / Terrarum.ingame.screenZoom,
|
|
||||||
Terrarum.HEIGHT.toFloat()// / Terrarum.ingame.screenZoom
|
|
||||||
),skyColourFill)
|
|
||||||
|
|
||||||
// calculate global light
|
// calculate global light
|
||||||
val gradCol = getGradientColour(lightColourMap, 0, timeNow)
|
val gradCol = getGradientColour(lightColourMap, 0, timeNow)
|
||||||
globalLightNow.r = gradCol.r
|
globalLightNow.r = gradCol.r
|
||||||
globalLightNow.g = gradCol.g
|
globalLightNow.g = gradCol.g
|
||||||
globalLightNow.b = gradCol.b
|
globalLightNow.b = gradCol.b
|
||||||
|
|
||||||
|
// draw skybox to provided (should be main) graphics instance
|
||||||
|
val skyColourFill = GradientFill(
|
||||||
|
0f, 0f,
|
||||||
|
getGradientColour(skyboxColourMap, 0, timeNow) * gradCol, // mul with globallight
|
||||||
|
0f, Terrarum.HEIGHT.toFloat(),// / Terrarum.ingame.screenZoom,
|
||||||
|
getGradientColour(skyboxColourMap, 1, timeNow) * gradCol // mul with globallight
|
||||||
|
)
|
||||||
|
|
||||||
|
blendNormal()
|
||||||
|
g.fill(Rectangle(
|
||||||
|
0f, 0f,
|
||||||
|
Terrarum.WIDTH.toFloat(),// / Terrarum.ingame.screenZoom,
|
||||||
|
Terrarum.HEIGHT.toFloat()// / Terrarum.ingame.screenZoom
|
||||||
|
), skyColourFill)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator fun Color.times(other: Color) = Color(this.r * other.r, this.g * other.g, this.b * other.b, 1f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a GL of specific time
|
* Get a GL of specific time
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user