wires are now visible when not selected, but gets covered by the terrain to make them appear natural

This commit is contained in:
minjaesong
2021-08-20 15:48:20 +09:00
parent d318f0114c
commit 64271dc9ba
10 changed files with 91 additions and 99 deletions

View File

@@ -202,7 +202,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
return actor
}
//fun SortedArrayList<*>.binarySearch(actor: Actor) = this.toArrayList().binarySearch(actor.referenceID!!)
//fun SortedArrayList<*>.binarySearch(actor: Actor) = this.toArrayList().binarySearch(actor.referenceID)
//fun SortedArrayList<*>.binarySearch(ID: Int) = this.toArrayList().binarySearch(ID)
open fun removeActor(ID: Int) = removeActor(getActorByID(ID))
@@ -217,7 +217,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
open fun removeActor(actor: Actor?) {
if (actor == null) return
val indexToDelete = actorContainerActive.searchFor(actor.referenceID!!) { it.referenceID!! }
val indexToDelete = actorContainerActive.searchFor(actor.referenceID) { it.referenceID }
if (indexToDelete != null) {
actorContainerActive.remove(indexToDelete)
}
@@ -229,7 +229,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
open fun addNewActor(actor: Actor?) {
if (actor == null) return
if (theGameHasActor(actor.referenceID!!)) {
if (theGameHasActor(actor.referenceID)) {
throw Error("The actor $actor already exists in the game")
}
else {
@@ -241,18 +241,18 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
if (actorContainerActive.size == 0)
false
else
actorContainerActive.searchFor(ID) { it.referenceID!! } != null
actorContainerActive.searchFor(ID) { it.referenceID } != null
fun isInactive(ID: Int): Boolean =
if (actorContainerInactive.size == 0)
false
else
actorContainerInactive.searchFor(ID) { it.referenceID!! } != null
actorContainerInactive.searchFor(ID) { it.referenceID } != null
/**
* actorContainerActive extensions
*/
fun theGameHasActor(actor: Actor?) = if (actor == null) false else theGameHasActor(actor.referenceID!!)
fun theGameHasActor(actor: Actor?) = if (actor == null) false else theGameHasActor(actor.referenceID)
fun theGameHasActor(ID: Int): Boolean =
isActive(ID) || isInactive(ID)

View File

@@ -13,15 +13,21 @@ object ReferencingRanges {
val ACTORS = 0x1000_0000..0x7FFF_FFFF // too much actors
// Actor IDs are assigned in 256 groups, single actor can have 256 sub-actors
val ACTORS_BEHIND = 0x1000_0000..0x1FFF_FFFF // Rendered behind (e.g. tapestries)
val ACTORS_MIDDLE = 0x2000_0000..0x4FFF_FFFF // Regular actors (e.g. almost all of them)
val ACTORS_MIDTOP = 0x5000_0000..0x5FFF_FFFF // Special (e.g. weapon swung, bullets, dropped item, particles)
val ACTORS_FRONT = 0x6000_0000..0x6EFF_FFFF // Rendered front (e.g. fake tile)
// we're leaving last 65536 entries unassignable so that some special actors would use them
val ACTORS_BEHIND = 0x1000_0000..0x1FFE_FFFF // Rendered behind (e.g. tapestries)
val ACTORS_MIDDLE = 0x2000_0000..0x4FFE_FFFF // Regular actors (e.g. almost all of them)
val ACTORS_MIDTOP = 0x5000_0000..0x5FFE_FFFF // Special (e.g. weapon swung, bullets, dropped item, particles)
val ACTORS_FRONT = 0x6000_0000..0x6FFE_FFFF // Rendered front (e.g. fake tile)
val ACTORS_WIRES = 0x6FFF_0000..0x6FFF_FFFF // Rendered front--wires
val ACTORS_WIRES_HELPER = 0x7000_0000..0x7000_FFFF // Rendered overlay--wiring port icons and logic gates
// IDs doesn't effect the render order at all, but we're kinda enforcing these ID ranging.
// However, these two wire-related actor will break the rule. But as we want them to render on top of others
// in the same render orders, we're giveng them relatively high IDs for them.
val ACTORS_WIRES = 0x7FFF_E000..0x7FFF_EFFF // Rendered front--wires
val ACTORS_WIRES_HELPER = 0x7FFF_F000..0x7FFF_FF00 // Rendered overlay--wiring port icons and logic gates
val ACTORS_OVERLAY = 0x7001_0000..0x7FFF_FFFF // Rendered as screen overlay, not affected by light nor environment overlays
val ACTORS_OVERLAY = 0x7001_0000..0x7FFE_FFFF // Rendered as screen overlay, not affected by light nor environment overlays
// Actor ID 0x7FFF_FFFF is pre-assigned to the block cursor!
val PREFIX_DYNAMICITEM = "dyn"
val PREFIX_ACTORITEM = "actor"

View File

@@ -268,26 +268,22 @@ object Terrarum : Disposable {
inline val updateRate: Double
get() = 1.0 / Gdx.graphics.rawDeltaTime
private val noSubActorClass = hashSetOf(Actor.RenderOrder.WIRES)
/**
* Usage:
*
* override var referenceID: Int = generateUniqueReferenceID()
*/
fun generateUniqueReferenceID(renderOrder: Actor.RenderOrder): ActorID {
fun renderOrderToRange(renderOrder: Actor.RenderOrder) = when (renderOrder) {
Actor.RenderOrder.BEHIND -> Actor.RANGE_BEHIND
Actor.RenderOrder.MIDDLE -> Actor.RANGE_MIDDLE
Actor.RenderOrder.MIDTOP -> Actor.RANGE_MIDTOP
Actor.RenderOrder.FRONT -> Actor.RANGE_FRONT
Actor.RenderOrder.OVERLAY-> Actor.RANGE_OVERLAY
}
fun hasCollision(value: ActorID) =
try {
Terrarum.ingame?.theGameHasActor(value) == true ||
value < ItemCodex.ACTORID_MIN ||
value !in when (renderOrder) {
Actor.RenderOrder.BEHIND -> Actor.RANGE_BEHIND
Actor.RenderOrder.MIDDLE -> Actor.RANGE_MIDDLE
Actor.RenderOrder.MIDTOP -> Actor.RANGE_MIDTOP
Actor.RenderOrder.FRONT -> Actor.RANGE_FRONT
Actor.RenderOrder.OVERLAY-> Actor.RANGE_OVERLAY
Actor.RenderOrder.WIRES -> Actor.RANGE_WIRES
}
Terrarum.ingame?.theGameHasActor(value) == true
}
catch (gameNotInitialisedException: KotlinNullPointerException) {
false
@@ -295,7 +291,9 @@ object Terrarum : Disposable {
var ret: Int
do {
ret = HQRNG().nextInt().and(if (noSubActorClass.contains(renderOrder)) 0x7FFFFFFF else 0x7FFFFF00) // set new ID
val range = renderOrderToRange(renderOrder)
val size = range.last - range.first + 1
ret = (HQRNG().nextInt().rem(size) + range.first) and 0x7FFF_FF00 // make room for sub-actors
} while (hasCollision(ret)) // check for collision
return ret
}

View File

@@ -12,15 +12,14 @@ typealias ActorID = Int
*
* Created by minjaesong on 2015-12-31.
*/
abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable {
abstract class Actor(var renderOrder: RenderOrder, id: ActorID?) : Comparable<Actor>, Runnable {
enum class RenderOrder {
BEHIND, // tapestries, some particles (obstructed by terrain)
MIDDLE, // actors
MIDTOP, // bullets, thrown items
FRONT, // fake tiles
OVERLAY, // screen overlay, not affected by lightmap
WIRES
OVERLAY // screen overlay, not affected by lightmap
}
companion object {
@@ -29,9 +28,6 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
val RANGE_MIDTOP = ReferencingRanges.ACTORS_MIDTOP // 1
val RANGE_FRONT = ReferencingRanges.ACTORS_FRONT // 0.9375
val RANGE_OVERLAY= ReferencingRanges.ACTORS_OVERLAY // 0.9375
val RANGE_WIRES = ReferencingRanges.ACTORS_WIRES // 0.0002
val RANGE_WIRES_HELPER = ReferencingRanges.ACTORS_WIRES_HELPER // 0.0002
}
abstract fun update(delta: Float)
@@ -40,7 +36,7 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
* Valid RefID is equal to or greater than 16777216.
* @return Reference ID. (16777216-0x7FFF_FFFF)
*/
open var referenceID: ActorID = Terrarum.generateUniqueReferenceID(renderOrder) // in old time this was nullable without initialiser. If you're going to revert to that, add the reason why this should be nullable.
open var referenceID: ActorID = id ?: Terrarum.generateUniqueReferenceID(renderOrder) // in old time this was nullable without initialiser. If you're going to revert to that, add the reason why this should be nullable.
var actorValue = ActorValue(this) // FIXME cyclic reference on GSON
@Volatile var flagDespawn = false

View File

@@ -38,8 +38,8 @@ import kotlin.math.sign
*
* Created by minjaesong on 2016-01-13.
*/
open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties) :
Actor(renderOrder) {
open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties, id: ActorID? = null) :
Actor(renderOrder, id) {
@Transient val COLLISION_TEST_MODE = false

View File

@@ -10,9 +10,11 @@ import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.toInt
/**
* FIXME Constructor is super expensive
*
* Created by minjaesong on 2021-07-30.
*/
class WireActor(id: ActorID) : ActorWithBody(RenderOrder.WIRES, PhysProperties.IMMOBILE) {
class WireActor(id: ActorID) : ActorWithBody(RenderOrder.OVERLAY, PhysProperties.IMMOBILE, id) {
companion object {
val WIRE_NEARBY = arrayOf(
@@ -24,7 +26,6 @@ class WireActor(id: ActorID) : ActorWithBody(RenderOrder.WIRES, PhysProperties.I
}
init {
referenceID = id
setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, 0)
}

View File

@@ -54,7 +54,7 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
}
}
catch (e: GdxRuntimeException) {
printdbg(this, e.message)
printdbgerr(this, "Error initialising controller: ${e.message}")
e.stackTrace.forEach { printdbgerr(this, "\t$it") }
}
}

View File

@@ -63,23 +63,15 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
*/
//val ACTORCONTAINER_INITIAL_SIZE = 64
val PARTICLES_MAX = AppLoader.getConfigInt("maxparticles")
//val actorContainerActive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
//val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val particlesContainer = CircularArray<ParticleBase>(PARTICLES_MAX, true)
val uiContainer = UIContainer()
private val actorsRenderBehind = SortedArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMiddle = SortedArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMidTop = SortedArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderFront = SortedArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderOverlay= SortedArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
// these are required because actors always change their position
private var visibleActorsRenderBehind: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderMiddle: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderMidTop: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderFront: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderOverlay: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderBehind: ArrayList<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderMiddle: ArrayList<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderMidTop: ArrayList<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderFront: ArrayList<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderOverlay: ArrayList<ActorWithBody> = ArrayList(1)
//var screenZoom = 1.0f // definition moved to IngameInstance
//val ZOOM_MAXIMUM = 4.0f // definition moved to IngameInstance
@@ -196,12 +188,6 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
private set
var selectedWireRenderClass = ""
/**
* unlike faketiles which gets placed onto the world just like ordinary fixtures, wires are dynamically
* "rendered" into wire-actors, and we need to keep track of them in some way (and definitely NOT create
* 65536 actors all at once)
*/
private var allocatedWireActorsCount = 0
@@ -683,7 +669,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
if (uiFixture?.isClosed == true) { uiFixture = null }
// fill up visibleActorsRenderFront for wires
measureDebugTime("Ingame.WiresRenderAndDraw") {
measureDebugTime("Ingame.FillUpWiresBuffer") {
fillUpWiresBuffer()
}
@@ -701,19 +687,12 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
}
private val maxRenderableWires = ReferencingRanges.ACTORS_WIRES.endInclusive - ReferencingRanges.ACTORS_WIRES.first + 1
private val wireActorsContainer = Array(maxRenderableWires) { WireActor(ReferencingRanges.ACTORS_WIRES.first + it).let {
addNewActor(it)
/*^let*/ it
} }
private fun fillUpWiresBuffer() {
fun getOrMakeWireActor(num: Int): WireActor {
return try {
getActorByID(ReferencingRanges.ACTORS_WIRES.first + num) as WireActor
}
catch (_: IllegalArgumentException) {
val actor = WireActor(ReferencingRanges.ACTORS_WIRES.first + num)
addNewActor(actor)
actor
}
}
val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorInt()
val for_y_end = for_y_start + BlocksDrawer.tilesInVertical - 1
@@ -724,37 +703,46 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
for (y in for_y_start..for_y_end) {
for (x in for_x_start..for_x_end) {
if (wiringCounter >= maxRenderableWires) break
world.getAllWiresFrom(x, y)?.forEach {
val wireActor = wireActorsContainer[wiringCounter]
val wires = world.getAllWiresFrom(x, y)
wires?.forEach {
val wireActor = getOrMakeWireActor(wiringCounter)
wireActor.setWire(it, x, y)
if (WireCodex[it].renderClass == selectedWireRenderClass || selectedWireRenderClass == "wire_render_all") {
wireActor.isUpdate = true
wireActor.isVisible = true
wireActor.forceDormant = false
wireActor.setWire(it, x, y)
wireActor.renderOrder = Actor.RenderOrder.OVERLAY
}
else {
wireActor.isUpdate = false
wireActor.isVisible = false
wireActor.forceDormant = true
wireActor.renderOrder = Actor.RenderOrder.BEHIND
}
wireActor.isUpdate = true
wireActor.isVisible = true
wireActor.forceDormant = false
wiringCounter += 1
}
}
}
for (i in wiringCounter until maxRenderableWires) {
wireActorsContainer[i].isUpdate = false
wireActorsContainer[i].isVisible = false
wireActorsContainer[i].forceDormant = true
}
}
private fun filterVisibleActors() {
visibleActorsRenderBehind = actorsRenderBehind.filter { it.inScreen(world) }
visibleActorsRenderMiddle = actorsRenderMiddle.filter { it.inScreen(world) }
visibleActorsRenderMidTop = actorsRenderMidTop.filter { it.inScreen(world) }
visibleActorsRenderFront = actorsRenderFront.filter { it.inScreen(world) }
visibleActorsRenderOverlay=actorsRenderOverlay.filter { it.inScreen(world) }
visibleActorsRenderBehind.clear()
visibleActorsRenderMiddle.clear()
visibleActorsRenderMidTop.clear()
visibleActorsRenderFront.clear()
visibleActorsRenderOverlay.clear()
actorContainerActive.forEach {
if (it is ActorWithBody)
actorToRenderQueue(it).add(it)
}
}
private fun repossessActor() {
@@ -906,13 +894,13 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
private val cameraWindowX = WorldCamera.x.toDouble()..WorldCamera.xEnd.toDouble()
private val cameraWindowY = WorldCamera.y.toDouble()..WorldCamera.yEnd.toDouble()
private fun actorToRenderQueue(actor: ActorWithBody): SortedArrayList<ActorWithBody> {
private fun actorToRenderQueue(actor: ActorWithBody): ArrayList<ActorWithBody> {
return when (actor.renderOrder) {
Actor.RenderOrder.BEHIND -> actorsRenderBehind
Actor.RenderOrder.MIDDLE -> actorsRenderMiddle
Actor.RenderOrder.MIDTOP -> actorsRenderMidTop
Actor.RenderOrder.FRONT, Actor.RenderOrder.WIRES -> actorsRenderFront
Actor.RenderOrder.OVERLAY-> actorsRenderOverlay
Actor.RenderOrder.BEHIND -> visibleActorsRenderBehind
Actor.RenderOrder.MIDDLE -> visibleActorsRenderMiddle
Actor.RenderOrder.MIDTOP -> visibleActorsRenderMidTop
Actor.RenderOrder.FRONT -> visibleActorsRenderFront
Actor.RenderOrder.OVERLAY-> visibleActorsRenderOverlay
}
}
@@ -977,7 +965,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
throw Error("The actor $actor already exists in the game")
}
else {
if (actor.referenceID < ReferencingRanges.ACTORS_WIRES.first) {
if (actor.referenceID !in ReferencingRanges.ACTORS_WIRES && actor.referenceID !in ReferencingRanges.ACTORS_WIRES_HELPER) {
printdbg(this, "Adding actor $actor")
printStackTrace(this)
}
@@ -1096,11 +1084,11 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
}
override fun dispose() {
actorsRenderBehind.forEach { it.dispose() }
actorsRenderMiddle.forEach { it.dispose() }
actorsRenderMidTop.forEach { it.dispose() }
actorsRenderFront.forEach { it.dispose() }
actorsRenderOverlay.forEach { it.dispose() }
visibleActorsRenderBehind.forEach { it.dispose() }
visibleActorsRenderMiddle.forEach { it.dispose() }
visibleActorsRenderMidTop.forEach { it.dispose() }
visibleActorsRenderFront.forEach { it.dispose() }
visibleActorsRenderOverlay.forEach { it.dispose() }
uiContainer.forEach {
it?.handler?.dispose()

View File

@@ -8,6 +8,7 @@ import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.gameactors.ActorID
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.PhysProperties
import net.torvald.terrarum.gameitem.ItemID
@@ -32,9 +33,10 @@ open class FixtureBase(
renderOrder: RenderOrder = RenderOrder.MIDDLE,
val nameFun: () -> String,
val mainUI: UICanvas? = null,
val inventory: FixtureInventory? = null
val inventory: FixtureInventory? = null,
id: ActorID? = null
// disabling physics (not allowing the fixture to move) WILL make things easier in many ways
) : ActorWithBody(renderOrder, PhysProperties.IMMOBILE), CuedByTerrainChange {
) : ActorWithBody(renderOrder, PhysProperties.IMMOBILE, id), CuedByTerrainChange {
var blockBox: BlockBox = blockBox0
protected set // something like TapestryObject will want to redefine this

View File

@@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.ceilInt
import net.torvald.terrarum.gameactors.ActorID
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**