mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
throwing in a pr-tree onto the project
This commit is contained in:
1
.idea/libraries/lib.xml
generated
1
.idea/libraries/lib.xml
generated
@@ -19,6 +19,7 @@
|
|||||||
<root url="jar://$PROJECT_DIR$/lib/Terrarum_Joise.jar!/" />
|
<root url="jar://$PROJECT_DIR$/lib/Terrarum_Joise.jar!/" />
|
||||||
<root url="jar://$PROJECT_DIR$/lib/source/gdx-backend-lwjgl-sources.jar!/" />
|
<root url="jar://$PROJECT_DIR$/lib/source/gdx-backend-lwjgl-sources.jar!/" />
|
||||||
<root url="jar://$PROJECT_DIR$/lib/TerrarumSansBitmap.jar!/" />
|
<root url="jar://$PROJECT_DIR$/lib/TerrarumSansBitmap.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/prtree.jar!/" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" />
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/source" recursive="false" type="SOURCES" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/source" recursive="false" type="SOURCES" />
|
||||||
|
|||||||
39
COPYING.md
39
COPYING.md
@@ -66,7 +66,7 @@ limitations under the License.
|
|||||||
*Accidental Noise Library*
|
*Accidental Noise Library*
|
||||||
|
|
||||||
Joise is a derivative work based on Josua Tippetts' C++ library:
|
Joise is a derivative work based on Josua Tippetts' C++ library:
|
||||||
http://accidentalnoise.sourceforge.net/index.html
|
<http://accidentalnoise.sourceforge.net/index.html>
|
||||||
|
|
||||||
Copyright (C) 2011 Joshua Tippetts
|
Copyright (C) 2011 Joshua Tippetts
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ Copyright (C) 2011 Joshua Tippetts
|
|||||||
|
|
||||||
*Vector2.java*, *Epsilon.java*
|
*Vector2.java*, *Epsilon.java*
|
||||||
|
|
||||||
Copyright (c) 2010-2015 William Bittle http://www.dyn4j.org/
|
Copyright (c) 2010-2015 William Bittle <http://www.dyn4j.org/>
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
@@ -127,7 +127,7 @@ Ambient sound recordings:
|
|||||||
crickets_02.ogg
|
crickets_02.ogg
|
||||||
|
|
||||||
Copyright (C) 2012, 2013, 2015, 2016, 2017 Klankbeeld
|
Copyright (C) 2012, 2013, 2015, 2016, 2017 Klankbeeld
|
||||||
Sound from http://www.freesound.org/people/klankbeeld/
|
Sound from <http://www.freesound.org/people/klankbeeld/>
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -155,6 +155,39 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
PRTree, a Priority R-Tree, a spatial index for java code
|
||||||
|
|
||||||
|
Copyright (c) 2008-2012 Robert Olofsson.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the authors nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
Some of the resources were created by _raxod502_.
|
Some of the resources were created by _raxod502_.
|
||||||
|
|
||||||
|
|||||||
BIN
lib/prtree.jar
Normal file
BIN
lib/prtree.jar
Normal file
Binary file not shown.
@@ -56,7 +56,7 @@ object Terrarum : Disposable {
|
|||||||
/**
|
/**
|
||||||
* To be used with physics simulator. This is a magic number.
|
* To be used with physics simulator. This is a magic number.
|
||||||
*/
|
*/
|
||||||
val PHYS_TIME_FRAME: Double = 26.0 + (2.0 / 3.0)
|
const val PHYS_TIME_FRAME: Double = 26.0 + (2.0 / 3.0)
|
||||||
// 26.0 + (2.0 / 3.0) // lower value == faster gravity response (IT WON'T HOTSWAP!!)
|
// 26.0 + (2.0 / 3.0) // lower value == faster gravity response (IT WON'T HOTSWAP!!)
|
||||||
// protip: using METER, game unit and SI unit will have same number
|
// protip: using METER, game unit and SI unit will have same number
|
||||||
|
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
*/ // got the idea from gl_FragCoord
|
*/ // got the idea from gl_FragCoord
|
||||||
val hIntTilewiseHitbox: Hitbox
|
val hIntTilewiseHitbox: Hitbox
|
||||||
get() = Hitbox.fromTwoPoints(
|
get() = Hitbox.fromTwoPoints(
|
||||||
hitbox.startX.plus(0.00001).div(TILE_SIZE).floor() + 0.5,
|
hitbox.startX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
||||||
hitbox.startY.plus(0.00001).div(TILE_SIZE).floor() + 0.5,
|
hitbox.startY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
||||||
hitbox.endX.plus(0.00001).div(TILE_SIZE).floor() + 0.5,
|
hitbox.endX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
||||||
hitbox.endY.plus(0.00001).div(TILE_SIZE).floor() + 0.5,
|
hitbox.endY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -89,8 +89,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
get() = Hitbox.fromTwoPoints(
|
get() = Hitbox.fromTwoPoints(
|
||||||
hitbox.startX.div(TILE_SIZE).floor(),
|
hitbox.startX.div(TILE_SIZE).floor(),
|
||||||
hitbox.startY.div(TILE_SIZE).floor(),
|
hitbox.startY.div(TILE_SIZE).floor(),
|
||||||
hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(),
|
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
||||||
hitbox.endY.minus(0.00001).div(TILE_SIZE).floor(),
|
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -641,8 +641,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
||||||
hitbox.startX.div(TILE_SIZE).floor(),
|
hitbox.startX.div(TILE_SIZE).floor(),
|
||||||
hitbox.startY.div(TILE_SIZE).floor(),
|
hitbox.startY.div(TILE_SIZE).floor(),
|
||||||
hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(),
|
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
||||||
hitbox.endY.minus(0.00001).div(TILE_SIZE).floor(),
|
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -690,7 +690,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
// trying to use same function as the others, in an effort to eliminate the "contradiction" mentioned below
|
// trying to use same function as the others, in an effort to eliminate the "contradiction" mentioned below
|
||||||
if (isColliding(stepBox)) {
|
if (isColliding(stepBox, vectorSum.y > PHYS_EPSILON_VELO)) {
|
||||||
collidingStep = step
|
collidingStep = step
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,13 +773,13 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
|
|
||||||
// points to the EDGE of the tile in world dimension (don't use this directly to get tilewise coord!!)
|
// points to the EDGE of the tile in world dimension (don't use this directly to get tilewise coord!!)
|
||||||
val offendingTileWorldX = if (selfCollisionStatus in listOf(6, 12))
|
val offendingTileWorldX = if (selfCollisionStatus in listOf(6, 12))
|
||||||
newHitbox.endX.div(TILE_SIZE).floor() * TILE_SIZE - 0.00001
|
newHitbox.endX.div(TILE_SIZE).floor() * TILE_SIZE - PHYS_EPSILON_DIST
|
||||||
else
|
else
|
||||||
newHitbox.startX.div(TILE_SIZE).ceil() * TILE_SIZE
|
newHitbox.startX.div(TILE_SIZE).ceil() * TILE_SIZE
|
||||||
|
|
||||||
// points to the EDGE of the tile in world dimension (don't use this directly to get tilewise coord!!)
|
// points to the EDGE of the tile in world dimension (don't use this directly to get tilewise coord!!)
|
||||||
val offendingTileWorldY = if (selfCollisionStatus in listOf(3, 6))
|
val offendingTileWorldY = if (selfCollisionStatus in listOf(3, 6))
|
||||||
newHitbox.endY.div(TILE_SIZE).floor() * TILE_SIZE - 0.00001
|
newHitbox.endY.div(TILE_SIZE).floor() * TILE_SIZE - PHYS_EPSILON_DIST
|
||||||
else
|
else
|
||||||
newHitbox.startY.div(TILE_SIZE).ceil() * TILE_SIZE
|
newHitbox.startY.div(TILE_SIZE).ceil() * TILE_SIZE
|
||||||
|
|
||||||
@@ -962,7 +962,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
/**
|
/**
|
||||||
* @see /work_files/hitbox_collision_detection_compensation.jpg
|
* @see /work_files/hitbox_collision_detection_compensation.jpg
|
||||||
*/
|
*/
|
||||||
private fun isColliding(hitbox: Hitbox): Boolean {
|
private fun isColliding(hitbox: Hitbox, feet: Boolean = false): Boolean {
|
||||||
if (isNoCollideWorld) return false
|
if (isNoCollideWorld) return false
|
||||||
|
|
||||||
// detectors are inside of the bounding box
|
// detectors are inside of the bounding box
|
||||||
@@ -978,7 +978,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
val tyStart = y1.plus(0.5f).div(TILE_SIZE).floorInt()
|
val tyStart = y1.plus(0.5f).div(TILE_SIZE).floorInt()
|
||||||
val tyEnd = y2.plus(0.5f).div(TILE_SIZE).floorInt()
|
val tyEnd = y2.plus(0.5f).div(TILE_SIZE).floorInt()
|
||||||
|
|
||||||
return isCollidingInternal(txStart, tyStart, txEnd, tyEnd)
|
return isCollidingInternal(txStart, tyStart, txEnd, tyEnd, feet)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1604,8 +1604,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
||||||
hitbox.startX.div(TILE_SIZE).floor(),
|
hitbox.startX.div(TILE_SIZE).floor(),
|
||||||
hitbox.startY.div(TILE_SIZE).floor(),
|
hitbox.startY.div(TILE_SIZE).floor(),
|
||||||
hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(),
|
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
||||||
hitbox.endY.minus(0.00001).div(TILE_SIZE).floor(),
|
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
||||||
true
|
true
|
||||||
) // NOT the same as intTilewiseHitbox !!
|
) // NOT the same as intTilewiseHitbox !!
|
||||||
|
|
||||||
@@ -1659,20 +1659,23 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
|||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Transient val METER = 24.0
|
@Transient const val METER = 24.0
|
||||||
/**
|
/**
|
||||||
* [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
|
* [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
|
||||||
*/
|
*/
|
||||||
@Transient val SI_TO_GAME_ACC = METER / (Terrarum.PHYS_TIME_FRAME * Terrarum.PHYS_TIME_FRAME)
|
@Transient const val SI_TO_GAME_ACC = METER / (Terrarum.PHYS_TIME_FRAME * Terrarum.PHYS_TIME_FRAME)
|
||||||
/**
|
/**
|
||||||
* [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame]
|
* [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame]
|
||||||
*/
|
*/
|
||||||
@Transient val SI_TO_GAME_VEL = METER / Terrarum.PHYS_TIME_FRAME
|
@Transient const val SI_TO_GAME_VEL = METER / Terrarum.PHYS_TIME_FRAME
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [px / InternalFrame^2] * GAME_TO_SI_ACC -> [m / s^2]
|
* [px / InternalFrame^2] * GAME_TO_SI_ACC -> [m / s^2]
|
||||||
*/
|
*/
|
||||||
@Transient val GAME_TO_SI_ACC = (Terrarum.PHYS_TIME_FRAME * Terrarum.PHYS_TIME_FRAME) / METER
|
@Transient const val GAME_TO_SI_ACC = (Terrarum.PHYS_TIME_FRAME * Terrarum.PHYS_TIME_FRAME) / METER
|
||||||
|
|
||||||
|
@Transient const val PHYS_EPSILON_DIST = 0.00001
|
||||||
|
@Transient const val PHYS_EPSILON_VELO = 0.0001
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -484,9 +484,6 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
particlesActive = 0
|
particlesActive = 0
|
||||||
|
|
||||||
|
|
||||||
ingameController.update(delta)
|
|
||||||
|
|
||||||
|
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
|
|
||||||
WorldSimulator.resetForThisFrame()
|
WorldSimulator.resetForThisFrame()
|
||||||
@@ -496,9 +493,15 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
///////////////////////////
|
///////////////////////////
|
||||||
BlockPropUtil.dynamicLumFuncTickClock()
|
BlockPropUtil.dynamicLumFuncTickClock()
|
||||||
world.updateWorldTime(delta)
|
world.updateWorldTime(delta)
|
||||||
|
AppLoader.measureDebugTime("WorldSimulator.update") {
|
||||||
WorldSimulator.invoke(actorNowPlaying, delta)
|
WorldSimulator.invoke(actorNowPlaying, delta)
|
||||||
|
}
|
||||||
|
AppLoader.measureDebugTime("WeatherMixer.update") {
|
||||||
WeatherMixer.update(delta, actorNowPlaying, world)
|
WeatherMixer.update(delta, actorNowPlaying, world)
|
||||||
|
}
|
||||||
|
AppLoader.measureDebugTime("BlockStats.update") {
|
||||||
BlockStats.update()
|
BlockStats.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -524,6 +527,12 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
WorldCamera.update(gameworld, actorNowPlaying)
|
WorldCamera.update(gameworld, actorNowPlaying)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// world click events (e.g. opening the UI that a fixture has) must go here
|
||||||
|
ingameController.update(delta)
|
||||||
|
|
||||||
|
if (!paused) {
|
||||||
|
|
||||||
// completely consume block change queues because why not
|
// completely consume block change queues because why not
|
||||||
terrainChangeQueue.clear()
|
terrainChangeQueue.clear()
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
|||||||
object PlayerBuilderTestSubject1 {
|
object PlayerBuilderTestSubject1 {
|
||||||
operator fun invoke(): IngamePlayer {
|
operator fun invoke(): IngamePlayer {
|
||||||
val p: IngamePlayer = IngamePlayer(
|
val p: IngamePlayer = IngamePlayer(
|
||||||
ModMgr.getPath("basegame", "sprites/furry_sprite.properties"),
|
ModMgr.getPath("basegame", "sprites/test_sprite.properties"),
|
||||||
ModMgr.getPath("basegame", "sprites/furry_sprite_glow.properties"),
|
null,//ModMgr.getPath("basegame", "sprites/test_sprite_glow.properties"),
|
||||||
-589141658L // random value thrown
|
-589141658L // random value thrown
|
||||||
)
|
)
|
||||||
InjectCreatureRaw(p.actorValue, "basegame", "CreatureHuman.json")
|
InjectCreatureRaw(p.actorValue, "basegame", "CreatureHuman.json")
|
||||||
@@ -29,7 +29,7 @@ object PlayerBuilderTestSubject1 {
|
|||||||
p.sprite!!.setRowsAndFrames(2, 4)*/
|
p.sprite!!.setRowsAndFrames(2, 4)*/
|
||||||
|
|
||||||
p.sprite = SpriteAnimation(p)
|
p.sprite = SpriteAnimation(p)
|
||||||
p.spriteGlow = SpriteAnimation(p)
|
//p.spriteGlow = SpriteAnimation(p)
|
||||||
p.reassembleSprite(p.sprite!!, p.spriteGlow)
|
p.reassembleSprite(p.sprite!!, p.spriteGlow)
|
||||||
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT) ?: ActorHumanoid.BASE_HEIGHT, 21, 0)
|
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT) ?: ActorHumanoid.BASE_HEIGHT, 21, 0)
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.gameworld
|
package net.torvald.terrarum.modulebasegame.gameworld
|
||||||
|
|
||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
import com.badlogic.gdx.graphics.Color
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.aa.KDTree
|
|
||||||
import net.torvald.terrarum.AppLoader
|
|
||||||
import net.torvald.terrarum.IngameInstance
|
|
||||||
import net.torvald.terrarum.Terrarum
|
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
import net.torvald.terrarum.blockproperties.Fluid
|
import net.torvald.terrarum.blockproperties.Fluid
|
||||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
import net.torvald.terrarum.gameworld.FluidType
|
import net.torvald.terrarum.gameworld.FluidType
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
import net.torvald.terrarum.roundInt
|
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||||
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.TILE_SIZE
|
||||||
|
import org.khelekore.prtree.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-08-03.
|
* Created by minjaesong on 2016-08-03.
|
||||||
@@ -57,25 +54,25 @@ object WorldSimulator {
|
|||||||
/** Bottom-right point */
|
/** Bottom-right point */
|
||||||
var updateYTo = 0
|
var updateYTo = 0
|
||||||
|
|
||||||
val colourNone = Color(0x808080FF.toInt())
|
|
||||||
val colourWater = Color(0x66BBFFFF.toInt())
|
|
||||||
|
|
||||||
private val ingame: IngameInstance
|
private val ingame: IngameInstance
|
||||||
get() = Terrarum.ingame!!
|
get() = Terrarum.ingame!!
|
||||||
private val world: GameWorld
|
private val world: GameWorld
|
||||||
get() = ingame.world
|
get() = ingame.world
|
||||||
|
|
||||||
// TODO use R-Tree instead? https://stackoverflow.com/questions/10269179/find-rectangles-that-contain-point-efficient-algorithm#10269695
|
|
||||||
private var actorsKDTree: KDTree? = null
|
private lateinit var actorsRTree: PRTree<ActorWithBody>
|
||||||
|
|
||||||
fun resetForThisFrame() {
|
fun resetForThisFrame() {
|
||||||
actorsKDTree = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Must be called BEFORE the actors update -- actors depend on the R-Tree for various things */
|
||||||
operator fun invoke(player: ActorHumanoid?, delta: Float) {
|
operator fun invoke(player: ActorHumanoid?, delta: Float) {
|
||||||
// build the kdtree that will be used during a single frame of updating
|
// build the r-tree that will be used during a single frame of updating
|
||||||
if (actorsKDTree == null)
|
actorsRTree = PRTree(actorMBRConverter, 24)
|
||||||
actorsKDTree = KDTree(ingame.actorContainerActive.filter { it is ActorWBMovable })
|
actorsRTree.load(ingame.actorContainerActive.filter { it is ActorWithBody })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//printdbg(this, "============================")
|
//printdbg(this, "============================")
|
||||||
|
|
||||||
@@ -85,12 +82,49 @@ object WorldSimulator {
|
|||||||
updateXTo = updateXFrom + DOUBLE_RADIUS
|
updateXTo = updateXFrom + DOUBLE_RADIUS
|
||||||
updateYTo = updateYFrom + DOUBLE_RADIUS
|
updateYTo = updateYFrom + DOUBLE_RADIUS
|
||||||
}
|
}
|
||||||
moveFluids(delta)
|
//moveFluids(delta)
|
||||||
displaceFallables(delta)
|
displaceFallables(delta)
|
||||||
|
|
||||||
//printdbg(this, "============================")
|
//printdbg(this, "============================")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list of actors under the bounding box given, list may be empty if no actor is under the point.
|
||||||
|
*/
|
||||||
|
fun getActorsAt(startPoint: Point2d, endPoint: Point2d): List<ActorWithBody> {
|
||||||
|
val outList = ArrayList<ActorWithBody>()
|
||||||
|
actorsRTree.find(startPoint.x, startPoint.y, endPoint.x, endPoint.y, outList)
|
||||||
|
return outList
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getActorsAt(worldX: Double, worldY: Double): List<ActorWithBody> {
|
||||||
|
val outList = ArrayList<ActorWithBody>()
|
||||||
|
actorsRTree.find(worldX, worldY, worldX + 1.0, worldY + 1.0, outList)
|
||||||
|
return outList
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Will use centre point of the actors
|
||||||
|
* @return List of DistanceResult, list may be empty */
|
||||||
|
fun findKNearestActors(from: ActorWithBody, maxHits: Int): List<DistanceResult<ActorWithBody>> {
|
||||||
|
return actorsRTree.nearestNeighbour(actorDistanceCalculator, null, maxHits, object : PointND {
|
||||||
|
override fun getDimensions(): Int = 2
|
||||||
|
override fun getOrd(axis: Int): Double = when(axis) {
|
||||||
|
0 -> from.hitbox.centeredX
|
||||||
|
1 -> from.hitbox.centeredY
|
||||||
|
else -> throw IllegalArgumentException("nonexistent axis $axis for ${dimensions}-dimensional object")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/** Will use centre point of the actors
|
||||||
|
* @return Pair of: the actor, distance from the actor; null if none found */
|
||||||
|
fun findNearestActors(from: ActorWithBody): DistanceResult<ActorWithBody>? {
|
||||||
|
val t = findKNearestActors(from, 1)
|
||||||
|
return if (t.isNotEmpty())
|
||||||
|
t[0]
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* displace fluids. Note that the code assumes the gravity pulls things downward ONLY,
|
* 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
|
* which means you'll need to modify the code A LOT if you're going to implement zero- or
|
||||||
@@ -119,6 +153,90 @@ object WorldSimulator {
|
|||||||
return ((fluid.type sameAs type || fluid.type sameAs Fluid.NULL) && !BlockCodex[tile].isSolid)
|
return ((fluid.type sameAs type || fluid.type sameAs Fluid.NULL) && !BlockCodex[tile].isSolid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* displace fallable tiles. It is scanned bottom-left first. To achieve the sens ofreal
|
||||||
|
* falling, each tiles are displaced by ONLY ONE TILE below.
|
||||||
|
*/
|
||||||
|
fun displaceFallables(delta: Float) {
|
||||||
|
/*for (y in updateYFrom..updateYTo) {
|
||||||
|
for (x in updateXFrom..updateXTo) {
|
||||||
|
val tile = world.getTileFromTerrain(x, y) ?: Block.STONE
|
||||||
|
val tileBelow = world.getTileFromTerrain(x, y + 1) ?: Block.STONE
|
||||||
|
|
||||||
|
if (tile.maxSupport()) {
|
||||||
|
// displace fluid. This statement must precede isSolid()
|
||||||
|
if (tileBelow.isFluid()) {
|
||||||
|
// remove tileThis to create air pocket
|
||||||
|
world.setTileTerrain(x, y, Block.AIR)
|
||||||
|
|
||||||
|
pour(x, y, drain(x, y, tileBelow.fluidLevel().toInt()))
|
||||||
|
// place our tile
|
||||||
|
world.setTileTerrain(x, y + 1, tile)
|
||||||
|
}
|
||||||
|
else if (!tileBelow.isSolid()) {
|
||||||
|
world.setTileTerrain(x, y, Block.AIR)
|
||||||
|
world.setTileTerrain(x, y + 1, tile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// displace fallables (TODO implement blocks with fallable supports e.g. scaffolding)
|
||||||
|
// only displace SINGLE BOTTOMMOST block on single X-coord (this doesn't mean they must fall only one block)
|
||||||
|
// so that the "falling" should be visible to the end user
|
||||||
|
if (!DEBUG_STEPPING_MODE || DEBUG_STEPPING_MODE && KeyToggler.isOn (Input.Keys.PERIOD)) {
|
||||||
|
for (x in updateXFrom..updateXTo) {
|
||||||
|
var fallDownCounter = 0
|
||||||
|
var fallableStackProcessed = false
|
||||||
|
// one "stack" is a contiguous fallable blocks, regardless of the actual block number
|
||||||
|
// when you are simulating the gradual falling, it is natural to process all the "stacks" at the same run,
|
||||||
|
// otherwise you'll get an artefact.
|
||||||
|
for (y in updateYTo downTo updateYFrom) {
|
||||||
|
val currentTile = world.getTileFromTerrain(x, y)
|
||||||
|
val prop = BlockCodex[currentTile]
|
||||||
|
val isSolid = prop.isSolid
|
||||||
|
val support = prop.maxSupport
|
||||||
|
val isFallable = support != -1
|
||||||
|
|
||||||
|
// mark the beginnig of the new "stack"
|
||||||
|
if (fallableStackProcessed && !isFallable) {
|
||||||
|
fallableStackProcessed = false
|
||||||
|
} // do not chain with "else if"
|
||||||
|
|
||||||
|
// process the gradual falling of the selected "stack"
|
||||||
|
if (!fallableStackProcessed && fallDownCounter != 0 && isFallable) {
|
||||||
|
// replace blocks
|
||||||
|
world.setTileTerrain(x, y, Block.AIR)
|
||||||
|
world.setTileTerrain(x, y + fallDownCounter, currentTile)
|
||||||
|
|
||||||
|
fallableStackProcessed = true
|
||||||
|
}
|
||||||
|
else if (isSolid) {
|
||||||
|
fallDownCounter = 0
|
||||||
|
}
|
||||||
|
else if (!isSolid && !isFallable && fallDownCounter < FALLABLE_MAX_FALL_SPEED) {
|
||||||
|
fallDownCounter += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG_STEPPING_MODE) {
|
||||||
|
KeyToggler.forceSet(Input.Keys.PERIOD, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun disperseHeat(delta: Float) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Explanation of get_stable_state_b (well, kind-of) :
|
Explanation of get_stable_state_b (well, kind-of) :
|
||||||
|
|
||||||
@@ -259,86 +377,6 @@ object WorldSimulator {
|
|||||||
|
|
||||||
private val FALLABLE_MAX_FALL_SPEED = 2
|
private val FALLABLE_MAX_FALL_SPEED = 2
|
||||||
|
|
||||||
/**
|
|
||||||
* displace fallable tiles. It is scanned bottom-left first. To achieve the sens ofreal
|
|
||||||
* falling, each tiles are displaced by ONLY ONE TILE below.
|
|
||||||
*/
|
|
||||||
fun displaceFallables(delta: Float) {
|
|
||||||
/*for (y in updateYFrom..updateYTo) {
|
|
||||||
for (x in updateXFrom..updateXTo) {
|
|
||||||
val tile = world.getTileFromTerrain(x, y) ?: Block.STONE
|
|
||||||
val tileBelow = world.getTileFromTerrain(x, y + 1) ?: Block.STONE
|
|
||||||
|
|
||||||
if (tile.maxSupport()) {
|
|
||||||
// displace fluid. This statement must precede isSolid()
|
|
||||||
if (tileBelow.isFluid()) {
|
|
||||||
// remove tileThis to create air pocket
|
|
||||||
world.setTileTerrain(x, y, Block.AIR)
|
|
||||||
|
|
||||||
pour(x, y, drain(x, y, tileBelow.fluidLevel().toInt()))
|
|
||||||
// place our tile
|
|
||||||
world.setTileTerrain(x, y + 1, tile)
|
|
||||||
}
|
|
||||||
else if (!tileBelow.isSolid()) {
|
|
||||||
world.setTileTerrain(x, y, Block.AIR)
|
|
||||||
world.setTileTerrain(x, y + 1, tile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// displace fallables (TODO implement blocks with fallable supports e.g. scaffolding)
|
|
||||||
// only displace SINGLE BOTTOMMOST block on single X-coord (this doesn't mean they must fall only one block)
|
|
||||||
// so that the "falling" should be visible to the end user
|
|
||||||
if (!DEBUG_STEPPING_MODE || DEBUG_STEPPING_MODE && KeyToggler.isOn (Input.Keys.PERIOD)) {
|
|
||||||
for (x in updateXFrom..updateXTo) {
|
|
||||||
var fallDownCounter = 0
|
|
||||||
var fallableStackProcessed = false
|
|
||||||
// one "stack" is a contiguous fallable blocks, regardless of the actual block number
|
|
||||||
// when you are simulating the gradual falling, it is natural to process all the "stacks" at the same run,
|
|
||||||
// otherwise you'll get an artefact.
|
|
||||||
for (y in updateYTo downTo updateYFrom) {
|
|
||||||
val currentTile = world.getTileFromTerrain(x, y)
|
|
||||||
val prop = BlockCodex[currentTile]
|
|
||||||
val isSolid = prop.isSolid
|
|
||||||
val support = prop.maxSupport
|
|
||||||
val isFallable = support != -1
|
|
||||||
|
|
||||||
// mark the beginnig of the new "stack"
|
|
||||||
if (fallableStackProcessed && !isFallable) {
|
|
||||||
fallableStackProcessed = false
|
|
||||||
} // do not chain with "else if"
|
|
||||||
|
|
||||||
// process the gradual falling of the selected "stack"
|
|
||||||
if (!fallableStackProcessed && fallDownCounter != 0 && isFallable) {
|
|
||||||
// replace blocks
|
|
||||||
world.setTileTerrain(x, y, Block.AIR)
|
|
||||||
world.setTileTerrain(x, y + fallDownCounter, currentTile)
|
|
||||||
|
|
||||||
fallableStackProcessed = true
|
|
||||||
}
|
|
||||||
else if (isSolid) {
|
|
||||||
fallDownCounter = 0
|
|
||||||
}
|
|
||||||
else if (!isSolid && !isFallable && fallDownCounter < FALLABLE_MAX_FALL_SPEED) {
|
|
||||||
fallDownCounter += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG_STEPPING_MODE) {
|
|
||||||
KeyToggler.forceSet(Input.Keys.PERIOD, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun disperseHeat(delta: Float) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun monitorIllegalFluidSetup() {
|
private fun monitorIllegalFluidSetup() {
|
||||||
for (y in 0 until fluidMap.size) {
|
for (y in 0 until fluidMap.size) {
|
||||||
for (x in 0 until fluidMap[0].size) {
|
for (x in 0 until fluidMap[0].size) {
|
||||||
@@ -380,5 +418,32 @@ object WorldSimulator {
|
|||||||
fun Int.isFallable() = BlockCodex[this].maxSupport
|
fun Int.isFallable() = BlockCodex[this].maxSupport
|
||||||
|
|
||||||
|
|
||||||
|
private val actorMBRConverter = object : MBRConverter<ActorWithBody> {
|
||||||
|
override fun getDimensions(): Int = 2
|
||||||
|
override fun getMin(axis: Int, t: ActorWithBody): Double =
|
||||||
|
when (axis) {
|
||||||
|
0 -> t.hitbox.startX
|
||||||
|
1 -> t.hitbox.startY
|
||||||
|
else -> throw IllegalArgumentException("nonexistent axis $axis for ${dimensions}-dimensional object")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getMax(axis: Int, t: ActorWithBody): Double =
|
||||||
|
when (axis) {
|
||||||
|
0 -> t.hitbox.endX
|
||||||
|
1 -> t.hitbox.endY
|
||||||
|
else -> throw IllegalArgumentException("nonexistent axis $axis for ${dimensions}-dimensional object")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// simple euclidean norm, squared
|
||||||
|
private val actorDistanceCalculator = object : DistanceCalculator<ActorWithBody> {
|
||||||
|
override fun distanceTo(t: ActorWithBody, p: PointND): Double {
|
||||||
|
val dist1 = (p.getOrd(0) - t.hitbox.centeredX).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
||||||
|
// ROUNDWORLD implementation
|
||||||
|
val dist2 = (p.getOrd(0) - (t.hitbox.centeredX - world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
||||||
|
val dist3 = (p.getOrd(0) - (t.hitbox.centeredX + world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
||||||
|
|
||||||
|
return minOf(dist1, minOf(dist2, dist3))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user