mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-15 13:04:05 +09:00
rain megaparticle experiment
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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))
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
107
src/net/torvald/terrarum/gameactors/ParticleMegaRain.kt
Normal file
107
src/net/torvald/terrarum/gameactors/ParticleMegaRain.kt
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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")))
|
||||
|
||||
Reference in New Issue
Block a user