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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -3,4 +3,4 @@
|0..4095|Tiles| |0..4095|Tiles|
|4096..32767|Items| |4096..32767|Items|
|32768..0x7FFFFFFF|Actors| |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. * 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 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 equals(other: Any?) = referenceID == (other as Actor).referenceID
override fun hashCode() = referenceID override fun hashCode() = referenceID
override fun toString() = "Actor, " + if (actorValue.getAsString(AVKey.NAME).isNullOrEmpty()) override fun toString() = "Actor, " +
"ID: ${hashCode()}" if (actorValue.getAsString(AVKey.NAME).isNullOrEmpty())
else "ID: ${hashCode()}"
"ID: ${hashCode()} (${actorValue.getAsString(AVKey.NAME)})" else
"ID: ${hashCode()} (${actorValue.getAsString(AVKey.NAME)})"
override fun compareTo(other: Actor): Int = (this.referenceID - other.referenceID).sign() 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 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. * Created by minjaesong on 16-03-14.
*/ */
open class ActorWithBody constructor() : Actor(), Visible { open class ActorWithBody : Actor(), Visible {
override var actorValue: ActorValue = ActorValue() override var actorValue: ActorValue = ActorValue()
@@ -65,10 +65,11 @@ open class ActorWithBody constructor() : Actor(), Visible {
override var referenceID: Int = generateUniqueReferenceID() 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) override val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
@Transient val nextHitbox = Hitbox(0.0,0.0,0.0,0.0) @Transient val nextHitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
/** /**
* Physical properties. * Physical properties.
@@ -194,7 +195,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
internal var walledRight = false internal var walledRight = false
init { init {
// any initialiser goes here...
} }
/** /**
@@ -251,7 +252,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
physSleep = false physSleep = false
} }
override fun update(gc: GameContainer, delta_t: Int) { override fun update(gc: GameContainer, delta: Int) {
if (isUpdate) { if (isUpdate) {
// make NoClip work for player // make NoClip work for player
@@ -549,15 +550,14 @@ open class ActorWithBody constructor() : Actor(), Visible {
val ccdTryMax = 400 val ccdTryMax = 400
var ccdCount = 0 var ccdCount = 0
//if (ccdDelta.x.abs() >= SLEEP_THRE || ccdDelta.y.abs() >= SLEEP_THRE) { // regular situation while (((ccdDelta.x.abs() >= SLEEP_THRE) || (ccdDelta.y.abs() >= SLEEP_THRE))
// CCD to delta while still colliding && (isColliding(CONTACT_AREA_LEFT) || isColliding(CONTACT_AREA_RIGHT)
while ((isColliding(CONTACT_AREA_LEFT) || isColliding(CONTACT_AREA_RIGHT)
|| isColliding(CONTACT_AREA_TOP) || isColliding(CONTACT_AREA_BOTTOM)) || isColliding(CONTACT_AREA_TOP) || isColliding(CONTACT_AREA_BOTTOM))
&& ccdCount < ccdTryMax && ccdCount < ccdTryMax
) { ) {
nextHitbox.translate(ccdDelta) nextHitbox.translate(ccdDelta)
ccdCount += 1 ccdCount += 1
} }
//} //}
/*else { // stuck while standing still /*else { // stuck while standing still
// CCD upward // CCD upward
@@ -586,7 +586,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
private fun applyNormalForce() { private fun applyNormalForce() {
if (!isNoCollideWorld) { if (!isNoCollideWorld) {
// axis Y // 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)) { if (isColliding(CONTACT_AREA_BOTTOM) || isColliding(CONTACT_AREA_BOTTOM, 0, 1)) {
// the actor is hitting the ground // the actor is hitting the ground
hitAndReflectY() hitAndReflectY()
@@ -596,7 +596,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
grounded = false grounded = false
} }
} }
else if (moveDelta.y < 0) { // check upward else if (moveDelta.y < SLEEP_THRE) { // check upward
grounded = false grounded = false
if (isColliding(CONTACT_AREA_TOP) || isColliding(CONTACT_AREA_TOP, 0, -1)) { if (isColliding(CONTACT_AREA_TOP) || isColliding(CONTACT_AREA_TOP, 0, -1)) {
// the actor is hitting the ceiling // the actor is hitting the ceiling
@@ -606,7 +606,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
} }
} }
// axis X // axis X
if (moveDelta.x > 0) { // check right if (moveDelta.x > SLEEP_THRE) { // check right
if ((isColliding(CONTACT_AREA_RIGHT) && !isColliding(CONTACT_AREA_LEFT)) if ((isColliding(CONTACT_AREA_RIGHT) && !isColliding(CONTACT_AREA_LEFT))
|| (isColliding(CONTACT_AREA_RIGHT, 1, 0) && !isColliding(CONTACT_AREA_LEFT, 0, -1))) { || (isColliding(CONTACT_AREA_RIGHT, 1, 0) && !isColliding(CONTACT_AREA_LEFT, 0, -1))) {
// the actor is hitting the right wall // the actor is hitting the right wall
@@ -615,7 +615,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
else { else {
} }
} }
else if (moveDelta.x < 0) { // check left else if (moveDelta.x < SLEEP_THRE) { // check left
// System.out.println("collidingleft"); // System.out.println("collidingleft");
if ((isColliding(CONTACT_AREA_LEFT) && !isColliding(CONTACT_AREA_RIGHT)) if ((isColliding(CONTACT_AREA_LEFT) && !isColliding(CONTACT_AREA_RIGHT))
|| (isColliding(CONTACT_AREA_LEFT, -1, 0) && !isColliding(CONTACT_AREA_RIGHT, 1, 0))) { || (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 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: * Recommended implementation:
* *
override var luminosity: Char override var luminosity: Int
get() = if (actorValue.get("luminosity") != null) { get() = actorValue.getAsInt(AVKey.LUMINOSITY) ?: 0
actorValue.get("luminosity") as Char
}
else {
0 as Char
}
set(value) { set(value) {
actorValue.set("luminosity", value) actorValue[AVKey.LUMINOSITY] = value
} }
*/ */
var luminosity: Int 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. * Created by minjaesong on 16-03-14.
*/ */
class PhysTestBall : ActorWithBody { class PhysTestBall : ActorWithBody() {
private var color = Color.orange private var color = Color.orange
constructor(): super() { init {
setHitboxDimension(16, 16, 0, 0) setHitboxDimension(16, 16, 0, 0)
isVisible = true isVisible = true
actorValue[AVKey.BASEMASS] = 10.0 actorValue[AVKey.BASEMASS] = 10.0

View File

@@ -17,7 +17,7 @@ import java.util.*
* Created by minjaesong on 16-03-14. * 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. * empirical value.
@@ -71,6 +71,8 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
set(value) { set(value) {
actorValue[AVKey.LUMINOSITY] = 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 { 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! @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
*/ */
@Throws(SlickException::class) init {
constructor() : super() {
isVisible = true isVisible = true
referenceID = PLAYER_REF_ID referenceID = PLAYER_REF_ID // forcibly set ID
super.setDensity(BASE_DENSITY) super.setDensity(BASE_DENSITY)
} }
override fun update(gc: GameContainer, delta_t: Int) { override fun update(gc: GameContainer, delta: Int) {
if (vehicleRiding is Player) if (vehicleRiding is Player)
throw RuntimeException("Attempted to 'ride' " + "player object.") throw RuntimeException("Attempted to 'ride' " + "player object.")
super.update(gc, delta_t) super.update(gc, delta)
updateSprite(delta_t) updateSprite(delta)
updateMovementControl() updateMovementControl()

View File

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

View File

@@ -0,0 +1 @@
*.{psd,tga,ogg} filter=lfs diff=lfs merge=lfs -text