rain megaparticle experiment

This commit is contained in:
minjaesong
2017-12-18 20:45:32 +09:00
parent 3936d381d2
commit f8568899d9
16 changed files with 286 additions and 69 deletions

View File

@@ -11,6 +11,7 @@ import net.torvald.terrarum.itemproperties.Material
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.ui.UIInventoryFull
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import org.dyn4j.geometry.Vector2
import java.util.*
/**
@@ -473,30 +474,89 @@ open class ActorHumanoid(
isWalkingV = false
}
private fun getJumpAcc(pwr: Double, timedJumpCharge: Double): Double {
return pwr * timedJumpCharge * JUMP_ACCELERATION_MOD * Math.sqrt(scale) // positive value
}
private var oldMAX_JUMP_LENGTH = -1 // init
private var oldJUMPPOWER = -1.0 // init
private var oldJUMPPOWERBUFF = -1.0 // init
private var oldScale = -1.0
private var oldDragCoefficient = -1.0
val jumpAirTime: Double = -1.0
get() {
// compare all the affecting variables
if (oldMAX_JUMP_LENGTH == MAX_JUMP_LENGTH &&
oldJUMPPOWER == actorValue.getAsDouble(AVKey.JUMPPOWER)!! &&
oldJUMPPOWERBUFF == actorValue.getAsDouble(AVKey.JUMPPOWERBUFF) ?: 1.0 &&
oldScale == scale &&
oldDragCoefficient == dragCoefficient) {
return field
}
// if variables are changed, get new value, store it and return it
else {
oldMAX_JUMP_LENGTH = MAX_JUMP_LENGTH
oldJUMPPOWER = actorValue.getAsDouble(AVKey.JUMPPOWER)!!
oldJUMPPOWERBUFF = actorValue.getAsDouble(AVKey.JUMPPOWERBUFF) ?: 1.0
oldScale = scale
oldDragCoefficient = dragCoefficient
var frames = 0
var simYPos = 0.0
var forceVec = Vector2(0.0, 0.0)
var jmpCtr = 0
while (true) {
if (jmpCtr < MAX_JUMP_LENGTH) jmpCtr++
val timedJumpCharge = jumpFunc(MAX_JUMP_LENGTH, jmpCtr)
forceVec.y -= getJumpAcc(jumpPower, timedJumpCharge)
forceVec.y += getDrag(forceVec).y
simYPos += forceVec.y // ignoring all the fluid drag OTHER THAN THE AIR
if ((simYPos >= 0.0 && frames > 0) || frames >= 1000) break
frames++
}
field = frames * (1.0 / Terrarum.TARGET_FPS)
// fixme: looks good but return value is wrong -- 2.25 seconds? when I jump it barely goes past 1 sec
return field
}
}
private val jumpPower: Double
get() = actorValue.getAsDouble(AVKey.JUMPPOWER)!! * (actorValue.getAsDouble(AVKey.JUMPPOWERBUFF) ?: 1.0)
private fun jumpFunc(len: Int, counter: Int): Double {
// linear time mode
val init = (len + 1) / 2.0
var timedJumpCharge = init - init / len * counter
if (timedJumpCharge < 0) timedJumpCharge = 0.0
return timedJumpCharge
}
/**
* See ./work_files/Jump power by pressing time.gcx
*
* TODO linear function (play Super Mario Bros. and you'll get what I'm talking about) -- SCRATCH THAT!
*/
private fun jump() {
val len = MAX_JUMP_LENGTH.toFloat()
val pwr = actorValue.getAsDouble(AVKey.JUMPPOWER)!! * (actorValue.getAsDouble(AVKey.JUMPPOWERBUFF) ?: 1.0)
fun jumpFunc(counter: Int): Double {
// linear time mode
val init = (len + 1) / 2.0
var timedJumpCharge = init - init / len * counter
if (timedJumpCharge < 0) timedJumpCharge = 0.0
return timedJumpCharge
}
if (jumping) {// && jumpable) {
// increment jump counter
if (jumpCounter < len) jumpCounter += 1
if (jumpCounter < MAX_JUMP_LENGTH) jumpCounter += 1
val timedJumpCharge = jumpFunc(jumpCounter)
val timedJumpCharge = jumpFunc(MAX_JUMP_LENGTH, jumpCounter)
jumpAcc = pwr * timedJumpCharge * JUMP_ACCELERATION_MOD * Math.sqrt(scale) // positive value
jumpAcc = getJumpAcc(jumpPower, timedJumpCharge)
controllerMoveDelta?.y?.let { controllerMoveDelta!!.y -= jumpAcc } // feed negative value to the vector
// do not think of resetting this to zero when counter hit the ceiling; that's HOW NOT
@@ -510,7 +570,7 @@ open class ActorHumanoid(
}*/
// release "jump key" of AIs
if (jumpCounter >= len && !isGamer) {
if (jumpCounter >= MAX_JUMP_LENGTH && !isGamer) {
isJumpDown = false
jumping = false
jumpCounter = 0

View File

@@ -493,6 +493,27 @@ open class ActorWithPhysics(val world: GameWorld, renderOrder: RenderOrder, val
}
}*/
fun getDrag(externalForce: Vector2): Vector2 {
/**
* weight; gravitational force in action
* W = mass * G (9.8 [m/s^2])
*/
val W: Vector2 = gravitation * Terrarum.TARGET_FPS.toDouble()
/**
* Area
*/
val A: Double = (scale * baseHitboxW / METER) * (scale * baseHitboxW / METER)
/**
* Drag of atmosphere
* D = Cd (drag coefficient) * 0.5 * rho (density) * V^2 (velocity sqr) * A (area)
*/
val D: Vector2 = Vector2(externalForce.x.magnSqr(), externalForce.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble()
val V: Vector2 = (W - D) / Terrarum.TARGET_FPS.toDouble() * SI_TO_GAME_ACC
return V
}
/**
* Apply gravitation to the every falling body (unless not levitating)
*
@@ -502,24 +523,7 @@ open class ActorWithPhysics(val world: GameWorld, renderOrder: RenderOrder, val
if (!isNoSubjectToGrav && !(gravitation.y > 0 && walledBottom || gravitation.y < 0 && walledTop)) {
//if (!isWalled(hitbox, COLLIDING_BOTTOM)) {
/**
* weight; gravitational force in action
* W = mass * G (9.8 [m/s^2])
*/
val W: Vector2 = gravitation * Terrarum.TARGET_FPS.toDouble()
/**
* Area
*/
val A: Double = (scale * baseHitboxW / METER) * (scale * baseHitboxW / METER)
/**
* Drag of atmosphere
* D = Cd (drag coefficient) * 0.5 * rho (density) * V^2 (velocity sqr) * A (area)
*/
val D: Vector2 = Vector2(externalForce.x.magnSqr(), externalForce.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble()
val V: Vector2 = (W - D) / Terrarum.TARGET_FPS.toDouble() * SI_TO_GAME_ACC
applyForce(V)
applyForce(getDrag(externalForce))
//}
}
}

View File

@@ -15,7 +15,7 @@ import org.dyn4j.geometry.Vector2
*
* Created by minjaesong on 2017-01-20.
*/
open class ParticleBase(renderOrder: Actor.RenderOrder, maxLifeTime: Second? = null) : Runnable {
open class ParticleBase(renderOrder: Actor.RenderOrder, val despawnUponCollision: Boolean, maxLifeTime: Second? = null) : Runnable {
/** Will NOT actually delete from the CircularArray */
@Volatile var flagDespawn = false
@@ -41,12 +41,18 @@ open class ParticleBase(renderOrder: Actor.RenderOrder, maxLifeTime: Second? = n
fun update(delta: Float) {
if (!flagDespawn) {
lifetimeCounter += delta
if (velocity.isZero || lifetimeCounter >= lifetimeMax ||
// simple stuck check
BlockCodex[Terrarum.ingame!!.world.getTileFromTerrain(
hitbox.canonicalX.div(TILE_SIZE).floorInt(),
hitbox.canonicalY.div(TILE_SIZE).floorInt()
) ?: Block.STONE].isSolid) {
if (despawnUponCollision) {
if (velocity.isZero ||
// simple stuck check
BlockCodex[Terrarum.ingame!!.world.getTileFromTerrain(
hitbox.canonicalX.div(TILE_SIZE).floorInt(),
hitbox.canonicalY.div(TILE_SIZE).floorInt()
) ?: Block.STONE].isSolid) {
flagDespawn = true
}
}
if (lifetimeCounter >= lifetimeMax) {
flagDespawn = true
}

View File

@@ -0,0 +1,107 @@
package net.torvald.terrarum.gameactors
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.random.HQRNG
import net.torvald.terrarum.ModMgr
import net.torvald.terrarum.Terrarum
/**
* Created by minjaesong on 2017-12-18.
*/
class ParticleMegaRain(posX: Double, posY: Double) : ParticleBase(Actor.RenderOrder.BEHIND, false, 3.2f) {
init {
body = MegaRainGovernor.get()
val w = body.regionWidth.toDouble()
val h = body.regionHeight.toDouble()
hitbox.setFromWidthHeight(
posX - w.times(0.5),
posY - h.times(0.5),
w, h
)
velocity.y = 18.0
}
}
object MegaRainGovernor {
private var reseedTimer = 0f
var reseedTime: Second = 90f
private val body = Pixmap(ModMgr.getGdxFile("basegame", "weathers/raindrop.tga"))
private lateinit var bodies: Array<TextureRegion>
private var withdrawCounter = 0
init {
seed()
}
private fun seed() {
val w = body.width
val h = body.height
bodies = Array(1024) {
val pixmap = Pixmap(Terrarum.WIDTH * 2, Terrarum.HEIGHT / 4, Pixmap.Format.RGBA8888)
val rng = HQRNG()
repeat(64) {
val rndX = rng.nextInt(pixmap.width - body.width)
val rndY = rng.nextInt(pixmap.height - body.height)
pixmap.drawPixmap(body, rndX, rndY)
}
// return composed (mega)pixmap
val region = TextureRegion(Texture(pixmap))
region.flip(false, true)
/*return*/region
}
// randomise
bodies.shuffle()
}
fun get(): TextureRegion {
if (withdrawCounter >= bodies.size) {
withdrawCounter = 0
bodies.shuffle()
}
return bodies[withdrawCounter++]
}
@Deprecated("re-seeding freezes the game a little and large enough randomnesses ought to be good")
fun update(delta: Float) {
if (reseedTimer >= reseedTime) {
seed()
reseedTimer -= reseedTime
}
reseedTimer += delta
}
fun resize() {
seed()
withdrawCounter = 0
reseedTimer = 0f
}
fun Array<TextureRegion>.shuffle() {
for (i in this.size - 1 downTo 1) {
val rndIndex = (Math.random() * (i + 1)).toInt()
val t = this[rndIndex]
this[rndIndex] = this[i]
this[i] = t
}
}
}

View File

@@ -7,7 +7,7 @@ import net.torvald.terrarum.ModMgr
/**
* Created by minjaesong on 2017-01-20.
*/
class ParticleTestRain(posX: Double, posY: Double) : ParticleBase(Actor.RenderOrder.BEHIND, 6f) {
class ParticleTestRain(posX: Double, posY: Double) : ParticleBase(Actor.RenderOrder.BEHIND, true, 6f) {
init {
body = TextureRegion(Texture(ModMgr.getGdxFile("basegame", "weathers/raindrop.tga")))