added "lightBox" to the interface Luminous; determines which area of the actor is luminous, and modified lightmapRenderer code accordingly

Former-commit-id: d7d9c33977b0fa2fd505cd070cf1cb6da0bdc0db
Former-commit-id: cf7c96f2ff891e07622ac0657811ea9de2cbd7c5
This commit is contained in:
Song Minjae
2016-06-20 13:14:41 +09:00
parent e926dd84db
commit e62f8feda5
15 changed files with 122 additions and 49 deletions

View File

@@ -3,4 +3,4 @@
|0..4095|Tiles|
|4096..32767|Items|
|32768..0x7FFFFFFF|Actors|
|0x80000000L..0xFFFFFFFFL|Faction|
|0x80000000..0xFFFFFFFF (all negative number)|Faction|

View File

@@ -14,7 +14,7 @@ abstract class Actor : Comparable<Actor>, Runnable {
/**
* Valid RefID is equal to or greater than 32768.
* @return Reference ID. (32768-0xFFFF_FFFF)
* @return Reference ID. (32768-0x7FFF_FFFF)
*/
abstract var referenceID: Int
@@ -22,10 +22,11 @@ abstract class Actor : Comparable<Actor>, Runnable {
override fun equals(other: Any?) = referenceID == (other as Actor).referenceID
override fun hashCode() = referenceID
override fun toString() = "Actor, " + if (actorValue.getAsString(AVKey.NAME).isNullOrEmpty())
"ID: ${hashCode()}"
else
"ID: ${hashCode()} (${actorValue.getAsString(AVKey.NAME)})"
override fun toString() = "Actor, " +
if (actorValue.getAsString(AVKey.NAME).isNullOrEmpty())
"ID: ${hashCode()}"
else
"ID: ${hashCode()} (${actorValue.getAsString(AVKey.NAME)})"
override fun compareTo(other: Actor): Int = (this.referenceID - other.referenceID).sign()
fun Int.sign(): Int = if (this > 0) 1 else if (this < 0) -1 else this

View File

@@ -18,7 +18,7 @@ import org.newdawn.slick.Graphics
*
* Created by minjaesong on 16-03-14.
*/
open class ActorWithBody constructor() : Actor(), Visible {
open class ActorWithBody : Actor(), Visible {
override var actorValue: ActorValue = ActorValue()
@@ -65,10 +65,11 @@ open class ActorWithBody constructor() : Actor(), Visible {
override var referenceID: Int = generateUniqueReferenceID()
/**
* Positions: top-left point
* * Position: top-left point
* * Unit: pixel
*/
override val hitbox = Hitbox(0.0,0.0,0.0,0.0)
@Transient val nextHitbox = Hitbox(0.0,0.0,0.0,0.0)
override val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
@Transient val nextHitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
/**
* Physical properties.
@@ -194,7 +195,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
internal var walledRight = false
init {
// any initialiser goes here...
}
/**
@@ -251,7 +252,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
physSleep = false
}
override fun update(gc: GameContainer, delta_t: Int) {
override fun update(gc: GameContainer, delta: Int) {
if (isUpdate) {
// make NoClip work for player
@@ -549,15 +550,14 @@ open class ActorWithBody constructor() : Actor(), Visible {
val ccdTryMax = 400
var ccdCount = 0
//if (ccdDelta.x.abs() >= SLEEP_THRE || ccdDelta.y.abs() >= SLEEP_THRE) { // regular situation
// CCD to delta while still colliding
while ((isColliding(CONTACT_AREA_LEFT) || isColliding(CONTACT_AREA_RIGHT)
while (((ccdDelta.x.abs() >= SLEEP_THRE) || (ccdDelta.y.abs() >= SLEEP_THRE))
&& (isColliding(CONTACT_AREA_LEFT) || isColliding(CONTACT_AREA_RIGHT)
|| isColliding(CONTACT_AREA_TOP) || isColliding(CONTACT_AREA_BOTTOM))
&& ccdCount < ccdTryMax
) {
nextHitbox.translate(ccdDelta)
ccdCount += 1
}
&& ccdCount < ccdTryMax
) {
nextHitbox.translate(ccdDelta)
ccdCount += 1
}
//}
/*else { // stuck while standing still
// CCD upward
@@ -586,7 +586,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
private fun applyNormalForce() {
if (!isNoCollideWorld) {
// axis Y
if (moveDelta.y >= 0) { // check downward
if (moveDelta.y > SLEEP_THRE) { // check downward
if (isColliding(CONTACT_AREA_BOTTOM) || isColliding(CONTACT_AREA_BOTTOM, 0, 1)) {
// the actor is hitting the ground
hitAndReflectY()
@@ -596,7 +596,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
grounded = false
}
}
else if (moveDelta.y < 0) { // check upward
else if (moveDelta.y < SLEEP_THRE) { // check upward
grounded = false
if (isColliding(CONTACT_AREA_TOP) || isColliding(CONTACT_AREA_TOP, 0, -1)) {
// the actor is hitting the ceiling
@@ -606,7 +606,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
}
}
// axis X
if (moveDelta.x > 0) { // check right
if (moveDelta.x > SLEEP_THRE) { // check right
if ((isColliding(CONTACT_AREA_RIGHT) && !isColliding(CONTACT_AREA_LEFT))
|| (isColliding(CONTACT_AREA_RIGHT, 1, 0) && !isColliding(CONTACT_AREA_LEFT, 0, -1))) {
// the actor is hitting the right wall
@@ -615,7 +615,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
else {
}
}
else if (moveDelta.x < 0) { // check left
else if (moveDelta.x < SLEEP_THRE) { // check left
// System.out.println("collidingleft");
if ((isColliding(CONTACT_AREA_LEFT) && !isColliding(CONTACT_AREA_RIGHT))
|| (isColliding(CONTACT_AREA_LEFT, -1, 0) && !isColliding(CONTACT_AREA_RIGHT, 1, 0))) {

View File

@@ -22,7 +22,7 @@ class DroppedItem constructor(itemID: Int) : ActorWithBody() {
ItemPropCodex.getProp(itemID).mass
}
override fun update(gc: GameContainer, delta_t: Int) {
override fun update(gc: GameContainer, delta: Int) {
}

View File

@@ -0,0 +1,26 @@
package net.torvald.terrarum.gameactors
import net.torvald.spriteanimation.SpriteAnimation
/**
* Created by minjaesong on 16-06-17.
*/
open class FixturesBase : ActorWithBody() {
/** Binary flags. Indicates that other actor (player) can pass in the direction.
* - (0: No collision)
* - 1: Top
* - 2: Right
* - 4: Bottom
* - 8: Left
* For example, flag of 4 is good for tables; player can stand on, which means
* downward movement is blocked within the fixtures' AABB.
*/
var collisionFlag: Int = 0
/**
* Normally if player is standing on the fixtures (with flag 4), pressing DOWN wiil allow
* player to get down. Setting this flag TRUE will block such movement (player cannot get down)
*/
var cannotPassThru = false
}

View File

@@ -0,0 +1,35 @@
package net.torvald.terrarum.gameactors
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.tileproperties.TileNameCode
import net.torvald.terrarum.tileproperties.TilePropCodex
/**
* Created by minjaesong on 16-06-17.
*/
class FixturesTikiTorch : FixturesBase(), Luminous {
override var luminosity: Int
get() = TilePropCodex.getProp(TileNameCode.TORCH).luminosity
set(value) {
throw UnsupportedOperationException()
}
override val lightBox: Hitbox = Hitbox(3.0, 0.0, 4.0, 3.0)
init {
isVisible = true
super.setDensity(1200)
setHitboxDimension(10, 24, 0, 0)
sprite = SpriteAnimation()
sprite!!.setDimension(10, 27)
sprite!!.setSpriteImage("res/graphics/sprites/fixtures/tiki_torch.png")
sprite!!.setDelay(200)
sprite!!.setRowsAndFrames(1, 1)
sprite!!.setAsVisible()
actorValue[AVKey.BASEMASS] = 1.0
actorValue[AVKey.LUMINOSITY] = TilePropCodex.getProp(TileNameCode.TORCH).luminosity
}
}

View File

@@ -8,17 +8,18 @@ interface Luminous {
/**
* Recommended implementation:
*
override var luminosity: Char
get() = if (actorValue.get("luminosity") != null) {
actorValue.get("luminosity") as Char
}
else {
0 as Char
}
override var luminosity: Int
get() = actorValue.getAsInt(AVKey.LUMINOSITY) ?: 0
set(value) {
actorValue.set("luminosity", value)
actorValue[AVKey.LUMINOSITY] = value
}
*/
var luminosity: Int
/**
* Arguments:
*
* Hitbox(x-offset, y-offset, width, height)
*/
val lightBox: Hitbox
}

View File

@@ -8,11 +8,11 @@ import org.newdawn.slick.Graphics
/**
* Created by minjaesong on 16-03-14.
*/
class PhysTestBall : ActorWithBody {
class PhysTestBall : ActorWithBody() {
private var color = Color.orange
constructor(): super() {
init {
setHitboxDimension(16, 16, 0, 0)
isVisible = true
actorValue[AVKey.BASEMASS] = 10.0

View File

@@ -17,7 +17,7 @@ import java.util.*
* Created by minjaesong on 16-03-14.
*/
class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, LandHolder {
class Player : ActorWithBody(), Controllable, Pocketed, Factionable, Luminous, LandHolder {
/**
* empirical value.
@@ -71,6 +71,8 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
set(value) {
actorValue[AVKey.LUMINOSITY] = value
}
override val lightBox: Hitbox
get() = Hitbox(0.0, 0.0, hitbox.width, hitbox.height) // use getter; dimension of the player may change by time.
companion object {
@Transient internal const val ACCEL_MULT_IN_FLIGHT: Double = 0.21 // TODO air control still too 'slippery' with 0.31, lower the value!
@@ -87,20 +89,19 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
* @throws SlickException
*/
@Throws(SlickException::class)
constructor() : super() {
init {
isVisible = true
referenceID = PLAYER_REF_ID
referenceID = PLAYER_REF_ID // forcibly set ID
super.setDensity(BASE_DENSITY)
}
override fun update(gc: GameContainer, delta_t: Int) {
override fun update(gc: GameContainer, delta: Int) {
if (vehicleRiding is Player)
throw RuntimeException("Attempted to 'ride' " + "player object.")
super.update(gc, delta_t)
super.update(gc, delta)
updateSprite(delta_t)
updateSprite(delta)
updateMovementControl()

View File

@@ -29,7 +29,7 @@ object LightmapRenderer {
* 8-Bit RGB values
*/
private val lightmap: Array<IntArray> = Array(LIGHTMAP_HEIGHT) { IntArray(LIGHTMAP_WIDTH) }
private val lanternMap = ArrayList<Lantern>(Terrarum.game.ACTORCONTAINER_INITIAL_SIZE)
private val lanternMap = ArrayList<Lantern>(Terrarum.game.ACTORCONTAINER_INITIAL_SIZE * 4)
private val AIR = TileNameCode.AIR
@@ -172,12 +172,19 @@ object LightmapRenderer {
// scan for luminous actors and store their lighting info to the lanterns
lanternMap.clear()
Terrarum.game.actorContainer.forEach { it ->
if (it is Luminous && it is Visible)
lanternMap.add(Lantern(
it.hitbox.centeredX.div(TSIZE).round(),
it.hitbox.centeredY.div(TSIZE).round(),
it.luminosity
))
if (it is Luminous && it is Visible) {
// put lanterns to the area the luminantBox is occupying
val lightBox = it.lightBox
val lightBoxX = it.hitbox.posX + lightBox.posX
val lightBoxY = it.hitbox.posY + lightBox.posY
val lightBoxW = lightBox.width
val lightBoxH = lightBox.height
for (y in lightBoxY.div(TSIZE).floorInt()
..lightBoxY.plus(lightBoxH).div(TSIZE).floorInt())
for (x in lightBoxX.div(TSIZE).floorInt()
..lightBoxX.plus(lightBoxW).div(TSIZE).floorInt())
lanternMap.add(Lantern(x, y, it.luminosity))
}
}
try {
@@ -623,6 +630,7 @@ object LightmapRenderer {
private fun Float.sqrt() = FastMath.sqrt(this)
private fun Float.inv() = 1f / this
fun Float.floor() = FastMath.floor(this)
fun Double.floorInt() = Math.floor(this).toInt()
fun Float.round(): Int = Math.round(this)
fun Double.round(): Int = Math.round(this).toInt()
fun Float.ceil() = FastMath.ceil(this)