mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
fixing the critical bug in active/dormant thingies, actor ID is now positive integer (I had to), class Actor is now shipped with ID generator, optimisation in add/removeActor
Former-commit-id: f743ecb27ba1cea05215889d7e1a77e10171cb8c Former-commit-id: 4b88f9711c34542a8a504682cffe79a2f8a43ed8
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import net.torvald.imagefont.GameFontBase
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.console.Authenticator
|
||||
import net.torvald.terrarum.gamecontroller.GameController
|
||||
@@ -146,31 +147,11 @@ constructor() : BasicGameState() {
|
||||
MapCamera.update(gc, delta)
|
||||
|
||||
// determine whether the inactive actor should be re-active
|
||||
actorContainerInactive.forEach { actor ->
|
||||
if (actor is Visible && distToActorSqr(actor, player) <= ACTOR_UPDATE_RANGE.sqr()) {
|
||||
addActor(actor)
|
||||
}
|
||||
}
|
||||
actorContainer.forEach { if (actorContainerInactive.contains(it))
|
||||
actorContainerInactive.remove(it)
|
||||
}
|
||||
wakeDormantActors()
|
||||
|
||||
actorContainer.forEach { actor -> // update actors
|
||||
// determine whether the actor should be active by their distance from the player
|
||||
// will put inactive actors to list specifically for them
|
||||
if (actor is Visible && distToActorSqr(actor, player) > ACTOR_UPDATE_RANGE.sqr()) {
|
||||
actorContainerInactive.add(actor)
|
||||
}
|
||||
else {
|
||||
// update our remaining active actors
|
||||
actor.update(gc, delta)
|
||||
if (actor is Visible) {
|
||||
actor.updateBodySprite(gc, delta)
|
||||
actor.updateGlowSprite(gc, delta)
|
||||
}
|
||||
}
|
||||
}
|
||||
actorContainerInactive.forEach { removeActor(it.referenceID) }
|
||||
// determine whether the actor should be active or dormant
|
||||
// also updates active actors
|
||||
inactivateDistantActors(gc, delta)
|
||||
|
||||
uiContainer.forEach { ui -> ui.update(gc, delta) }
|
||||
consoleHandler.update(gc, delta)
|
||||
@@ -184,12 +165,9 @@ constructor() : BasicGameState() {
|
||||
|
||||
private fun setAppTitle() {
|
||||
Terrarum.appgc.setTitle(
|
||||
"Simple Slick Game — FPS: "
|
||||
+ Terrarum.appgc.fps + " ("
|
||||
+ Terrarum.TARGET_INTERNAL_FPS.toString()
|
||||
+ ") — "
|
||||
+ memInUse.toString() + "M / "
|
||||
+ totalVMMem.toString() + "M")
|
||||
"Simple Slick Game" +
|
||||
" — FPS: ${Terrarum.appgc.fps} (${Terrarum.TARGET_INTERNAL_FPS})" +
|
||||
" — ${memInUse}M / ${totalVMMem}M")
|
||||
}
|
||||
|
||||
override fun render(gc: GameContainer, sbg: StateBasedGame, g: Graphics) {
|
||||
@@ -210,10 +188,7 @@ constructor() : BasicGameState() {
|
||||
|
||||
// draw actors
|
||||
actorContainer.forEach { actor ->
|
||||
if (actor is Visible &&
|
||||
distToActorSqr(actor, player) <= (Terrarum.WIDTH.plus(actor.hitbox.width.div(2)).sqr() +
|
||||
Terrarum.HEIGHT.plus(actor.hitbox.height.div(2)).sqr())
|
||||
) { // if visible and within screen
|
||||
if (actor is Visible && actor.inScreen()) { // if visible and within screen
|
||||
actor.drawBody(gc, g)
|
||||
}
|
||||
}
|
||||
@@ -235,10 +210,7 @@ constructor() : BasicGameState() {
|
||||
|
||||
// draw actor glows
|
||||
actorContainer.forEach { actor ->
|
||||
if (actor is Visible &&
|
||||
distToActorSqr(actor, player) <= (Terrarum.WIDTH.plus(actor.hitbox.width.div(2)).sqr() +
|
||||
Terrarum.HEIGHT.plus(actor.hitbox.height.div(2)).sqr())
|
||||
) {
|
||||
if (actor is Visible && actor.inScreen()) { // if visible and within screen
|
||||
actor.drawGlow(gc, g)
|
||||
}
|
||||
}
|
||||
@@ -255,6 +227,15 @@ constructor() : BasicGameState() {
|
||||
actor.hitbox.posX,
|
||||
actor.hitbox.pointedY + 4
|
||||
)
|
||||
|
||||
if (DEBUG_ARRAY) {
|
||||
g.color = GameFontBase.codeToCol["g"]
|
||||
g.drawString(
|
||||
i.toString(),
|
||||
actor.hitbox.posX,
|
||||
actor.hitbox.pointedY + 4 + 10
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -329,6 +310,45 @@ constructor() : BasicGameState() {
|
||||
notifinator.setAsOpening()
|
||||
}
|
||||
|
||||
fun wakeDormantActors() {
|
||||
// determine whether the inactive actor should be re-active
|
||||
var actorContainerSize = actorContainerInactive.size
|
||||
var i = 0
|
||||
while (i < actorContainerSize) { // loop thru actorContainerInactive
|
||||
val actor = actorContainerInactive[i]
|
||||
val actorIndex = i
|
||||
if (actor is Visible && actor.inUpdateRange()) {
|
||||
addActor(actor)
|
||||
actorContainerInactive.removeAt(actorIndex)
|
||||
actorContainerSize -= 1
|
||||
i-- // array removed 1 elem, so also decrement counter by 1
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
fun inactivateDistantActors(gc: GameContainer, delta: Int) {
|
||||
var actorContainerSize = actorContainer.size
|
||||
var i = 0
|
||||
// determine whether the actor should be active or dormant by its distance from the player
|
||||
// will put dormant actors to list specifically for them
|
||||
// if the actor is not to be dormant, update it
|
||||
while (i < actorContainerSize) { // loop thru actorContainer
|
||||
val actor = actorContainer[i]
|
||||
val actorIndex = i
|
||||
if (actor is Visible && !actor.inUpdateRange()) {
|
||||
actorContainerInactive.add(actor)
|
||||
actorContainer.removeAt(actorIndex)
|
||||
actorContainerSize -= 1
|
||||
i-- // array removed 1 elem, so also decrement counter by 1
|
||||
}
|
||||
else {
|
||||
actorContainer[i].update(gc, delta)
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
private val globalLightByTime: Int
|
||||
get() = getGradientColour(2).getRGB24().rgb24ExpandToRgb30()
|
||||
|
||||
@@ -342,8 +362,11 @@ constructor() : BasicGameState() {
|
||||
|
||||
fun Float.sqr() = this * this
|
||||
fun Int.sqr() = this * this
|
||||
private fun distToActorSqr(a: Visible, p: Player) =
|
||||
private fun distToActorSqr(a: Visible, p: Player): Float =
|
||||
(a.hitbox.centeredX - p.hitbox.centeredX).sqr() + (a.hitbox.centeredY - p.hitbox.centeredY).sqr()
|
||||
private fun Visible.inScreen() = distToActorSqr(this, player) <= (Terrarum.WIDTH.plus(this.hitbox.width.div(2)).times(1 / Terrarum.game.screenZoom).sqr() +
|
||||
Terrarum.HEIGHT.plus(this.hitbox.height.div(2)).times(1 / Terrarum.game.screenZoom).sqr())
|
||||
private fun Visible.inUpdateRange() = distToActorSqr(this, player) <= ACTOR_UPDATE_RANGE.sqr()
|
||||
/**
|
||||
* actorContainer extensions
|
||||
*/
|
||||
@@ -353,30 +376,33 @@ constructor() : BasicGameState() {
|
||||
else
|
||||
actorContainer.binarySearch(ID) >= 0
|
||||
|
||||
/**
|
||||
* Remove actor and sort the list
|
||||
*/
|
||||
fun removeActor(actor: Actor) = removeActor(actor.referenceID)
|
||||
|
||||
fun removeActor(ID: Int) {
|
||||
for (actor in actorContainer) {
|
||||
if (actor.referenceID == ID) {
|
||||
actorContainer.remove(actor)
|
||||
actorContainer.sort()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (ID == player.referenceID) throw IllegalArgumentException("Attemped to remove player.")
|
||||
// get index of the actor and delete by the index.
|
||||
// we can do this as the list is guaranteed to be sorted
|
||||
// and only contains unique values
|
||||
val indexToDelete = actorContainer.binarySearch(ID)
|
||||
if (indexToDelete >= 0) actorContainer.removeAt(indexToDelete)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add actor and sort the list
|
||||
*/
|
||||
fun addActor(other: Actor): Boolean {
|
||||
if (hasActor(other.referenceID)) return false
|
||||
actorContainer.add(other)
|
||||
actorContainer.sort()
|
||||
fun addActor(actor: Actor): Boolean {
|
||||
if (hasActor(actor.referenceID)) throw IllegalArgumentException("Actor with ID ${actor.referenceID} already exists.")
|
||||
actorContainer.add(actor)
|
||||
insertionSortLastElem(actorContainer) // we can do this as we only add one actor
|
||||
return true
|
||||
}
|
||||
|
||||
fun getActor(ID: Int): Actor {
|
||||
/**
|
||||
* Whether the game should display actorContainer elem number when F3 is on
|
||||
*/
|
||||
val DEBUG_ARRAY = false
|
||||
|
||||
fun getActorByID(ID: Int): Actor {
|
||||
if (actorContainer.size == 0) throw IllegalArgumentException("Actor with ID $ID does not exist.")
|
||||
|
||||
val index = actorContainer.binarySearch(ID)
|
||||
@@ -386,7 +412,25 @@ constructor() : BasicGameState() {
|
||||
return actorContainer[index]
|
||||
}
|
||||
|
||||
private fun insertionSortLastElem(arr: ArrayList<Actor>) {
|
||||
|
||||
// 'insertion sort' last element
|
||||
var x: Actor
|
||||
var j: Int
|
||||
var index: Int = arr.size - 1
|
||||
x = arr[index]
|
||||
j = index - 1
|
||||
while (j > 0 && arr[j].referenceID > x.referenceID) {
|
||||
arr[j + 1] = arr[j]
|
||||
j -= 1
|
||||
}
|
||||
arr[j + 1] = x
|
||||
}
|
||||
|
||||
private fun ArrayList<Actor>.binarySearch(actor: Actor) = this.binarySearch(actor.referenceID)
|
||||
|
||||
private fun ArrayList<Actor>.binarySearch(ID: Int): Int {
|
||||
// code from collections/Collections.kt
|
||||
var low = 0
|
||||
var high = actorContainer.size - 1
|
||||
|
||||
|
||||
@@ -114,9 +114,22 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
||||
|
||||
private lateinit var configDir: String
|
||||
|
||||
/**
|
||||
* 0xAA_BB_XXXX
|
||||
* AA: Major version
|
||||
* BB: Minor version
|
||||
* XXXX: Revision
|
||||
*
|
||||
* e.g. 0x02010034 can be translated as 2.1.52
|
||||
*/
|
||||
const val VERSION_RAW = 0x00020041
|
||||
const val VERSION_STRING: String =
|
||||
"${VERSION_RAW.ushr(24)}.${VERSION_RAW.and(0xFF0000).ushr(16)}.${VERSION_RAW.and(0xFFFF)}"
|
||||
const val NAME = "Terrarum"
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
try {
|
||||
appgc = AppGameContainer(Terrarum("Terrarum"))
|
||||
appgc = AppGameContainer(Terrarum(NAME))
|
||||
appgc.setDisplayMode(WIDTH, HEIGHT, false)
|
||||
|
||||
appgc.setTargetFrameRate(TARGET_INTERNAL_FPS)
|
||||
@@ -355,18 +368,6 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 0xAA_BB_XXXX
|
||||
* AA: Major version
|
||||
* BB: Minor version
|
||||
* XXXX: Revision
|
||||
*
|
||||
* e.g. 0x02010034 can be translated as 2.1.52
|
||||
*/
|
||||
const val VERSION_RAW = 0x00024000
|
||||
const val VERSION_STRING: String =
|
||||
"${VERSION_RAW.ushr(24)}.${VERSION_RAW.and(0xFF0000).ushr(16)}.${VERSION_RAW.and(0xFFFF)}"
|
||||
|
||||
fun main(args: Array<String>) = Terrarum.main(args)
|
||||
|
||||
fun setBlendMul() {
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.regex.Pattern
|
||||
*/
|
||||
object CommandInterpreter {
|
||||
|
||||
private val commandsNoAuth = arrayOf("auth", "qqq", "zoom", "setlocale", "getlocale", "help")
|
||||
private val commandsNoAuth = arrayOf("auth", "qqq", "zoom", "setlocale", "getlocale", "help", "version")
|
||||
|
||||
private val ccW = GameFontBase.colToCode["w"]
|
||||
private val ccG = GameFontBase.colToCode["g"]
|
||||
|
||||
@@ -52,7 +52,7 @@ class GetAV : ConsoleCommand {
|
||||
}
|
||||
else {
|
||||
// args[1] is actor ID
|
||||
val actor = Terrarum.game.getActor(args[1].toInt())
|
||||
val actor = Terrarum.game.getActorByID(args[1].toInt())
|
||||
val av = actor.actorValue
|
||||
val keyset = av.keySet
|
||||
|
||||
@@ -74,14 +74,14 @@ class GetAV : ConsoleCommand {
|
||||
val id = args[1].toInt()
|
||||
val av = args[2]
|
||||
echo.execute("$ccW$id.$ccM$av $ccW= $ccG" +
|
||||
Terrarum.game.getActor(id).actorValue[av] +
|
||||
Terrarum.game.getActorByID(id).actorValue[av] +
|
||||
" $ccO" +
|
||||
Terrarum.game.getActor(id).actorValue[av]!!.javaClass.simpleName
|
||||
Terrarum.game.getActorByID(id).actorValue[av]!!.javaClass.simpleName
|
||||
)
|
||||
println("id.av = " +
|
||||
Terrarum.game.getActor(id).actorValue[av] +
|
||||
Terrarum.game.getActorByID(id).actorValue[av] +
|
||||
" " +
|
||||
Terrarum.game.getActor(id).actorValue[av]!!.javaClass.simpleName
|
||||
Terrarum.game.getActorByID(id).actorValue[av]!!.javaClass.simpleName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class GetFactioning : ConsoleCommand {
|
||||
val echo = Echo()
|
||||
|
||||
fun printOutFactioning(id: Int) {
|
||||
val a = Terrarum.game.getActor(id)
|
||||
val a = Terrarum.game.getActorByID(id)
|
||||
if (a is Factionable) {
|
||||
echo.execute("$ccW== Faction assignment for $ccY${if (id == Player.PLAYER_REF_ID) "player" else id.toString()} $ccW==")
|
||||
println("[GetFactioning] == Faction assignment for '${if (id == Player.PLAYER_REF_ID) "player" else id.toString()}' ==")
|
||||
|
||||
@@ -77,7 +77,7 @@ internal class SetAV : ConsoleCommand {
|
||||
try {
|
||||
val id = args[1].toInt()
|
||||
val `val` = parseAVInput(args[3])
|
||||
val actor = Terrarum.game.getActor(id)
|
||||
val actor = Terrarum.game.getActorByID(id)
|
||||
|
||||
// check if av is number
|
||||
if (args[2].isNum()) {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package net.torvald.terrarum.console
|
||||
|
||||
import net.torvald.terrarum.VERSION_STRING
|
||||
import net.torvald.terrarum.Terrarum
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-04-23.
|
||||
*/
|
||||
class Version : ConsoleCommand {
|
||||
override fun execute(args: Array<String>) {
|
||||
Echo().execute(VERSION_STRING)
|
||||
Echo().execute("${Terrarum.NAME} ${Terrarum.VERSION_STRING}")
|
||||
}
|
||||
|
||||
override fun printUsage() {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.torvald.terrarum.gameactors
|
||||
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import org.newdawn.slick.GameContainer
|
||||
|
||||
/**
|
||||
@@ -19,6 +21,23 @@ abstract class Actor : Comparable<Actor> {
|
||||
|
||||
override fun equals(other: Any?) = referenceID == (other as Actor).referenceID
|
||||
override fun hashCode() = referenceID
|
||||
override fun toString() = "ID: ${hashCode()}"
|
||||
override fun toString() = 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
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* override var referenceID: Int = generateUniqueReferenceID()
|
||||
*/
|
||||
fun generateUniqueReferenceID(): Int {
|
||||
fun Int.abs() = if (this < 0) -this else this
|
||||
var ret: Int
|
||||
do {
|
||||
ret = HQRNG().nextInt().abs() // set new ID
|
||||
} while (Terrarum.game.hasActor(ret)) // check for collision
|
||||
return ret
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
internal var baseSpriteWidth: Int = 0
|
||||
internal var baseSpriteHeight: Int = 0
|
||||
|
||||
override var referenceID: Int = 0
|
||||
override var referenceID: Int = generateUniqueReferenceID()
|
||||
/**
|
||||
* Positions: top-left point
|
||||
*/
|
||||
@@ -137,10 +137,6 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
private var posAdjustY = 0
|
||||
|
||||
init {
|
||||
do {
|
||||
referenceID = HQRNG().nextInt() // set new ID
|
||||
} while (Terrarum.game.hasActor(referenceID)) // check for collision
|
||||
|
||||
map = Terrarum.game.map
|
||||
}
|
||||
|
||||
@@ -719,19 +715,13 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
fun Float.round() = Math.round(this).toFloat()
|
||||
fun Float.roundToInt(): Int = Math.round(this)
|
||||
fun Float.abs() = FastMath.abs(this)
|
||||
fun Int.abs() = if (this < 0) -this else this
|
||||
|
||||
companion object {
|
||||
|
||||
@Transient private val TSIZE = MapDrawer.TILE_SIZE
|
||||
private var AUTO_CLIMB_RATE = TSIZE / 8
|
||||
|
||||
private fun div16(x: Int): Int {
|
||||
if (x < 0) {
|
||||
throw IllegalArgumentException("div16: Positive integer only: " + x.toString())
|
||||
}
|
||||
return x and 0x7FFFFFFF shr 4
|
||||
}
|
||||
|
||||
private fun div16TruncateToMapWidth(x: Int): Int {
|
||||
if (x < 0)
|
||||
return 0
|
||||
@@ -750,13 +740,6 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
return y and 0x7FFFFFFF shr 4
|
||||
}
|
||||
|
||||
private fun mod16(x: Int): Int {
|
||||
if (x < 0) {
|
||||
throw IllegalArgumentException("mod16: Positive integer only: " + x.toString())
|
||||
}
|
||||
return x and 15
|
||||
}
|
||||
|
||||
private fun clampCeil(x: Float, ceil: Float): Float {
|
||||
return if (Math.abs(x) > ceil) ceil else x
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ object ItemPropCodex {
|
||||
if (code < ITEM_UNIQUE_MAX)
|
||||
return itemCodex[code]
|
||||
else {
|
||||
val a = Terrarum.game.getActor(code)
|
||||
val a = Terrarum.game.getActorByID(code)
|
||||
if (a is CanBeAnItem) return a.itemData
|
||||
|
||||
throw NullPointerException()
|
||||
|
||||
Reference in New Issue
Block a user