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:
minjaesong
2018-10-05 23:40:03 +09:00
parent 5641910036
commit 83fd44df4c
36 changed files with 344 additions and 268 deletions

View File

@@ -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)