mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-15 04:54:05 +09:00
abolished a need to pass world as parametre
+ simply changing the single variable (ingame.world) will update all the renderer's behaviour + somehow my git changelogs are exploding
This commit is contained in:
@@ -31,15 +31,21 @@ import java.util.*
|
||||
*
|
||||
* Created by minjaesong on 2016-01-13.
|
||||
*/
|
||||
open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val immobileBody: Boolean = false, var usePhysics: Boolean = true) :
|
||||
open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean = false, var usePhysics: Boolean = true) :
|
||||
ActorWithBody(renderOrder) {
|
||||
|
||||
|
||||
val COLLISION_TEST_MODE = false
|
||||
|
||||
/** !! ActorValue macros are on the very bottom of the source !! **/
|
||||
/* !! ActorValue macros are on the very bottom of the source !! */
|
||||
|
||||
/** This is GameWorld? only because the title screen also uses this thing as its camera;
|
||||
* titlescreen does not use instance of Ingame.
|
||||
*/
|
||||
private val world: GameWorld?
|
||||
get() = Terrarum.ingame?.world
|
||||
|
||||
|
||||
@Transient internal var sprite: SpriteAnimation? = null
|
||||
@Transient internal var spriteGlow: SpriteAnimation? = null
|
||||
|
||||
@@ -165,9 +171,11 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
*/
|
||||
|
||||
private inline val grounded: Boolean
|
||||
get() = isNoClip ||
|
||||
(world.gravitation.y > 0 && isWalled(hitbox, COLLIDING_BOTTOM) ||
|
||||
world.gravitation.y < 0 && isWalled(hitbox, COLLIDING_TOP))
|
||||
get() = if (world == null) true else {
|
||||
isNoClip ||
|
||||
(world!!.gravitation.y > 0 && isWalled(hitbox, COLLIDING_BOTTOM) ||
|
||||
world!!.gravitation.y < 0 && isWalled(hitbox, COLLIDING_TOP))
|
||||
}
|
||||
/** Default to 'true' */
|
||||
var isVisible = true
|
||||
/** Default to 'true' */
|
||||
@@ -190,7 +198,8 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
* s^2 = 1/FPS = 1/60 if FPS is targeted to 60
|
||||
* meter to pixel : 24/FPS
|
||||
*/
|
||||
@Transient private val gravitation: Vector2 = world.gravitation
|
||||
private val gravitation: Vector2
|
||||
get() = world?.gravitation ?: Vector2(0.0, 9.8)
|
||||
@Transient val DRAG_COEFF_DEFAULT = 1.2
|
||||
/** Drag coefficient. Parachutes have much higher value than bare body (1.2) */
|
||||
var dragCoefficient: Double
|
||||
@@ -565,257 +574,281 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
|
||||
private fun displaceHitbox() {
|
||||
|
||||
fun debug1(wut: Any?) {
|
||||
// vvvvv set it true to make debug print work
|
||||
if (true) println(wut)
|
||||
}
|
||||
fun debug2(wut: Any?) {
|
||||
// vvvvv set it true to make debug print work
|
||||
if (false) println(wut)
|
||||
}
|
||||
fun debug3(wut: Any?) {
|
||||
// vvvvv set it true to make debug print work
|
||||
if (false) println(wut)
|
||||
}
|
||||
fun debug4(wut: Any?) {
|
||||
// vvvvv set it true to make debug print work
|
||||
if (false) println(wut)
|
||||
}
|
||||
fun Double.modTile() = this.toInt().div(TILE_SIZE).times(TILE_SIZE)
|
||||
fun Double.modTileDelta() = this - this.modTile()
|
||||
if (world != null) {
|
||||
|
||||
fun debug1(wut: Any?) {
|
||||
// vvvvv set it true to make debug print work
|
||||
if (true) println(wut)
|
||||
}
|
||||
|
||||
fun debug2(wut: Any?) {
|
||||
// vvvvv set it true to make debug print work
|
||||
if (false) println(wut)
|
||||
}
|
||||
|
||||
fun debug3(wut: Any?) {
|
||||
// vvvvv set it true to make debug print work
|
||||
if (false) println(wut)
|
||||
}
|
||||
|
||||
fun debug4(wut: Any?) {
|
||||
// vvvvv set it true to make debug print work
|
||||
if (false) println(wut)
|
||||
}
|
||||
|
||||
fun Double.modTile() = this.toInt().div(TILE_SIZE).times(TILE_SIZE)
|
||||
fun Double.modTileDelta() = this - this.modTile()
|
||||
|
||||
|
||||
val vectorSum = externalForce + controllerMoveDelta
|
||||
val ccdSteps = minOf(16, (vectorSum.magnitudeSquared / TILE_SIZE.sqr()).floorInt() + 1) // adaptive
|
||||
val vectorSum = externalForce + controllerMoveDelta
|
||||
val ccdSteps = minOf(16, (vectorSum.magnitudeSquared / TILE_SIZE.sqr()).floorInt() + 1) // adaptive
|
||||
|
||||
|
||||
|
||||
// * NEW idea: wall pushes the actors (ref. SM64 explained by dutch pancake) *
|
||||
// direction to push is determined by the velocity
|
||||
// proc:
|
||||
// 10 I detect being walled and displace myself
|
||||
// 11 There's 16 possible case so work all 16 (some can be merged obviously)
|
||||
// 12 Amount of displacement can be obtained with modTileDelta()
|
||||
// 13 isWalled() is confirmed to be working
|
||||
// 20 sixteenStep may be optional, I think, but it'd be good to have
|
||||
// * NEW idea: wall pushes the actors (ref. SM64 explained by dutch pancake) *
|
||||
// direction to push is determined by the velocity
|
||||
// proc:
|
||||
// 10 I detect being walled and displace myself
|
||||
// 11 There's 16 possible case so work all 16 (some can be merged obviously)
|
||||
// 12 Amount of displacement can be obtained with modTileDelta()
|
||||
// 13 isWalled() is confirmed to be working
|
||||
// 20 sixteenStep may be optional, I think, but it'd be good to have
|
||||
|
||||
// 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??)
|
||||
|
||||
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())) } // zeroth step is for special condition
|
||||
|
||||
val affectingTiles = ArrayList<BlockAddress>()
|
||||
var collidingStep: Int? = null
|
||||
val affectingTiles = ArrayList<BlockAddress>()
|
||||
var collidingStep: Int? = null
|
||||
|
||||
for (step in 1..ccdSteps) {
|
||||
for (step in 1..ccdSteps) {
|
||||
|
||||
val stepBox = sixteenStep[step]
|
||||
val stepBox = sixteenStep[step]
|
||||
|
||||
forEachOccupyingTilePos(stepBox) {
|
||||
val tileCoord = LandUtil.resolveBlockAddr(this.world, it)
|
||||
val tileProp = BlockCodex.getOrNull(world.getTileFromTerrain(tileCoord.first, tileCoord.second))
|
||||
forEachOccupyingTilePos(stepBox) {
|
||||
val tileCoord = LandUtil.resolveBlockAddr(world!!, it)
|
||||
val tileProp = BlockCodex.getOrNull(world!!.getTileFromTerrain(tileCoord.first, tileCoord.second))
|
||||
|
||||
if (tileProp == null || tileProp.isSolid) {
|
||||
affectingTiles.add(it)
|
||||
if (tileProp == null || tileProp.isSolid) {
|
||||
affectingTiles.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (affectingTiles.isNotEmpty()) {
|
||||
collidingStep = step
|
||||
break // collision found on this step, break and proceed to next step
|
||||
}
|
||||
}
|
||||
|
||||
if (affectingTiles.isNotEmpty()) {
|
||||
collidingStep = step
|
||||
break // collision found on this step, break and proceed to next step
|
||||
|
||||
val COLL_LEFTSIDE = 1
|
||||
val COLL_BOTTOMSIDE = 2
|
||||
val COLL_RIGHTSIDE = 4
|
||||
val COLL_TOPSIDE = 8
|
||||
|
||||
var bounceX = false
|
||||
var bounceY = false
|
||||
var zeroX = false
|
||||
var zeroY = false
|
||||
// collision NOT detected
|
||||
if (collidingStep == null) {
|
||||
hitbox.translate(vectorSum)
|
||||
// grounded = false
|
||||
}
|
||||
}
|
||||
// collision detected
|
||||
else {
|
||||
debug1("== Collision step: $collidingStep / $ccdSteps")
|
||||
|
||||
|
||||
val COLL_LEFTSIDE = 1
|
||||
val COLL_BOTTOMSIDE = 2
|
||||
val COLL_RIGHTSIDE = 4
|
||||
val COLL_TOPSIDE = 8
|
||||
val newHitbox = hitbox.reassign(sixteenStep[collidingStep])
|
||||
|
||||
var bounceX = false
|
||||
var bounceY = false
|
||||
var zeroX = false
|
||||
var zeroY = false
|
||||
// collision NOT detected
|
||||
if (collidingStep == null) {
|
||||
hitbox.translate(vectorSum)
|
||||
// grounded = false
|
||||
}
|
||||
// collision detected
|
||||
else {
|
||||
debug1("== Collision step: $collidingStep / $ccdSteps")
|
||||
var selfCollisionStatus = 0
|
||||
if (isWalled(newHitbox, COLLIDING_LEFT)) selfCollisionStatus += COLL_LEFTSIDE // 1
|
||||
if (isWalled(newHitbox, COLLIDING_RIGHT)) selfCollisionStatus += COLL_RIGHTSIDE // 4
|
||||
if (isWalled(newHitbox, COLLIDING_TOP)) selfCollisionStatus += COLL_TOPSIDE // 8
|
||||
if (isWalled(newHitbox, COLLIDING_BOTTOM)) selfCollisionStatus += COLL_BOTTOMSIDE // 2
|
||||
|
||||
// fixme UP and RIGHT && LEFT and DOWN bug
|
||||
|
||||
val newHitbox = hitbox.reassign(sixteenStep[collidingStep])
|
||||
debug1("Collision type: $selfCollisionStatus")
|
||||
affectingTiles.forEach {
|
||||
val tileCoord = LandUtil.resolveBlockAddr(world!!, it)
|
||||
debug2("affectign tile: ${tileCoord.first}, ${tileCoord.second}")
|
||||
}
|
||||
|
||||
var selfCollisionStatus = 0
|
||||
if (isWalled(newHitbox, COLLIDING_LEFT)) selfCollisionStatus += COLL_LEFTSIDE // 1
|
||||
if (isWalled(newHitbox, COLLIDING_RIGHT)) selfCollisionStatus += COLL_RIGHTSIDE // 4
|
||||
if (isWalled(newHitbox, COLLIDING_TOP)) selfCollisionStatus += COLL_TOPSIDE // 8
|
||||
if (isWalled(newHitbox, COLLIDING_BOTTOM)) selfCollisionStatus += COLL_BOTTOMSIDE // 2
|
||||
|
||||
// fixme UP and RIGHT && LEFT and DOWN bug
|
||||
|
||||
debug1("Collision type: $selfCollisionStatus")
|
||||
affectingTiles.forEach {
|
||||
val tileCoord = LandUtil.resolveBlockAddr(this.world, it)
|
||||
debug2("affectign tile: ${tileCoord.first}, ${tileCoord.second}")
|
||||
}
|
||||
|
||||
when (selfCollisionStatus) {
|
||||
0 -> { debug1("[ActorWBMovable] Contradiction -- collision detected by CCD, but isWalled() says otherwise") }
|
||||
5 -> { zeroX = true }
|
||||
10 -> { zeroY = true }
|
||||
15 -> { newHitbox.reassign(sixteenStep[0]); zeroX = true; zeroY = true }
|
||||
when (selfCollisionStatus) {
|
||||
0 -> {
|
||||
debug1("[ActorWBMovable] Contradiction -- collision detected by CCD, but isWalled() says otherwise")
|
||||
}
|
||||
5 -> {
|
||||
zeroX = true
|
||||
}
|
||||
10 -> {
|
||||
zeroY = true
|
||||
}
|
||||
15 -> {
|
||||
newHitbox.reassign(sixteenStep[0]); zeroX = true; zeroY = true
|
||||
}
|
||||
// one-side collision
|
||||
1, 11 -> { newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta()); bounceX = true }
|
||||
4, 14 -> { newHitbox.translatePosX( - newHitbox.endX.modTileDelta()) ; bounceX = true }
|
||||
8, 13 -> { newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta()); bounceY = true }
|
||||
2, 7 -> { newHitbox.translatePosY( - newHitbox.endY.modTileDelta()) ; bounceY = true }
|
||||
}
|
||||
1, 11 -> {
|
||||
newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta()); bounceX = true
|
||||
}
|
||||
4, 14 -> {
|
||||
newHitbox.translatePosX(-newHitbox.endX.modTileDelta()); bounceX = true
|
||||
}
|
||||
8, 13 -> {
|
||||
newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta()); bounceY = true
|
||||
}
|
||||
2, 7 -> {
|
||||
newHitbox.translatePosY(-newHitbox.endY.modTileDelta()); bounceY = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fire Collision Event with one/two/three-side collision
|
||||
// for the ease of writing, this jumptable is separated from above.
|
||||
when (selfCollisionStatus) {
|
||||
// fire Collision Event with one/two/three-side collision
|
||||
// for the ease of writing, this jumptable is separated from above.
|
||||
when (selfCollisionStatus) {
|
||||
// TODO compose CollisionInfo and fire collided()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// two-side collision
|
||||
if (selfCollisionStatus in listOf(3,6,9,12)) {
|
||||
debug1("twoside collision $selfCollisionStatus")
|
||||
// two-side collision
|
||||
if (selfCollisionStatus in listOf(3, 6, 9, 12)) {
|
||||
debug1("twoside collision $selfCollisionStatus")
|
||||
|
||||
// !! this code is based on Dyn4j Vector's coord system; V(1,0) -> 0, V(0,1) -> pi, V(0,-1) -> -pi !! //
|
||||
// !! this code is based on Dyn4j Vector's coord system; V(1,0) -> 0, V(0,1) -> pi, V(0,-1) -> -pi !! //
|
||||
|
||||
// we can use selfCollisionStatus to tell which of those four side we care
|
||||
// we can use selfCollisionStatus to tell which of those four side we care
|
||||
|
||||
// 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))
|
||||
newHitbox.endX.div(TILE_SIZE).floor() * TILE_SIZE - 0.00001
|
||||
else
|
||||
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!!)
|
||||
val offendingTileWorldX = if (selfCollisionStatus in listOf(6, 12))
|
||||
newHitbox.endX.div(TILE_SIZE).floor() * TILE_SIZE - 0.00001
|
||||
else
|
||||
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!!)
|
||||
val offendingTileWorldY = if (selfCollisionStatus in listOf(3, 6))
|
||||
newHitbox.endY.div(TILE_SIZE).floor() * TILE_SIZE - 0.00001
|
||||
else
|
||||
newHitbox.startY.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!!)
|
||||
val offendingTileWorldY = if (selfCollisionStatus in listOf(3, 6))
|
||||
newHitbox.endY.div(TILE_SIZE).floor() * TILE_SIZE - 0.00001
|
||||
else
|
||||
newHitbox.startY.div(TILE_SIZE).ceil() * TILE_SIZE
|
||||
|
||||
val offendingHitboxPointX = if (selfCollisionStatus in listOf(6, 12))
|
||||
newHitbox.endX
|
||||
else
|
||||
newHitbox.startX
|
||||
val offendingHitboxPointX = if (selfCollisionStatus in listOf(6, 12))
|
||||
newHitbox.endX
|
||||
else
|
||||
newHitbox.startX
|
||||
|
||||
val offendingHitboxPointY = if (selfCollisionStatus in listOf(3, 6))
|
||||
newHitbox.endY
|
||||
else
|
||||
newHitbox.startY
|
||||
val offendingHitboxPointY = if (selfCollisionStatus in listOf(3, 6))
|
||||
newHitbox.endY
|
||||
else
|
||||
newHitbox.startY
|
||||
|
||||
|
||||
|
||||
val angleOfIncidence =
|
||||
if (selfCollisionStatus in listOf(3, 9))
|
||||
vectorSum.direction.toPositiveRad()
|
||||
else
|
||||
vectorSum.direction
|
||||
val angleOfIncidence =
|
||||
if (selfCollisionStatus in listOf(3, 9))
|
||||
vectorSum.direction.toPositiveRad()
|
||||
else
|
||||
vectorSum.direction
|
||||
|
||||
val angleThreshold =
|
||||
if (selfCollisionStatus in listOf(3, 9))
|
||||
(Vector2(offendingHitboxPointX, offendingHitboxPointY) -
|
||||
Vector2(offendingTileWorldX, offendingTileWorldY)).direction.toPositiveRad()
|
||||
else
|
||||
(Vector2(offendingHitboxPointX, offendingHitboxPointY) -
|
||||
Vector2(offendingTileWorldX, offendingTileWorldY)).direction
|
||||
val angleThreshold =
|
||||
if (selfCollisionStatus in listOf(3, 9))
|
||||
(Vector2(offendingHitboxPointX, offendingHitboxPointY) -
|
||||
Vector2(offendingTileWorldX, offendingTileWorldY)).direction.toPositiveRad()
|
||||
else
|
||||
(Vector2(offendingHitboxPointX, offendingHitboxPointY) -
|
||||
Vector2(offendingTileWorldX, offendingTileWorldY)).direction
|
||||
|
||||
|
||||
debug1("vectorSum: $vectorSum, vectorDirRaw: ${vectorSum.direction / Math.PI}pi")
|
||||
debug1("incidentAngle: ${angleOfIncidence / Math.PI}pi, threshold: ${angleThreshold / Math.PI}pi")
|
||||
debug1("vectorSum: $vectorSum, vectorDirRaw: ${vectorSum.direction / Math.PI}pi")
|
||||
debug1("incidentAngle: ${angleOfIncidence / Math.PI}pi, threshold: ${angleThreshold / Math.PI}pi")
|
||||
|
||||
|
||||
val displacementAbs = Vector2(
|
||||
(offendingTileWorldX - offendingHitboxPointX).abs(),
|
||||
(offendingTileWorldY - offendingHitboxPointY).abs()
|
||||
)
|
||||
val displacementAbs = Vector2(
|
||||
(offendingTileWorldX - offendingHitboxPointX).abs(),
|
||||
(offendingTileWorldY - offendingHitboxPointY).abs()
|
||||
)
|
||||
|
||||
|
||||
// FIXME jump-thru-ceil bug on 1px-wide (the edge), case-9 collision (does not occur on case-12 coll.)
|
||||
// FIXME jump-thru-ceil bug on 1px-wide (the edge), case-9 collision (does not occur on case-12 coll.)
|
||||
|
||||
|
||||
val displacementUnitVector =
|
||||
if (angleOfIncidence == angleThreshold)
|
||||
-vectorSum
|
||||
else {
|
||||
when (selfCollisionStatus) {
|
||||
3 -> if (angleOfIncidence > angleThreshold) Vector2(1.0, 0.0) else Vector2(0.0, -1.0)
|
||||
6 -> if (angleOfIncidence > angleThreshold) Vector2(0.0, -1.0) else Vector2(-1.0, 0.0)
|
||||
9 -> if (angleOfIncidence > angleThreshold) Vector2(0.0, 1.0) else Vector2(1.0, 0.0)
|
||||
12 -> if (angleOfIncidence > angleThreshold) Vector2(-1.0, 0.0) else Vector2(0.0, 1.0)
|
||||
else -> throw InternalError("Blame hardware or universe")
|
||||
val displacementUnitVector =
|
||||
if (angleOfIncidence == angleThreshold)
|
||||
-vectorSum
|
||||
else {
|
||||
when (selfCollisionStatus) {
|
||||
3 -> if (angleOfIncidence > angleThreshold) Vector2(1.0, 0.0) else Vector2(0.0, -1.0)
|
||||
6 -> if (angleOfIncidence > angleThreshold) Vector2(0.0, -1.0) else Vector2(-1.0, 0.0)
|
||||
9 -> if (angleOfIncidence > angleThreshold) Vector2(0.0, 1.0) else Vector2(1.0, 0.0)
|
||||
12 -> if (angleOfIncidence > angleThreshold) Vector2(-1.0, 0.0) else Vector2(0.0, 1.0)
|
||||
else -> throw InternalError("Blame hardware or universe")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val finalDisplacement =
|
||||
if (angleOfIncidence == angleThreshold)
|
||||
displacementUnitVector
|
||||
else
|
||||
Vector2(
|
||||
displacementAbs.x * displacementUnitVector.x,
|
||||
displacementAbs.y * displacementUnitVector.y
|
||||
)
|
||||
val finalDisplacement =
|
||||
if (angleOfIncidence == angleThreshold)
|
||||
displacementUnitVector
|
||||
else
|
||||
Vector2(
|
||||
displacementAbs.x * displacementUnitVector.x,
|
||||
displacementAbs.y * displacementUnitVector.y
|
||||
)
|
||||
|
||||
newHitbox.translate(finalDisplacement)
|
||||
newHitbox.translate(finalDisplacement)
|
||||
|
||||
|
||||
debug1("displacement: $finalDisplacement")
|
||||
debug1("displacement: $finalDisplacement")
|
||||
|
||||
|
||||
// TODO: translate other axis proportionally to the incident vector
|
||||
// TODO: translate other axis proportionally to the incident vector
|
||||
|
||||
bounceX = angleOfIncidence == angleThreshold || displacementUnitVector.x != 0.0
|
||||
bounceY = angleOfIncidence == angleThreshold || displacementUnitVector.y != 0.0
|
||||
bounceX = angleOfIncidence == angleThreshold || displacementUnitVector.x != 0.0
|
||||
bounceY = angleOfIncidence == angleThreshold || displacementUnitVector.y != 0.0
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// bounce X/Y
|
||||
if (bounceX) {
|
||||
externalForce.x *= elasticity
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.x *= elasticity }
|
||||
}
|
||||
if (bounceY) {
|
||||
externalForce.y *= elasticity
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.y *= elasticity }
|
||||
}
|
||||
if (zeroX) {
|
||||
externalForce.x = 0.0
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.x = 0.0 }
|
||||
}
|
||||
if (zeroY) {
|
||||
externalForce.y = 0.0
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.y = 0.0 }
|
||||
}
|
||||
// bounce X/Y
|
||||
if (bounceX) {
|
||||
externalForce.x *= elasticity
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.x *= elasticity }
|
||||
}
|
||||
if (bounceY) {
|
||||
externalForce.y *= elasticity
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.y *= elasticity }
|
||||
}
|
||||
if (zeroX) {
|
||||
externalForce.x = 0.0
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.x = 0.0 }
|
||||
}
|
||||
if (zeroY) {
|
||||
externalForce.y = 0.0
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.y = 0.0 }
|
||||
}
|
||||
|
||||
|
||||
hitbox.reassign(newHitbox)
|
||||
hitbox.reassign(newHitbox)
|
||||
|
||||
|
||||
// slam-into-whatever damage (such dirty; much hack; wow)
|
||||
// vvvv hack (supposed to be 1.0) vvv 50% hack
|
||||
val collisionDamage = mass * (vectorSum.magnitude / (10.0 / Terrarum.TARGET_FPS).sqr()) / fallDamageDampening.sqr() * GAME_TO_SI_ACC
|
||||
// kg * m / s^2 (mass * acceleration), acceleration -> (vectorMagn / (0.01)^2).gameToSI()
|
||||
if (collisionDamage != 0.0) debug1("Collision damage: $collisionDamage N")
|
||||
// FIXME instead of 0.5mv^2, we can model after "change of velocity (aka accel)", just as in real-life; big change of accel on given unit time is what kills
|
||||
// slam-into-whatever damage (such dirty; much hack; wow)
|
||||
// vvvv hack (supposed to be 1.0) vvv 50% hack
|
||||
val collisionDamage = mass * (vectorSum.magnitude / (10.0 / Terrarum.TARGET_FPS).sqr()) / fallDamageDampening.sqr() * GAME_TO_SI_ACC
|
||||
// kg * m / s^2 (mass * acceleration), acceleration -> (vectorMagn / (0.01)^2).gameToSI()
|
||||
if (collisionDamage != 0.0) debug1("Collision damage: $collisionDamage N")
|
||||
// FIXME instead of 0.5mv^2, we can model after "change of velocity (aka accel)", just as in real-life; big change of accel on given unit time is what kills
|
||||
|
||||
|
||||
// grounded = true
|
||||
}// end of collision not detected
|
||||
// grounded = true
|
||||
}// end of collision not detected
|
||||
|
||||
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
|
||||
// if collision not detected, just don't care; it's not your job to apply moveDelta
|
||||
// if collision not detected, just don't care; it's not your job to apply moveDelta
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -909,9 +942,11 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
}
|
||||
|
||||
private fun isCollidingInternal(txStart: Int, tyStart: Int, txEnd: Int, tyEnd: Int): Boolean {
|
||||
if (world == null) return false
|
||||
|
||||
for (y in tyStart..tyEnd) {
|
||||
for (x in txStart..txEnd) {
|
||||
val tile = world.getTileFromTerrain(x, y)
|
||||
val tile = world!!.getTileFromTerrain(x, y)
|
||||
if (BlockCodex[tile].isSolid)
|
||||
return true
|
||||
}
|
||||
@@ -921,6 +956,8 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
}
|
||||
|
||||
private fun getContactingAreaFluid(side: Int, translateX: Int = 0, translateY: Int = 0): Int {
|
||||
if (world == null) return 0
|
||||
|
||||
var contactAreaCounter = 0
|
||||
for (i in 0..(if (side % 2 == 0) hitbox.width else hitbox.height).roundInt() - 1) {
|
||||
// set tile positions
|
||||
@@ -951,7 +988,7 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
}
|
||||
|
||||
// evaluate
|
||||
if (BlockCodex[world.getTileFromTerrain(tileX, tileY)].isFluid) {
|
||||
if (BlockCodex[world!!.getTileFromTerrain(tileX, tileY)].isFluid) {
|
||||
contactAreaCounter += 1
|
||||
}
|
||||
}
|
||||
@@ -1166,7 +1203,10 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
}
|
||||
|
||||
private fun clampHitbox() {
|
||||
val worldsizePxl = world.width.times(TILE_SIZE)
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val worldsizePxl = world!!.width.times(TILE_SIZE)
|
||||
|
||||
// DEAR FUTURE ME,
|
||||
//
|
||||
@@ -1223,7 +1263,10 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
}
|
||||
|
||||
private fun drawSpriteInGoodPosition(sprite: SpriteAnimation, batch: SpriteBatch) {
|
||||
val leftsidePadding = world.width.times(TILE_SIZE) - WorldCamera.width.ushr(1)
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val leftsidePadding = world!!.width.times(TILE_SIZE) - WorldCamera.width.ushr(1)
|
||||
val rightsidePadding = WorldCamera.width.ushr(1)
|
||||
|
||||
val offsetX = hitboxTranslateX * scale
|
||||
@@ -1233,7 +1276,7 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
if (WorldCamera.xCentre > leftsidePadding && centrePosPoint.x <= rightsidePadding) {
|
||||
// camera center neg, actor center pos
|
||||
sprite.render(batch,
|
||||
(hitbox.startX - offsetX).toFloat() + world.width * TILE_SIZE,
|
||||
(hitbox.startX - offsetX).toFloat() + world!!.width * TILE_SIZE,
|
||||
(hitbox.startY - offsetY).toFloat(),
|
||||
(scale).toFloat()
|
||||
)
|
||||
@@ -1241,7 +1284,7 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
else if (WorldCamera.xCentre < rightsidePadding && centrePosPoint.x >= leftsidePadding) {
|
||||
// camera center pos, actor center neg
|
||||
sprite.render(batch,
|
||||
(hitbox.startX - offsetX).toFloat() - world.width * TILE_SIZE,
|
||||
(hitbox.startX - offsetX).toFloat() - world!!.width * TILE_SIZE,
|
||||
(hitbox.startY - offsetY).toFloat(),
|
||||
(scale).toFloat()
|
||||
)
|
||||
@@ -1263,32 +1306,34 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
|
||||
|
||||
private fun clampW(x: Double): Double =
|
||||
if (x < TILE_SIZE + hitbox.width / 2) {
|
||||
if (world == null) x
|
||||
else if (x < TILE_SIZE + hitbox.width / 2) {
|
||||
TILE_SIZE + hitbox.width / 2
|
||||
}
|
||||
else if (x >= (world.width * TILE_SIZE).toDouble() - TILE_SIZE.toDouble() - hitbox.width / 2) {
|
||||
(world.width * TILE_SIZE).toDouble() - 1.0 - TILE_SIZE.toDouble() - hitbox.width / 2
|
||||
else if (x >= (world!!.width * TILE_SIZE).toDouble() - TILE_SIZE.toDouble() - hitbox.width / 2) {
|
||||
(world!!.width * TILE_SIZE).toDouble() - 1.0 - TILE_SIZE.toDouble() - hitbox.width / 2
|
||||
}
|
||||
else {
|
||||
x
|
||||
}
|
||||
|
||||
private fun clampH(y: Double): Double =
|
||||
if (y < TILE_SIZE + hitbox.height) {
|
||||
if (world == null) y
|
||||
else if (y < TILE_SIZE + hitbox.height) {
|
||||
TILE_SIZE + hitbox.height
|
||||
}
|
||||
else if (y >= (world.height * TILE_SIZE).toDouble() - TILE_SIZE.toDouble() - hitbox.height) {
|
||||
(world.height * TILE_SIZE).toDouble() - 1.0 - TILE_SIZE.toDouble() - hitbox.height
|
||||
else if (y >= (world!!.height * TILE_SIZE).toDouble() - TILE_SIZE.toDouble() - hitbox.height) {
|
||||
(world!!.height * TILE_SIZE).toDouble() - 1.0 - TILE_SIZE.toDouble() - hitbox.height
|
||||
}
|
||||
else {
|
||||
y
|
||||
}
|
||||
|
||||
private fun clampWtile(x: Int): Int =
|
||||
if (x < 0) 0 else if (x >= world.width) world.width - 1 else x
|
||||
if (x < 0) 0 else if (x >= world?.width ?: 0) (world?.width ?: 0) - 1 else x
|
||||
|
||||
private fun clampHtile(x: Int): Int =
|
||||
if (x < 0) 0 else if (x >= world.height) world.height - 1 else x
|
||||
if (x < 0) 0 else if (x >= world?.height ?: 0) (world?.height ?: 0) - 1 else x
|
||||
|
||||
|
||||
var isNoClip: Boolean = false
|
||||
@@ -1324,10 +1369,13 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
|
||||
|
||||
private fun forEachOccupyingTileNum(consumer: (Int?) -> Unit) {
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val tiles = ArrayList<Int?>()
|
||||
for (y in hIntTilewiseHitbox.startY.toInt()..hIntTilewiseHitbox.endY.toInt()) {
|
||||
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
||||
tiles.add(world.getTileFromTerrain(x, y))
|
||||
tiles.add(world!!.getTileFromTerrain(x, y))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1335,10 +1383,13 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
}
|
||||
|
||||
private fun forEachOccupyingTile(consumer: (BlockProp?) -> Unit) {
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val tileProps = ArrayList<BlockProp?>()
|
||||
for (y in hIntTilewiseHitbox.startY.toInt()..hIntTilewiseHitbox.endY.toInt()) {
|
||||
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
||||
tileProps.add(BlockCodex[world.getTileFromTerrain(x, y)])
|
||||
tileProps.add(BlockCodex[world!!.getTileFromTerrain(x, y)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1346,6 +1397,9 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
}
|
||||
|
||||
private fun forEachOccupyingTilePos(hitbox: Hitbox, consumer: (BlockAddress) -> Unit) {
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
||||
hitbox.startX.div(TILE_SIZE).floor(),
|
||||
hitbox.startY.div(TILE_SIZE).floor(),
|
||||
@@ -1356,7 +1410,7 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
val tilePosList = ArrayList<BlockAddress>()
|
||||
for (y in newTilewiseHitbox.startY.toInt()..newTilewiseHitbox.endY.toInt()) {
|
||||
for (x in newTilewiseHitbox.startX.toInt()..newTilewiseHitbox.endX.toInt()) {
|
||||
tilePosList.add(LandUtil.getBlockAddr(this.world, x, y))
|
||||
tilePosList.add(LandUtil.getBlockAddr(world!!, x, y))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1364,26 +1418,32 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
|
||||
}
|
||||
|
||||
private fun forEachFeetTileNum(consumer: (Int?) -> Unit) {
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val tiles = ArrayList<Int?>()
|
||||
|
||||
// offset 1 pixel to the down so that friction would work
|
||||
val y = hitbox.endY.plus(1.0).div(TILE_SIZE).floorInt()
|
||||
|
||||
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
||||
tiles.add(world.getTileFromTerrain(x, y))
|
||||
tiles.add(world!!.getTileFromTerrain(x, y))
|
||||
}
|
||||
|
||||
return tiles.forEach(consumer)
|
||||
}
|
||||
|
||||
private fun forEachFeetTile(consumer: (BlockProp?) -> Unit) {
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val tileProps = ArrayList<BlockProp?>()
|
||||
|
||||
// offset 1 pixel to the down so that friction would work
|
||||
val y = hitbox.endY.plus(1.0).div(TILE_SIZE).floorInt()
|
||||
|
||||
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
||||
tileProps.add(BlockCodex[world.getTileFromTerrain(x, y)])
|
||||
tileProps.add(BlockCodex[world!!.getTileFromTerrain(x, y)])
|
||||
}
|
||||
|
||||
return tileProps.forEach(consumer)
|
||||
|
||||
Reference in New Issue
Block a user