mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
phys debugging; see L818@ActorWithBody.kt
This commit is contained in:
@@ -214,6 +214,11 @@ object Skybox : Disposable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* To get the idea what the fuck is going on here, please refer to https://www.desmos.com/calculator/snqglcu2wl
|
* To get the idea what the fuck is going on here, please refer to https://www.desmos.com/calculator/snqglcu2wl
|
||||||
|
*
|
||||||
|
* Sidenote: the original model involved two cosine curves, but since its Taylor series begins with x^2, I figured
|
||||||
|
* quadratic curve ought to be good enough, and the error against the original model was below 1/255 for
|
||||||
|
* reasonable range of p, and that's the reason I stopped at x^2 rather than also taking x^4 into the approximated
|
||||||
|
* model that is the code below.
|
||||||
*/
|
*/
|
||||||
internal fun smoothLinear(p: Double, x0: Double): Double {
|
internal fun smoothLinear(p: Double, x0: Double): Double {
|
||||||
val x = x0 - 0.5
|
val x = x0 - 0.5
|
||||||
|
|||||||
@@ -698,6 +698,7 @@ open class ActorWithBody : Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun displaceHitbox() {
|
private fun displaceHitbox() {
|
||||||
|
val printdbg1 = true
|
||||||
// // HOW IT SHOULD WORK // //
|
// // HOW IT SHOULD WORK // //
|
||||||
// ////////////////////////
|
// ////////////////////////
|
||||||
// combineVeloToMoveDelta now
|
// combineVeloToMoveDelta now
|
||||||
@@ -724,25 +725,6 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
if (world != null) {
|
if (world != null) {
|
||||||
|
|
||||||
fun debug1(wut: Any?) {
|
|
||||||
// vvvvv set it true to make debug print work
|
|
||||||
if (false) printdbg(this, wut)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun debug2(wut: Any?) {
|
|
||||||
// vvvvv set it true to make debug print work
|
|
||||||
if (false) printdbg(this, wut)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun debug3(wut: Any?) {
|
|
||||||
// vvvvv set it true to make debug print work
|
|
||||||
if (false) printdbg(this, wut)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun debug4(wut: Any?) {
|
|
||||||
// vvvvv set it true to make debug print work
|
|
||||||
if (false) printdbg(this, wut)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun BlockAddress.isFeetTile(hitbox: Hitbox): Boolean {
|
fun BlockAddress.isFeetTile(hitbox: Hitbox): Boolean {
|
||||||
val (x, y) = LandUtil.resolveBlockAddr(world!!, this)
|
val (x, y) = LandUtil.resolveBlockAddr(world!!, this)
|
||||||
@@ -763,6 +745,8 @@ open class ActorWithBody : Actor {
|
|||||||
(x in newTilewiseHitbox.startX.toInt()..newTilewiseHitbox.endX.toInt()) // copied from forEachOccupyingTilePos
|
(x in newTilewiseHitbox.startX.toInt()..newTilewiseHitbox.endX.toInt()) // copied from forEachOccupyingTilePos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun Double.modTile() = this.div(TILE_SIZE).floorToInt().times(TILE_SIZE)
|
fun Double.modTile() = this.div(TILE_SIZE).floorToInt().times(TILE_SIZE)
|
||||||
fun Double.modTileDelta() = this - this.modTile()
|
fun Double.modTileDelta() = this - this.modTile()
|
||||||
|
|
||||||
@@ -777,10 +761,27 @@ open class ActorWithBody : Actor {
|
|||||||
// the job of the ccd is that the "next hitbox" would not dig into the terrain greater than the tile size,
|
// the job of the ccd is that the "next hitbox" would not dig into the terrain greater than the tile size,
|
||||||
// in which the modTileDelta returns a wrong value
|
// in which the modTileDelta returns a wrong value
|
||||||
val vectorSum = (externalV + controllerV)
|
val vectorSum = (externalV + controllerV)
|
||||||
val ccdSteps = (vectorSum.magnitude / TILE_SIZE).floorToInt().coerceIn(2, 16) // adaptive
|
val ccdSteps = (vectorSum.magnitude / TILE_SIZE).ceilToInt().plus(1).times(2).coerceIn(0, 64) // adaptive
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun debug1(wut: Any?) {
|
||||||
|
// vvvvv set it true to make debug print work
|
||||||
|
if (printdbg1 && vectorSum.magnitudeSquared != 0.0) printdbg(this, wut)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun debug2(wut: Any?) {
|
||||||
|
// vvvvv set it true to make debug print work
|
||||||
|
if (true && vectorSum.magnitudeSquared != 0.0) printdbg(this, wut)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printdbg1 && vectorSum.magnitudeSquared != 0.0) println("")
|
||||||
|
debug1("Update Frame: ${INGAME.WORLD_UPDATE_TIMER}")
|
||||||
|
debug1("Hitbox: ${hitbox}")
|
||||||
|
|
||||||
|
debug1("vec dir: ${Math.toDegrees(vectorSum.direction)}°, value: $vectorSum")
|
||||||
|
|
||||||
|
|
||||||
// * NEW idea: wall pushes the actors (ref. SM64 explained by dutch pancake) *
|
// * NEW idea: wall pushes the actors (ref. SM64 explained by dutch pancake) *
|
||||||
// direction to push is determined by the velocity
|
// direction to push is determined by the velocity
|
||||||
// proc:
|
// proc:
|
||||||
@@ -793,14 +794,16 @@ open class ActorWithBody : Actor {
|
|||||||
// ignore MOST of the codes below (it might be possible to recycle the structure??)
|
// ignore MOST of the codes below (it might be possible to recycle the structure??)
|
||||||
// and the idea above has not yet implemented, and may never will. --Torvald, 2018-12-30
|
// and the idea above has not yet implemented, and may never will. --Torvald, 2018-12-30
|
||||||
|
|
||||||
val sixteenStep = (0..ccdSteps).map { hitbox.clone().translate(vectorSum * (it / ccdSteps.toDouble())) } // zeroth step is for special condition
|
val sixteenStep = (0..ccdSteps).map { hitbox.clone().translate(vectorSum * (it / ccdSteps.toDouble())) }
|
||||||
|
|
||||||
var collidingStep: Int? = null
|
var collidingStep: Int? = null
|
||||||
|
|
||||||
for (step in 1..ccdSteps) {
|
for (step in 0..ccdSteps) {
|
||||||
|
|
||||||
val stepBox = sixteenStep[step]
|
val stepBox = sixteenStep[step]
|
||||||
|
|
||||||
|
debug2("stepbox[$step]=$stepBox; feet?=${vectorSum.y > PHYS_EPSILON_DIST}")
|
||||||
|
|
||||||
/*forEachOccupyingTilePos(stepBox) {
|
/*forEachOccupyingTilePos(stepBox) {
|
||||||
val tileCoord = LandUtil.resolveBlockAddr(world!!, it)
|
val tileCoord = LandUtil.resolveBlockAddr(world!!, it)
|
||||||
val tile = world!!.getTileFromTerrain(tileCoord.first, tileCoord.second) ?: Block.STONE
|
val tile = world!!.getTileFromTerrain(tileCoord.first, tileCoord.second) ?: Block.STONE
|
||||||
@@ -812,10 +815,11 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
// 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, vectorSum.y > PHYS_EPSILON_DIST)) {
|
if (isColliding(stepBox, vectorSum.y > PHYS_EPSILON_DIST)) {
|
||||||
|
// not registering collision sometimes?
|
||||||
collidingStep = step
|
collidingStep = step
|
||||||
}
|
}
|
||||||
|
|
||||||
if (collidingStep != null) break
|
// if (collidingStep != null) break
|
||||||
}
|
}
|
||||||
|
|
||||||
var bounceX = false
|
var bounceX = false
|
||||||
@@ -824,6 +828,7 @@ open class ActorWithBody : Actor {
|
|||||||
var zeroY = false
|
var zeroY = false
|
||||||
// collision NOT detected
|
// collision NOT detected
|
||||||
if (collidingStep == null) {
|
if (collidingStep == null) {
|
||||||
|
debug1("== Collision step: no collision")
|
||||||
hitbox.translate(vectorSum)
|
hitbox.translate(vectorSum)
|
||||||
// grounded = false
|
// grounded = false
|
||||||
}
|
}
|
||||||
@@ -831,6 +836,7 @@ open class ActorWithBody : Actor {
|
|||||||
else {
|
else {
|
||||||
debug1("== Collision step: $collidingStep / $ccdSteps")
|
debug1("== Collision step: $collidingStep / $ccdSteps")
|
||||||
|
|
||||||
|
debug1("CCD hitbox: ${sixteenStep[collidingStep]}")
|
||||||
|
|
||||||
val newHitbox = hitbox.reassign(sixteenStep[collidingStep])
|
val newHitbox = hitbox.reassign(sixteenStep[collidingStep])
|
||||||
|
|
||||||
@@ -859,11 +865,11 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
// fixme UP and RIGHT && LEFT and DOWN bug
|
// fixme UP and RIGHT && LEFT and DOWN bug
|
||||||
|
|
||||||
//println("collision: $selfCollisionStatus\tstaircasing: $staircaseStatus")
|
debug1("collision: $selfCollisionStatus\tstaircasing: $staircaseStatus")
|
||||||
|
|
||||||
when (selfCollisionStatus) {
|
when (selfCollisionStatus) {
|
||||||
0 -> {
|
0 -> {
|
||||||
debug1("[ActorWBMovable] Contradiction -- collision detected by CCD, but isWalled() says otherwise")
|
debug1("Contradiction -- collision detected by CCD, but isWalled() says otherwise")
|
||||||
}
|
}
|
||||||
5 -> {
|
5 -> {
|
||||||
zeroX = true
|
zeroX = true
|
||||||
@@ -943,10 +949,9 @@ open class ActorWithBody : Actor {
|
|||||||
(Vector2(offendingHitboxPointX, offendingHitboxPointY) -
|
(Vector2(offendingHitboxPointX, offendingHitboxPointY) -
|
||||||
Vector2(offendingTileWorldX, offendingTileWorldY)).direction
|
Vector2(offendingTileWorldX, offendingTileWorldY)).direction
|
||||||
|
|
||||||
|
debug1("incidentAngle: ${Math.toDegrees(angleOfIncidence)}°, threshold: ${Math.toDegrees(angleThreshold)}°")
|
||||||
|
|
||||||
debug1("vectorSum: $vectorSum, vectorDirRaw: ${vectorSum.direction / Math.PI}pi")
|
debug1("offendingTileWorldY=$offendingTileWorldY, offendingHitboxPointY=$offendingHitboxPointY")
|
||||||
debug1("incidentAngle: ${angleOfIncidence / Math.PI}pi, threshold: ${angleThreshold / Math.PI}pi")
|
|
||||||
|
|
||||||
|
|
||||||
val displacementAbs = Vector2(
|
val displacementAbs = Vector2(
|
||||||
(offendingTileWorldX - offendingHitboxPointX).abs(),
|
(offendingTileWorldX - offendingHitboxPointX).abs(),
|
||||||
@@ -958,7 +963,7 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
val displacementUnitVector =
|
val displacementUnitVector =
|
||||||
if (angleOfIncidence == angleThreshold)
|
if (angleOfIncidence == angleThreshold)
|
||||||
-vectorSum
|
-vectorSum.signum
|
||||||
else {
|
else {
|
||||||
when (selfCollisionStatus) {
|
when (selfCollisionStatus) {
|
||||||
3 -> if (angleOfIncidence > angleThreshold) Vector2(1.0, 0.0) else Vector2(0.0, -1.0)
|
3 -> if (angleOfIncidence > angleThreshold) Vector2(1.0, 0.0) else Vector2(0.0, -1.0)
|
||||||
@@ -970,21 +975,25 @@ open class ActorWithBody : Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val finalDisplacement =
|
val finalDisplacement =
|
||||||
if (angleOfIncidence == angleThreshold)
|
// if (angleOfIncidence == angleThreshold)
|
||||||
displacementUnitVector
|
// displacementUnitVector
|
||||||
else
|
// else
|
||||||
Vector2(
|
Vector2(
|
||||||
displacementAbs.x * displacementUnitVector.x,
|
displacementAbs.x * displacementUnitVector.x,
|
||||||
displacementAbs.y * displacementUnitVector.y
|
displacementAbs.y * displacementUnitVector.y
|
||||||
)
|
)
|
||||||
|
|
||||||
|
debug1("displacementAbs=$displacementAbs")
|
||||||
|
debug1("displacementUnitVector=$displacementUnitVector")
|
||||||
|
debug1("finalDisplacement=$finalDisplacement")
|
||||||
|
|
||||||
// adjust finalDisplacement for honest-to-god staircasing
|
// adjust finalDisplacement for honest-to-god staircasing
|
||||||
if (physProp.useStairs && vectorSum.y <= 0.0 && staircaseStatus in listOf(1, 4) && selfCollisionStatus in (if (gravitation.y >= 0.0) listOf(3,6) else listOf(9, 12))) {
|
if (physProp.useStairs && vectorSum.y <= 0.0 && staircaseStatus in listOf(1, 4) && selfCollisionStatus in (if (gravitation.y >= 0.0) listOf(3,6) else listOf(9, 12))) {
|
||||||
// remove Y displacement
|
// remove Y displacement
|
||||||
// let original X velocity to pass-thru instead of snapping to tiles coded above
|
// let original X velocity to pass-thru instead of snapping to tiles coded above
|
||||||
// pass-thru values are held by the vectorSum
|
// pass-thru values are held by the vectorSum
|
||||||
|
|
||||||
//println("staircasing: $staircaseStatus for $selfCollisionStatus")
|
debug1("staircasing: $staircaseStatus for $selfCollisionStatus")
|
||||||
|
|
||||||
val stairHeight = if (staircaseStatus == COLLIDING_LEFT) stairHeightLeft else stairHeightRight
|
val stairHeight = if (staircaseStatus == COLLIDING_LEFT) stairHeightLeft else stairHeightRight
|
||||||
finalDisplacement.y = -stairHeight
|
finalDisplacement.y = -stairHeight
|
||||||
@@ -1043,6 +1052,7 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
|
|
||||||
hitbox.reassign(newHitbox)
|
hitbox.reassign(newHitbox)
|
||||||
|
debug1("resulting hitbox: $newHitbox")
|
||||||
|
|
||||||
|
|
||||||
// slam-into-whatever damage (such dirty; much hack; wow)
|
// slam-into-whatever damage (such dirty; much hack; wow)
|
||||||
@@ -1069,7 +1079,7 @@ open class ActorWithBody : Actor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun collisionInterpolatorRun() {
|
/*fun collisionInterpolatorRun() {
|
||||||
|
|
||||||
fun isWalled2(hitbox: Hitbox, option: Int): Boolean {
|
fun isWalled2(hitbox: Hitbox, option: Int): Boolean {
|
||||||
val newHB = Hitbox.fromTwoPoints(
|
val newHB = Hitbox.fromTwoPoints(
|
||||||
@@ -1086,18 +1096,16 @@ open class ActorWithBody : Actor {
|
|||||||
val intpStep = 64.0
|
val intpStep = 64.0
|
||||||
|
|
||||||
// make interpolation even if the "next" position is clear of collision
|
// make interpolation even if the "next" position is clear of collision
|
||||||
val testHitbox = hitbox.clone()
|
var testHitbox = hitbox.clone()
|
||||||
|
|
||||||
// divide the vectors by the constant
|
val vecSum = (externalV + controllerV)
|
||||||
externalV /= intpStep
|
|
||||||
controllerV?.let { controllerV!! /= intpStep }
|
|
||||||
|
|
||||||
repeat(intpStep.toInt()) { // basically we don't care if we're already been encased (e.g. entrapped by falling sand)
|
repeat(intpStep.toInt()) { // basically we don't care if we're already been encased (e.g. entrapped by falling sand)
|
||||||
|
|
||||||
// change the order and the player gets stuck in the vertical wall
|
// change the order and the player gets stuck in the vertical wall
|
||||||
// so leave as-is
|
// so leave as-is
|
||||||
|
|
||||||
testHitbox.translate(externalV + controllerV)
|
testHitbox = hitbox.clone().translate(vecSum * ((it + 1.0) / intpStep)) // <- this would not accumulate errors
|
||||||
|
|
||||||
// vertical collision
|
// vertical collision
|
||||||
if (isWalled2(testHitbox, COLLIDING_UD)) {
|
if (isWalled2(testHitbox, COLLIDING_UD)) {
|
||||||
@@ -1114,14 +1122,9 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
hitbox.reassign(testHitbox)
|
hitbox.reassign(testHitbox)
|
||||||
|
|
||||||
// revert the division because the Acceleration depends on being able to integrate onto the velo values
|
|
||||||
// don't want to mess up with the value they're expecting
|
|
||||||
externalV *= intpStep
|
|
||||||
controllerV?.let { controllerV!! *= intpStep }
|
|
||||||
|
|
||||||
// TODO collision damage
|
// TODO collision damage
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see /work_files/hitbox_collision_detection_compensation.jpg
|
* @see /work_files/hitbox_collision_detection_compensation.jpg
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
package org.dyn4j.geometry
|
package org.dyn4j.geometry
|
||||||
|
|
||||||
import org.dyn4j.Epsilon
|
import org.dyn4j.Epsilon
|
||||||
|
import kotlin.math.sign
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a vector or point in 2D space.
|
* This class represents a vector or point in 2D space.
|
||||||
@@ -699,6 +700,9 @@ class Vector2 {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val signum: Vector2
|
||||||
|
get() = Vector2(this.x.sign, this.y.sign)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** A vector representing the x-axis; this vector should not be changed at runtime; used internally */
|
/** A vector representing the x-axis; this vector should not be changed at runtime; used internally */
|
||||||
internal val X_AXIS = Vector2(1.0, 0.0)
|
internal val X_AXIS = Vector2(1.0, 0.0)
|
||||||
|
|||||||
Reference in New Issue
Block a user