From 54b52b1b6e7f6a6ae4cf807e991a7786e1cd2ac3 Mon Sep 17 00:00:00 2001 From: Song Minjae Date: Sun, 22 Jan 2017 04:13:45 +0900 Subject: [PATCH] more efficient particles Former-commit-id: 56dad88ecd715ad6e357e33b903851a47a358dcd Former-commit-id: c85c0b759a447c0461563d98156f59879fa95db2 --- src/net/torvald/aa/KDHeapifiedTree.kt | 2 +- src/net/torvald/colourutil/CIEXYZUtil.kt | 2 +- src/net/torvald/gadgets/HistoryArray.kt | 2 +- src/net/torvald/terrarum/CircularArray.kt | 49 ++++++++++++++ src/net/torvald/terrarum/StateBlurTest.kt | 2 +- src/net/torvald/terrarum/StateInGame.kt | 29 ++++++--- src/net/torvald/terrarum/StateNoiseTexGen.kt | 2 +- src/net/torvald/terrarum/console/AVTracker.kt | 2 +- .../torvald/terrarum/console/ActorsList.kt | 2 +- src/net/torvald/terrarum/console/Inventory.kt | 2 +- src/net/torvald/terrarum/console/SetScale.kt | 2 +- .../torvald/terrarum/console/SpawnTapestry.kt | 2 +- .../terrarum/console/SpawnTikiTorch.kt | 2 +- .../terrarum/debuggerapp/ActorValueTracker.kt | 2 +- .../terrarum/debuggerapp/ActorsLister.kt | 2 +- .../terrarum/gameactors/ActorVisible.kt | 2 +- .../terrarum/gameactors/ParticleBase.kt | 65 ++++++++++--------- .../terrarum/gameactors/ParticleTestRain.kt | 10 +-- .../terrarum/gameactors/TapestryObject.kt | 2 +- .../torvald/terrarum/mapdrawer/MapCamera.kt | 2 +- .../terrarum/ui/BasicDebugInfoWindow.kt | 2 + .../torvald/terrarum/weather/WeatherMixer.kt | 14 ++-- 22 files changed, 135 insertions(+), 66 deletions(-) create mode 100644 src/net/torvald/terrarum/CircularArray.kt diff --git a/src/net/torvald/aa/KDHeapifiedTree.kt b/src/net/torvald/aa/KDHeapifiedTree.kt index fd853adbc..ae6943a84 100644 --- a/src/net/torvald/aa/KDHeapifiedTree.kt +++ b/src/net/torvald/aa/KDHeapifiedTree.kt @@ -13,7 +13,7 @@ import java.util.* * -- I couldn't observe any significant boost in performance but this one seems * to give 3-4 more frames per second. * - * Created by SKYHi14 on 2017-01-02. + * Created by minjaesong on 2017-01-02. * * * Remarks: diff --git a/src/net/torvald/colourutil/CIEXYZUtil.kt b/src/net/torvald/colourutil/CIEXYZUtil.kt index ac873ff2e..bb4f5d156 100644 --- a/src/net/torvald/colourutil/CIEXYZUtil.kt +++ b/src/net/torvald/colourutil/CIEXYZUtil.kt @@ -4,7 +4,7 @@ import com.jme3.math.FastMath import org.newdawn.slick.Color /** - * Created by SKYHi14 on 2017-01-12. + * Created by minjaesong on 2017-01-12. */ object CIEXYZUtil { fun Color.brighterXYZ(scale: Float): Color { diff --git a/src/net/torvald/gadgets/HistoryArray.kt b/src/net/torvald/gadgets/HistoryArray.kt index 62d9b4144..49b2e09d8 100644 --- a/src/net/torvald/gadgets/HistoryArray.kt +++ b/src/net/torvald/gadgets/HistoryArray.kt @@ -47,7 +47,7 @@ class HistoryArray(val historyMax: Int) { /** * Iterate from latest to oldest */ - fun forEach(action: Consumer) = history.forEach(action) + fun forEach(action: (T?) -> Unit) = history.forEach(action) val latest: T? get() = this[0] diff --git a/src/net/torvald/terrarum/CircularArray.kt b/src/net/torvald/terrarum/CircularArray.kt new file mode 100644 index 000000000..1452f6cb6 --- /dev/null +++ b/src/net/torvald/terrarum/CircularArray.kt @@ -0,0 +1,49 @@ +package net.torvald.terrarum + + +/** + * Notes for particle storage: + * Particles does not need to be removed, just let it overwrite as their operation is rather + * lightweight. So, just flagDespawn = true if it need to be "deleted" so that it won't update + * anymore. + * + * Created by minjaesong on 2017-01-22. + */ +class CircularArray(val size: Int) { + + private val buffer: Array = arrayOfNulls(size) as Array + private var tail: Int = 0 + private var head: Int = 0 + + val elemCount: Int + get() = if (tail >= head) tail - head else size + + fun add(item: T) { + buffer[tail] = item // overwrites oldest item when eligible + tail = (tail + 1) % size + if (tail == head) { + head = (head + 1) % size + } + } + + fun forEach(action: (T) -> Unit) { + if (tail >= head) { // queue not full + (head..tail - 1).map { buffer[it] }.forEach { action(it) } + } + else { // queue full + (0..size - 1).map { buffer[(it + head) % size] }.forEach { action(it) } + } + } + + fun forEachConcurrent(action: (T) -> Unit) { + TODO() + } + + fun forEachConcurrentWaitFor(action: (T) -> Unit) { + TODO() + } + + override fun toString(): String { + return "CircularArray(size=" + buffer.size + ", head=" + head + ", tail=" + tail + ")" + } +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/StateBlurTest.kt b/src/net/torvald/terrarum/StateBlurTest.kt index ad870e754..f1072e743 100644 --- a/src/net/torvald/terrarum/StateBlurTest.kt +++ b/src/net/torvald/terrarum/StateBlurTest.kt @@ -12,7 +12,7 @@ import java.nio.ByteOrder /** * Software rendering test for blur * - * Created by SKYHi14 on 2017-01-12. + * Created by minjaesong on 2017-01-12. */ class StateBlurTest : BasicGameState() { diff --git a/src/net/torvald/terrarum/StateInGame.kt b/src/net/torvald/terrarum/StateInGame.kt index 6d4f292bd..dabb4b2ac 100644 --- a/src/net/torvald/terrarum/StateInGame.kt +++ b/src/net/torvald/terrarum/StateInGame.kt @@ -55,8 +55,10 @@ constructor() : BasicGameState() { * list of Actors that is sorted by Actors' referenceID */ val ACTORCONTAINER_INITIAL_SIZE = 128 + val PARTICLES_MAX = 768 val actorContainer = ArrayList(ACTORCONTAINER_INITIAL_SIZE) val actorContainerInactive = ArrayList(ACTORCONTAINER_INITIAL_SIZE) + val particlesContainer = CircularArray(PARTICLES_MAX) val uiContainer = ArrayList() private val actorsRenderBehind = ArrayList(ACTORCONTAINER_INITIAL_SIZE) @@ -224,6 +226,7 @@ constructor() : BasicGameState() { // determine whether the actor should keep being activated or be dormant KillOrKnockdownActors() updateActors(gc, delta) + particlesContainer.forEach { it.update(gc, delta) } // TODO thread pool(?) CollisionSolver.process() } @@ -232,7 +235,7 @@ constructor() : BasicGameState() { //////////////////////// // ui-related updates // //////////////////////// - uiContainer.forEach { ui -> ui.update(gc, delta) } + uiContainer.forEach { it.update(gc, delta) } consoleHandler.update(gc, delta) debugWindow.update(gc, delta) notifier.update(gc, delta) @@ -320,17 +323,19 @@ constructor() : BasicGameState() { // draw map related stuffs // ///////////////////////////// TilesDrawer.renderWall(worldG) - actorsRenderBehind.forEach { actor -> actor.drawBody(worldG) } - actorsRenderBehind.forEach { actor -> actor.drawGlow(worldG) } + actorsRenderBehind.forEach { it.drawBody(worldG) } + actorsRenderBehind.forEach { it.drawGlow(worldG) } + particlesContainer.forEach { it.drawBody(worldG) } + particlesContainer.forEach { it.drawGlow(worldG) } TilesDrawer.renderTerrain(worldG) ///////////////// // draw actors // ///////////////// - actorsRenderMiddle.forEach { actor -> actor.drawBody(worldG) } - actorsRenderMidTop.forEach { actor -> actor.drawBody(worldG) } + actorsRenderMiddle.forEach { it.drawBody(worldG) } + actorsRenderMidTop.forEach { it.drawBody(worldG) } player.drawBody(worldG) - actorsRenderFront.forEach { actor -> actor.drawBody(worldG) } + actorsRenderFront.forEach { it.drawBody(worldG) } // --> Change of blend mode <-- introduced by ActorVisible // @@ -354,10 +359,10 @@ constructor() : BasicGameState() { ////////////////////// // draw actor glows // ////////////////////// - actorsRenderMiddle.forEach { actor -> actor.drawGlow(worldG) } - actorsRenderMidTop.forEach { actor -> actor.drawGlow(worldG) } + actorsRenderMiddle.forEach { it.drawGlow(worldG) } + actorsRenderMidTop.forEach { it.drawGlow(worldG) } player.drawGlow(worldG) - actorsRenderFront.forEach { actor -> actor.drawGlow(worldG) } + actorsRenderFront.forEach { it.drawGlow(worldG) } // --> blendLightenOnly() <-- introduced by ActorVisible // @@ -396,7 +401,7 @@ constructor() : BasicGameState() { ////////////// // draw UIs // ////////////// - uiContainer.forEach { ui -> ui.render(gc, sbg, uiG) } + uiContainer.forEach { it.render(gc, sbg, uiG) } debugWindow.render(gc, sbg, uiG) consoleHandler.render(gc, sbg, uiG) notifier.render(gc, sbg, uiG) @@ -684,6 +689,10 @@ constructor() : BasicGameState() { } } + fun addParticle(particle: ParticleBase) { + particlesContainer.add(particle) + } + /** * Whether the game should display actorContainer elem number when F3 is on */ diff --git a/src/net/torvald/terrarum/StateNoiseTexGen.kt b/src/net/torvald/terrarum/StateNoiseTexGen.kt index 80e69308c..fa2aaea93 100644 --- a/src/net/torvald/terrarum/StateNoiseTexGen.kt +++ b/src/net/torvald/terrarum/StateNoiseTexGen.kt @@ -11,7 +11,7 @@ import org.newdawn.slick.state.StateBasedGame import java.util.* /** - * Created by SKYHi14 on 2016-12-21. + * Created by minjaesong on 2016-12-21. */ class StateNoiseTexGen : BasicGameState() { diff --git a/src/net/torvald/terrarum/console/AVTracker.kt b/src/net/torvald/terrarum/console/AVTracker.kt index 943ac7a33..da57ad653 100644 --- a/src/net/torvald/terrarum/console/AVTracker.kt +++ b/src/net/torvald/terrarum/console/AVTracker.kt @@ -5,7 +5,7 @@ import net.torvald.terrarum.debuggerapp.ActorValueTracker import java.util.* /** - * Created by SKYHi14 on 2016-12-29. + * Created by minjaesong on 2016-12-29. */ object AVTracker : ConsoleCommand { private val jPanelInstances = ArrayList() diff --git a/src/net/torvald/terrarum/console/ActorsList.kt b/src/net/torvald/terrarum/console/ActorsList.kt index f15995e4b..8bae65a38 100644 --- a/src/net/torvald/terrarum/console/ActorsList.kt +++ b/src/net/torvald/terrarum/console/ActorsList.kt @@ -5,7 +5,7 @@ import net.torvald.terrarum.debuggerapp.ActorsLister import java.util.* /** - * Created by SKYHi14 on 2016-12-29. + * Created by minjaesong on 2016-12-29. */ object ActorsList : ConsoleCommand { private val jPanelInstances = ArrayList() diff --git a/src/net/torvald/terrarum/console/Inventory.kt b/src/net/torvald/terrarum/console/Inventory.kt index f2c5c1a21..1528a51f4 100644 --- a/src/net/torvald/terrarum/console/Inventory.kt +++ b/src/net/torvald/terrarum/console/Inventory.kt @@ -8,7 +8,7 @@ import net.torvald.terrarum.gameitem.EquipPosition import net.torvald.terrarum.itemproperties.ItemCodex /** - * Created by SKYHi14 on 2016-12-12. + * Created by minjaesong on 2016-12-12. */ internal object Inventory : ConsoleCommand { diff --git a/src/net/torvald/terrarum/console/SetScale.kt b/src/net/torvald/terrarum/console/SetScale.kt index 63a0c3314..c41755ab3 100644 --- a/src/net/torvald/terrarum/console/SetScale.kt +++ b/src/net/torvald/terrarum/console/SetScale.kt @@ -4,7 +4,7 @@ import net.torvald.terrarum.Terrarum import net.torvald.terrarum.gameactors.ActorWithSprite /** - * Created by SKYHi14 on 2017-01-20. + * Created by minjaesong on 2017-01-20. */ object SetScale : ConsoleCommand { override fun execute(args: Array) { diff --git a/src/net/torvald/terrarum/console/SpawnTapestry.kt b/src/net/torvald/terrarum/console/SpawnTapestry.kt index 2ac07d142..ab143f08f 100644 --- a/src/net/torvald/terrarum/console/SpawnTapestry.kt +++ b/src/net/torvald/terrarum/console/SpawnTapestry.kt @@ -6,7 +6,7 @@ import java.io.File import java.io.FileInputStream /** - * Created by SKYHi14 on 2017-01-14. + * Created by minjaesong on 2017-01-14. */ object SpawnTapestry : ConsoleCommand { override fun execute(args: Array) { diff --git a/src/net/torvald/terrarum/console/SpawnTikiTorch.kt b/src/net/torvald/terrarum/console/SpawnTikiTorch.kt index 1fcf13178..0fdc15916 100644 --- a/src/net/torvald/terrarum/console/SpawnTikiTorch.kt +++ b/src/net/torvald/terrarum/console/SpawnTikiTorch.kt @@ -6,7 +6,7 @@ import net.torvald.terrarum.gamecontroller.mouseX import net.torvald.terrarum.gamecontroller.mouseY /** - * Created by SKYHi14 on 2016-12-17. + * Created by minjaesong on 2016-12-17. */ object SpawnTikiTorch : ConsoleCommand { override fun execute(args: Array) { diff --git a/src/net/torvald/terrarum/debuggerapp/ActorValueTracker.kt b/src/net/torvald/terrarum/debuggerapp/ActorValueTracker.kt index 3b993c3bd..865320e2a 100644 --- a/src/net/torvald/terrarum/debuggerapp/ActorValueTracker.kt +++ b/src/net/torvald/terrarum/debuggerapp/ActorValueTracker.kt @@ -17,7 +17,7 @@ import java.awt.event.MouseListener import javax.swing.* /** - * Created by SKYHi14 on 2016-12-29. + * Created by minjaesong on 2016-12-29. */ class ActorValueTracker constructor() : JFrame() { diff --git a/src/net/torvald/terrarum/debuggerapp/ActorsLister.kt b/src/net/torvald/terrarum/debuggerapp/ActorsLister.kt index 21c27f600..7e7c391a0 100644 --- a/src/net/torvald/terrarum/debuggerapp/ActorsLister.kt +++ b/src/net/torvald/terrarum/debuggerapp/ActorsLister.kt @@ -8,7 +8,7 @@ import java.util.* import javax.swing.* /** - * Created by SKYHi14 on 2016-12-29. + * Created by minjaesong on 2016-12-29. */ class ActorsLister( val actorContainer: ArrayList, diff --git a/src/net/torvald/terrarum/gameactors/ActorVisible.kt b/src/net/torvald/terrarum/gameactors/ActorVisible.kt index c4bf707a4..7d39cbd5b 100644 --- a/src/net/torvald/terrarum/gameactors/ActorVisible.kt +++ b/src/net/torvald/terrarum/gameactors/ActorVisible.kt @@ -4,7 +4,7 @@ import org.newdawn.slick.GameContainer import org.newdawn.slick.Graphics /** - * Created by SKYHi14 on 2017-01-21. + * Created by minjaesong on 2017-01-21. */ abstract class ActorVisible(renderOrder: ActorOrder) : Actor(renderOrder) { open val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0) diff --git a/src/net/torvald/terrarum/gameactors/ParticleBase.kt b/src/net/torvald/terrarum/gameactors/ParticleBase.kt index 00ba1e3d6..e27f76960 100644 --- a/src/net/torvald/terrarum/gameactors/ParticleBase.kt +++ b/src/net/torvald/terrarum/gameactors/ParticleBase.kt @@ -13,16 +13,14 @@ import org.newdawn.slick.Image /** * Actors with static sprites and very simple physics * - * Created by SKYHi14 on 2017-01-20. + * Created by minjaesong on 2017-01-20. */ -open class ParticleBase(renderOrder: ActorOrder, maxLifeTime: Int? = null) : ActorVisible(renderOrder), Projectile { +open class ParticleBase(renderOrder: ActorOrder, maxLifeTime: Int? = null) : Runnable { - override var actorValue = ActorValue() - override @Volatile var flagDespawn = false + /** Will NOT actually delete from the CircularArray */ + @Volatile var flagDespawn = false - override fun run() { - TODO("not implemented") - } + override fun run() = update(Terrarum.appgc, Terrarum.ingame.UPDATE_DELTA) var isNoSubjectToGrav = false var dragCoefficient = 3.0 @@ -31,38 +29,47 @@ open class ParticleBase(renderOrder: ActorOrder, maxLifeTime: Int? = null) : Act private var lifetimeCounter = 0 open val velocity = Vector2(0.0, 0.0) + open val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0) - open lateinit var image: Image + open lateinit var body: Image + open var glow: Image? = null init { } - override fun update(gc: GameContainer, delta: Int) { - lifetimeCounter += delta - if (velocity.isZero || lifetimeCounter >= lifetimeMax || - // simple stuck check - TileCodex[Terrarum.ingame.world.getTileFromTerrain( - hitbox.pointedX.div(TILE_SIZE).floorInt(), - hitbox.pointedY.div(TILE_SIZE).floorInt() - ) ?: Tile.STONE].isSolid) { - flagDespawn = true + fun update(gc: GameContainer, delta: Int) { + if (!flagDespawn) { + lifetimeCounter += delta + if (velocity.isZero || lifetimeCounter >= lifetimeMax || + // simple stuck check + TileCodex[Terrarum.ingame.world.getTileFromTerrain( + hitbox.pointedX.div(TILE_SIZE).floorInt(), + hitbox.pointedY.div(TILE_SIZE).floorInt() + ) ?: Tile.STONE].isSolid) { + flagDespawn = true + } + + // gravity, winds, etc. (external forces) + if (!isNoSubjectToGrav) { + velocity += Terrarum.ingame.world.gravitation / dragCoefficient * SI_TO_GAME_ACC + } + + + // combine external forces + hitbox.translate(velocity) } - - // gravity, winds, etc. (external forces) - if (!isNoSubjectToGrav) { - velocity += Terrarum.ingame.world.gravitation / dragCoefficient * SI_TO_GAME_ACC - } - - - // combine external forces - hitbox.translate(velocity) } - override fun drawBody(g: Graphics) { - g.drawImage(image, hitbox.centeredX.toFloat(), hitbox.centeredY.toFloat()) + fun drawBody(g: Graphics) { + if (!flagDespawn) { + g.drawImage(body, hitbox.centeredX.toFloat(), hitbox.centeredY.toFloat()) + } } - override fun drawGlow(g: Graphics) { + fun drawGlow(g: Graphics) { + if (!flagDespawn && glow != null) { + g.drawImage(glow, hitbox.centeredX.toFloat(), hitbox.centeredY.toFloat()) + } } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/ParticleTestRain.kt b/src/net/torvald/terrarum/gameactors/ParticleTestRain.kt index 77dcb82dd..6f9f4520c 100644 --- a/src/net/torvald/terrarum/gameactors/ParticleTestRain.kt +++ b/src/net/torvald/terrarum/gameactors/ParticleTestRain.kt @@ -4,21 +4,21 @@ import org.dyn4j.geometry.Vector2 import org.newdawn.slick.Image /** - * Created by SKYHi14 on 2017-01-20. + * Created by minjaesong on 2017-01-20. */ class ParticleTestRain(posX: Double, posY: Double) : ParticleBase(ActorOrder.BEHIND, 6000) { init { - image = Image("./assets/graphics/weathers/raindrop.tga") - val w = image.width.toDouble() - val h = image.height.toDouble() + body = Image("./assets/graphics/weathers/raindrop.tga") + val w = body.width.toDouble() + val h = body.height.toDouble() hitbox.setFromWidthHeight( posX - w.times(0.5), posY - h.times(0.5), w, h ) - velocity.y = 16.0 + velocity.y = 10.0 } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/TapestryObject.kt b/src/net/torvald/terrarum/gameactors/TapestryObject.kt index 4ddbd305d..e1b13feed 100644 --- a/src/net/torvald/terrarum/gameactors/TapestryObject.kt +++ b/src/net/torvald/terrarum/gameactors/TapestryObject.kt @@ -8,7 +8,7 @@ import org.newdawn.slick.Graphics import org.newdawn.slick.Image /** - * Created by SKYHi14 on 2017-01-07. + * Created by minjaesong on 2017-01-07. */ class TapestryObject(val image: Image, val artName: String, val artAuthor: String) : FixtureBase(physics = false) { diff --git a/src/net/torvald/terrarum/mapdrawer/MapCamera.kt b/src/net/torvald/terrarum/mapdrawer/MapCamera.kt index 71261b651..70f0898fc 100644 --- a/src/net/torvald/terrarum/mapdrawer/MapCamera.kt +++ b/src/net/torvald/terrarum/mapdrawer/MapCamera.kt @@ -5,7 +5,7 @@ import net.torvald.terrarum.Terrarum import net.torvald.terrarum.gameworld.GameWorld /** - * Created by SKYHi14 on 2016-12-30. + * Created by minjaesong on 2016-12-30. */ object MapCamera { private val world: GameWorld = Terrarum.ingame.world diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 94d049607..19b9e8e41 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -174,6 +174,8 @@ class BasicDebugInfoWindow : UICanvas { (2 + 17*8).toFloat(), Terrarum.HEIGHT - 10f) g.drawString("${ccY}Dormant $ccG${Terrarum.ingame.actorContainerInactive.size}", (2 + 28*8).toFloat(), Terrarum.HEIGHT - 10f) + g.drawString("${ccM}Particles $ccG${Terrarum.ingame.particlesContainer.elemCount}", + (2 + 41*8).toFloat(), Terrarum.HEIGHT - 10f) } private fun printLine(g: Graphics, l: Int, s: String) { diff --git a/src/net/torvald/terrarum/weather/WeatherMixer.kt b/src/net/torvald/terrarum/weather/WeatherMixer.kt index 39f702fb7..9aa5041b3 100644 --- a/src/net/torvald/terrarum/weather/WeatherMixer.kt +++ b/src/net/torvald/terrarum/weather/WeatherMixer.kt @@ -79,15 +79,17 @@ object WeatherMixer { fun update(gc: GameContainer, delta: Int) { currentWeather = weatherList[WEATHER_GENERIC]!![0] - // test rain toggled by F2 + // test rain toggled by F2 if (KeyToggler.isOn(Key.F2)) { val playerPos = Terrarum.ingame.player.centrePosPoint - val rainParticle = ParticleTestRain( - playerPos.x + HQRNG().nextInt(Terrarum.WIDTH) - Terrarum.HALFW, - playerPos.y - Terrarum.HALFH - ) - Terrarum.ingame.addActor(rainParticle) + kotlin.repeat(4) { // 4 seems good + val rainParticle = ParticleTestRain( + playerPos.x + HQRNG().nextInt(Terrarum.WIDTH) - Terrarum.HALFW, + playerPos.y - Terrarum.HALFH + ) + Terrarum.ingame.addParticle(rainParticle) + } } }