fixing "roundworld anomaly": some actors won't render

This commit is contained in:
minjaesong
2019-05-31 04:10:00 +09:00
parent c50d07b541
commit a1ac9b177a
4 changed files with 69 additions and 44 deletions

View File

@@ -1389,31 +1389,28 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// FIXME test me: this extra IF statement is supposed to not draw actors that's outside of the camera.
// basic code without offsetX/Y DOES work, but obviously offsets are not tested.
if (hitbox.startX - offsetX in WorldCamera.x - hitbox.width - offsetX..WorldCamera.x + WorldCamera.width + offsetX &&
hitbox.endY + offsetY in WorldCamera.y - hitbox.height - offsetY..WorldCamera.y + WorldCamera.height + offsetY) {
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.startY - offsetY).toFloat(),
(scale).toFloat()
)
}
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.startY - offsetY).toFloat(),
(scale).toFloat()
)
}
else {
sprite.render(batch,
(hitbox.startX - offsetX).toFloat(),
(hitbox.startY - offsetY).toFloat(),
(scale).toFloat()
)
}
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.startY - offsetY).toFloat(),
(scale).toFloat()
)
}
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.startY - offsetY).toFloat(),
(scale).toFloat()
)
}
else {
sprite.render(batch,
(hitbox.startX - offsetX).toFloat(),
(hitbox.startY - offsetY).toFloat(),
(scale).toFloat()
)
}
}

View File

@@ -30,6 +30,7 @@ import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
import net.torvald.terrarum.ui.ConsoleWindow
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.TILE_SIZE
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera
@@ -475,8 +476,12 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
}
private var worldWidth: Double = 0.0
protected fun updateGame(delta: Float) {
val world = this.world as GameWorldExtension
worldWidth = world.width.toDouble() * TILE_SIZE
particlesActive = 0
@@ -570,6 +575,8 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
visibleActorsRenderMidTop = actorsRenderMidTop.filter { it.inScreen() }
visibleActorsRenderFront = actorsRenderFront.filter { it.inScreen() }
visibleActorsRenderOverlay=actorsRenderOverlay.filter { it.inScreen() }
//printdbg(this, "total visible actors: ${visibleActorsRenderMiddle.size}")
}
private fun repossessActor() {
@@ -716,31 +723,40 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
private fun distToActorSqr(a: ActorWithBody, p: ActorWithBody) =
min(// take min of normal position and wrapped (x < 0) position
(a.hitbox.centeredX - p.hitbox.centeredX).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).sqr(),
(a.hitbox.centeredX - p.hitbox.centeredX + world.width * CreateTileAtlas.TILE_SIZE).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).sqr(),
(a.hitbox.centeredX - p.hitbox.centeredX - world.width * CreateTileAtlas.TILE_SIZE).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).sqr()
(a.hitbox.centeredY - p.hitbox.centeredY).sqr(),
((a.hitbox.centeredX + world.width * CreateTileAtlas.TILE_SIZE) - p.hitbox.centeredX).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).sqr(),
((a.hitbox.centeredX - world.width * CreateTileAtlas.TILE_SIZE) - p.hitbox.centeredX).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).sqr()
)
private fun distToCameraSqr(a: ActorWithBody) =
min(
(a.hitbox.startX - WorldCamera.x).sqr() +
(a.hitbox.startY - WorldCamera.y).sqr(),
(a.hitbox.startX - WorldCamera.x + world.width * CreateTileAtlas.TILE_SIZE).sqr() +
(a.hitbox.startY - WorldCamera.y).sqr(),
(a.hitbox.startX - WorldCamera.x - world.width * CreateTileAtlas.TILE_SIZE).sqr() +
(a.hitbox.startY - WorldCamera.y).sqr()
(a.hitbox.centeredX - WorldCamera.xCentre).sqr() +
(a.hitbox.centeredY - WorldCamera.yCentre).sqr(),
((a.hitbox.centeredX + world.width * CreateTileAtlas.TILE_SIZE) - WorldCamera.xCentre).sqr() +
(a.hitbox.centeredY - WorldCamera.yCentre).sqr(),
((a.hitbox.centeredX - world.width * CreateTileAtlas.TILE_SIZE) - WorldCamera.xCentre).sqr() +
(a.hitbox.centeredY - WorldCamera.yCentre).sqr()
)
/** whether the actor is within screen */
// FIXME "roundworld anomaly"
private fun ActorWithBody.inScreen() =
distToCameraSqr(this) <=
(Terrarum.WIDTH.plus(this.hitbox.width.div(2)).
times(1 / screenZoom).sqr() +
Terrarum.HEIGHT.plus(this.hitbox.height.div(2)).
times(1 / screenZoom).sqr())
// y
this.hitbox.endY >= WorldCamera.y && this.hitbox.startY <= WorldCamera.yEnd
&&
// x: camera is on the right side of the seam
((this.hitbox.endX - worldWidth >= WorldCamera.x && this.hitbox.startX - worldWidth <= WorldCamera.xEnd) ||
// x: camera in on the left side of the seam
(this.hitbox.endX + worldWidth >= WorldCamera.x && this.hitbox.startX + worldWidth <= WorldCamera.xEnd) ||
// x: neither
(this.hitbox.endX >= WorldCamera.x && this.hitbox.startX <= WorldCamera.xEnd))
private val cameraWindowX = WorldCamera.x.toDouble()..WorldCamera.xEnd.toDouble()
private val cameraWindowY = WorldCamera.y.toDouble()..WorldCamera.yEnd.toDouble()
/** whether the actor is within update range */
private fun ActorWithBody.inUpdateRange() = distToCameraSqr(this) <= ACTOR_UPDATE_RANGE.sqr()

View File

@@ -49,7 +49,14 @@ open class FixtureBase(blockBox0: BlockBox, val blockBoxProps: BlockBoxProps = B
for (x in posX until posX + blockBox.width) {
for (y in posY until posY + blockBox.height) {
world.setTileTerrain(x, y, blockBox.collisionType)
if (blockBox.collisionType == BlockBox.ALLOW_MOVE_DOWN) {
// if the collision type is allow_move_down, only the top surface tile should be "the platform"
// lower part must not have such property (think of the table!)
// TODO does this ACTUALLY work ?!
world.setTileTerrain(x, y, if (y == posY) BlockBox.ALLOW_MOVE_DOWN else BlockBox.NO_COLLISION)
}
else
world.setTileTerrain(x, y, blockBox.collisionType)
}
}
@@ -67,7 +74,6 @@ open class FixtureBase(blockBox0: BlockBox, val blockBoxProps: BlockBoxProps = B
return true // TODO for the tests' sake, just get fucking spawned
// FIXME has "roundworld anomaly"; check 'ActorWithBody.inScreen()'
}
/**

View File

@@ -17,6 +17,10 @@ object WorldCamera {
private set
var y: Int = 0 // top position
private set
var xEnd: Int = 0 // right position
private set
var yEnd: Int = 0 // bottom position
private set
inline val gdxCamX: Float // centre position
get() = xCentre.toFloat()
inline val gdxCamY: Float// centre position
@@ -53,6 +57,8 @@ object WorldCamera {
world.height * TILE_SIZE - height - TILE_SIZE.toFloat()
)).floorInt().clampCameraY(world)
xEnd = x + width
yEnd = y + height
}
private fun Int.clampCameraY(world: GameWorld): Int {