tiles with light level <= 1 will be rendered as black square, phys support for non-self-moving bodies (e.g. balls)

Former-commit-id: 5611e2d89f4601e57d014c45f0479600778217f6
Former-commit-id: d900c0733a6d1dcbd9aaed8e9f7f1671c3866624
This commit is contained in:
Song Minjae
2017-01-23 19:06:12 +09:00
parent ba3e1fe8fc
commit 92cc8ff94b
13 changed files with 236 additions and 137 deletions

View File

@@ -16,6 +16,7 @@ import java.util.*
/**
* Humanoid actor class to provide same controlling function (such as work, jump)
* Also applies unreal air friction for movement control
*
* Created by minjaesong on 16-10-24.
*/

View File

@@ -10,6 +10,7 @@ import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.gamecontroller.Key
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.mapdrawer.FeaturesDrawer.TILE_SIZE
import net.torvald.terrarum.mapdrawer.MapCamera
import net.torvald.terrarum.tileproperties.Tile
import net.torvald.terrarum.tileproperties.TileProp
import org.dyn4j.Epsilon
@@ -19,17 +20,19 @@ import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
import org.newdawn.slick.Image
import java.util.*
import kotlin.reflect.jvm.internal.impl.resolve.constants.DoubleValue
/**
* Base class for every actor that has animated sprites. This includes furnishings, paintings, gadgets, etc.
* Also has all the physics
*
* @param renderOrder Rendering order (BEHIND, MIDDLE, MIDTOP, FRONT)
* @param physics
* @param immobileBody use realistic air friction (1/1000 of "unrealistic" canonical setup)
* @param physics use physics simulation
*
* Created by minjaesong on 16-01-13.
*/
open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : ActorVisible(renderOrder) {
open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = false, physics: Boolean = true) : ActorVisible(renderOrder) {
/** !! ActorValue macros are on the very bottom of the source !! **/
@@ -343,6 +346,8 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
velocity += acc.times(speedMultByTile)
}
private val bounceDampenVelThreshold = 0.5
override fun update(gc: GameContainer, delta: Int) {
if (isUpdate && !flagDespawn) {
@@ -388,7 +393,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
}
setHorizontalFriction()
if (isPlayerNoClip) { // TODO also hanging on the rope, etc.
if (immobileBody || isPlayerNoClip) { // TODO also hanging on the rope, etc.
setVerticalFriction()
}
@@ -424,28 +429,28 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
// decide whether to ignore walkX
if (!(isCollidingSide(hitbox, COLLIDING_LEFT) && walkX < 0)
|| !(isCollidingSide(hitbox, COLLIDING_RIGHT) && walkX > 0)
) {
) {
moveDelta.x = veloX + walkX
}
// decide whether to ignore walkY
if (!(isCollidingSide(hitbox, COLLIDING_TOP) && walkY < 0)
|| !(isCollidingSide(hitbox, COLLIDING_BOTTOM) && walkY > 0)
) {
) {
moveDelta.y = veloY + walkY
}
}
else {
if (!isCollidingSide(hitbox, COLLIDING_LEFT)
|| !isCollidingSide(hitbox, COLLIDING_RIGHT)
) {
) {
moveDelta.x = veloX
}
// decide whether to ignore walkY
if (!isCollidingSide(hitbox, COLLIDING_TOP)
|| !isCollidingSide(hitbox, COLLIDING_BOTTOM)
) {
) {
moveDelta.y = veloY
}
}
@@ -771,6 +776,13 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
return contactAreaCounter
}
private fun getTileFriction(tile: Int) =
if (immobileBody && tile == Tile.AIR)
TileCodex[Tile.AIR].friction.frictionToMult().div(1000)
.times(if (!grounded) elasticity else 1.0)
else
TileCodex[tile].friction.frictionToMult()
/** about stopping
* for about get moving, see updateMovementControl */
private fun setHorizontalFriction() {
@@ -778,7 +790,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
BASE_FRICTION * TileCodex[Tile.STONE].friction.frictionToMult()
else {
// TODO status quo if !submerged else linearBlend(feetFriction, bodyFriction, submergedRatio)
BASE_FRICTION * (if (grounded) feetFriction else bodyFriction).frictionToMult()
BASE_FRICTION * if (grounded) feetFriction else bodyFriction
}
if (veloX < 0) {
@@ -806,7 +818,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
val friction = if (isPlayerNoClip)
BASE_FRICTION * TileCodex[Tile.STONE].friction.frictionToMult()
else
BASE_FRICTION * bodyFriction.frictionToMult()
BASE_FRICTION * bodyFriction
if (veloY < 0) {
veloY += friction
@@ -859,22 +871,24 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
).toDouble()
internal val bodyFriction: Int
internal val bodyFriction: Double
get() {
var friction = 0
forEachOccupyingTile { // get max friction
if (it?.friction ?: TileCodex[Tile.AIR].friction > friction)
friction = it?.friction ?: TileCodex[Tile.AIR].friction
var friction = 0.0
forEachOccupyingTileNum {
// get max friction
if (getTileFriction(it ?: Tile.AIR) > friction)
friction = getTileFriction(it ?: Tile.AIR)
}
return friction
}
internal val feetFriction: Int
internal val feetFriction: Double
get() {
var friction = 0
forEachFeetTile { // get max friction
if (it?.friction ?: TileCodex[Tile.AIR].friction > friction)
friction = it?.friction ?: TileCodex[Tile.AIR].friction
var friction = 0.0
forEachFeetTileNum {
// get max friction
if (getTileFriction(it ?: Tile.AIR) > friction)
friction = getTileFriction(it ?: Tile.AIR)
}
return friction
@@ -885,7 +899,8 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
internal val bodyViscosity: Int
get() {
var viscosity = 0
forEachOccupyingTile { // get max viscosity
forEachOccupyingTile {
// get max viscosity
if (it?.viscosity ?: 0 > viscosity)
viscosity = it?.viscosity ?: 0
}
@@ -895,7 +910,8 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
internal val feetViscosity: Int
get() {
var viscosity = 0
forEachFeetTile { // get max viscosity
forEachFeetTile {
// get max viscosity
if (it?.viscosity ?: 0 > viscosity)
viscosity = it?.viscosity ?: 0
}
@@ -921,9 +937,9 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
get() {
if (!isPlayerNoClip) {
val notSubmergedAccel = if (grounded)
feetFriction.frictionToMult()
feetFriction
else
bodyFriction.frictionToMult()
bodyFriction
val normalisedViscocity = bodyViscosity.viscosityToMult()
return interpolateLinear(submergedRatio, notSubmergedAccel, normalisedViscocity)
@@ -992,7 +1008,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
private fun updateHitbox() = hitbox.reassign(nextHitbox)
override open fun drawGlow(g: Graphics) {
override fun drawGlow(g: Graphics) {
if (isVisible && spriteGlow != null) {
blendLightenOnly()
@@ -1033,25 +1049,12 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
)
}
}
// debug hitbox
if (KeyToggler.isOn(Key.F11)) {
g.color = Color(1f, 0f, 1f, 1f)
blendNormal()
g.lineWidth = 1f
g.drawRect(
hitbox.posX.toFloat(),
hitbox.posY.toFloat(),
hitbox.width.toFloat(),
hitbox.height.toFloat()
)
}
}
override open fun drawBody(g: Graphics) {
if (isVisible && sprite != null) {
private val halfWorldW = world.width.times(TILE_SIZE).ushr(1)
override fun drawBody(g: Graphics) {
if (isVisible && sprite != null) {
when (drawMode) {
BLEND_NORMAL -> blendNormal()
@@ -1282,7 +1285,9 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
var avBaseScale: Double // use canonical "scale" for apparent scale (base * buff)
get() = actorValue.getAsDouble(AVKey.SCALE) ?: 1.0
set(value) { actorValue[AVKey.SCALE] = value }
set(value) {
actorValue[AVKey.SCALE] = value
}
/** Apparent strength */
var avStrength: Double
get() = (actorValue.getAsDouble(AVKey.STRENGTH) ?: 0.0) *
@@ -1294,10 +1299,14 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
}
var avBaseStrength: Double?
get() = actorValue.getAsDouble(AVKey.STRENGTH)
set(value) { actorValue[AVKey.STRENGTH] = value!! }
set(value) {
actorValue[AVKey.STRENGTH] = value!!
}
var avBaseMass: Double
get() = actorValue.getAsDouble(AVKey.BASEMASS) ?: MASS_DEFAULT
set(value) { actorValue[AVKey.BASEMASS] = value }
set(value) {
actorValue[AVKey.BASEMASS] = value
}
val avAcceleration: Double
get() = actorValue.getAsDouble(AVKey.ACCEL)!! *
actorValue.getAsDouble(AVKey.ACCELBUFF)!! *

View File

@@ -5,7 +5,8 @@ import net.torvald.spriteanimation.SpriteAnimation
/**
* Created by minjaesong on 16-06-17.
*/
open class FixtureBase(physics: Boolean = true) : ActorWithSprite(ActorOrder.BEHIND, physics) {
open class FixtureBase(physics: Boolean = true) :
ActorWithSprite(ActorOrder.BEHIND, immobileBody = true, physics = physics) {
/**
* 0: Open
* 1: Blocked

View File

@@ -11,7 +11,7 @@ import org.newdawn.slick.Input
*
* Created by minjaesong on 16-10-10.
*/
open class HistoricalFigure(val born: GameDate, val dead: GameDate? = null) : ActorWithSprite(ActorOrder.MIDDLE) {
open class HistoricalFigure(val born: GameDate, val dead: GameDate? = null, realAirFriction: Boolean = false) : ActorWithSprite(ActorOrder.MIDDLE, realAirFriction) {
init {
this.actorValue["_bornyear"] = born.year

View File

@@ -10,7 +10,7 @@ import org.newdawn.slick.Graphics
/**
* Created by minjaesong on 16-03-05.
*/
class PhysTestBall : ActorWithSprite(ActorOrder.MIDDLE) {
class PhysTestBall : ActorWithSprite(ActorOrder.MIDDLE, immobileBody = true) {
private var color = Color.orange