aim helper wip

This commit is contained in:
minjaesong
2024-02-29 00:57:57 +09:00
parent 9caf2a0d7e
commit 410456e173
3 changed files with 129 additions and 11 deletions

View File

@@ -11,6 +11,8 @@ class Point2d() : Cloneable {
var x: Double = 0.0
var y: Double = 0.0
constructor(other: Point2d) : this(other.x, other.y)
constructor(x: Double, y: Double) : this() {
this.x = x
this.y = y

View File

@@ -13,12 +13,20 @@ import net.torvald.random.HQRNG
import net.torvald.terrarum.*
import net.torvald.terrarum.App.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.METER
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.SI_TO_GAME_ACC
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
import net.torvald.terrarum.modulebasegame.gameitems.getThrowPosAndVector
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.weather.WeatherMixer.render
@@ -27,6 +35,7 @@ import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray
import org.dyn4j.geometry.Vector2
import kotlin.system.exitProcess
@@ -248,6 +257,8 @@ object IngameRenderer : Disposable {
drawToRGB(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
drawToA(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
drawOverlayActors(frameDelta, actorsRenderOverlay)
if (player != null && player is Pocketed) drawAimGuide(frameDelta, player)
}
batch.color = Color.WHITE
@@ -730,6 +741,101 @@ object IngameRenderer : Disposable {
}
}
private fun drawAimGuide(frameDelta: Float, player: ActorWithBody) {
fboRGB_lightMixed.inActionF(camera, batch) { fb ->
setCameraPosition(0f, 0f)
// BlocksDrawer.renderWhateverGlow_WALL
batch.inUse {
batch.shader = null
batch.color = Color.WHITE
moveCameraToWorldCoord()
(player as Pocketed).inventory.itemEquipped[GameItem.EquipPosition.HAND_GRIP]?.let { itemID ->
val heldItem = ItemCodex[itemID] // will be null for blocks
// this is a case-by-case affair
when (heldItem) {
is ItemThrowable -> drawAimGuideForThrowable(fb, batch, frameDelta, player, world, heldItem)
}
}
}
setCameraPosition(0f, 0f)
// BlocksDrawer.renderWhateverGlow_TERRAIN
}
}
private val externalV = Vector2()
private fun drawAimGuideForThrowable(frameBuffer: FrameBuffer, batch: SpriteBatch, frameDelta: Float, player: ActorWithBody, world: GameWorld, item: ItemThrowable) {
val (throwPos, throwVector) = getThrowPosAndVector(player)
val grav = world.gravitation
externalV.set(throwVector)
batch.color = Color.WHITE // TODO get better colour
var c = 0
while (c < 50) {
// plot a dot
Toolkit.fillArea(batch, throwPos.x.toFloat(), throwPos.y.toFloat(), 2f, 2f)
// simulate physics
applyGravitation(grav, 7.0) // TODO use actual value instead of 7.0
// FIXME the ActorWithBody phys sim -- horizontal speed is lost aggressively
// move the point
throwPos += externalV
// break if colliding with a tile
if (BlockCodex[world.getTileFromTerrain(throwPos.x.div(TILE_SIZED).toInt(), throwPos.x.div(TILE_SIZED).toInt())].isSolid)
break
c++
}
}
private fun applyGravitation(gravitation: Vector2, hitboxWidth: Double) {
applyForce(getDrag(externalV, gravitation, hitboxWidth))
}
private fun Int.viscosityToMult(): Double = 16.0 / (16.0 + this)
private fun applyForce(acc: Vector2) {
val speedMultByTile = BlockCodex[Block.AIR].viscosity.viscosityToMult()
externalV += acc * speedMultByTile
}
private fun getDrag(externalForce: Vector2, gravitation: Vector2, hitboxWidth: Double): Vector2 {
val dragCoefficient = 1.2
/**
* weight; gravitational force in action
* W = mass * G (9.8 [m/s^2])
*/
val W: Vector2 = gravitation * Terrarum.PHYS_TIME_FRAME
/**
* Area
*/
val A: Double = (hitboxWidth / METER).sqr() // this is not physically accurate but it's needed to make large playable characters more controllable
/**
* 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.PHYS_TIME_FRAME * SI_TO_GAME_ACC
return V
// FIXME v * const, where const = 1.0 for FPS=60, sqrt(2.0) for FPS=30, etc.
// this is "close enough" solution and not perfect.
}
private fun invokeInit() {
if (!initDone) {

View File

@@ -31,19 +31,11 @@ open class ItemThrowable(originalID: ItemID, private val throwableActorClassName
}
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long = mouseInInteractableRange(actor) { mx, my, mtx, mty ->
val playerCentrePos = actor.centrePosVector
val mousePos = Vector2(mx, my)
val actorPowMult = actor.avStrength / 2000.0
val relativeX = relativeXposition(actor, mousePos)
val relativeY = my - playerCentrePos.y
val powX = relativeX / TILE_SIZED * 3.0 * actorPowMult
val powY = relativeY / TILE_SIZED * 3.0 * actorPowMult
val (throwPos, throwForce) = getThrowPosAndVector(actor)
val lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor().newInstance() as ActorWithBody
lobbed.setPosition(playerCentrePos)
lobbed.externalV.set(powX, powY)
lobbed.setPosition(throwPos)
lobbed.externalV.set(throwForce)
setupLobbedActor(lobbed)
Terrarum.ingame?.queueActorAddition(lobbed)
@@ -52,6 +44,24 @@ open class ItemThrowable(originalID: ItemID, private val throwableActorClassName
1L
}
}
/**
* @return pair of throwing start position, throwing force
*/
fun getThrowPosAndVector(actor: ActorWithBody): Pair<Vector2, Vector2> {
val playerCentrePos = Vector2(actor.centrePosVector) // make a COPY of the actor.centrePosPoint
val mousePos = Vector2(Terrarum.mouseX, Terrarum.mouseY)
val actorPowMult = actor.avStrength / 2000.0
val relativeX = relativeXposition(actor, mousePos)
val relativeY = mousePos.y - playerCentrePos.y
val powX = relativeX / TILE_SIZED * 3.0 * actorPowMult
val powY = relativeY / TILE_SIZED * 3.0 * actorPowMult
return Pair(playerCentrePos, Vector2(powX, powY))
}