mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 02:24:05 +09:00
aim helper wip
This commit is contained in:
@@ -11,6 +11,8 @@ class Point2d() : Cloneable {
|
|||||||
var x: Double = 0.0
|
var x: Double = 0.0
|
||||||
var y: Double = 0.0
|
var y: Double = 0.0
|
||||||
|
|
||||||
|
constructor(other: Point2d) : this(other.x, other.y)
|
||||||
|
|
||||||
constructor(x: Double, y: Double) : this() {
|
constructor(x: Double, y: Double) : this() {
|
||||||
this.x = x
|
this.x = x
|
||||||
this.y = y
|
this.y = y
|
||||||
|
|||||||
@@ -13,12 +13,20 @@ import net.torvald.random.HQRNG
|
|||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.*
|
import net.torvald.terrarum.App.*
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
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.TerrarumAppConfiguration.TILE_SIZEF
|
||||||
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
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.gamecontroller.KeyToggler
|
||||||
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
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.ui.Toolkit
|
||||||
import net.torvald.terrarum.weather.WeatherMixer
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
import net.torvald.terrarum.weather.WeatherMixer.render
|
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.LightmapRenderer
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
|
import org.dyn4j.geometry.Vector2
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
@@ -248,6 +257,8 @@ object IngameRenderer : Disposable {
|
|||||||
drawToRGB(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
|
drawToRGB(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
|
||||||
drawToA(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
|
drawToA(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
|
||||||
drawOverlayActors(frameDelta, actorsRenderOverlay)
|
drawOverlayActors(frameDelta, actorsRenderOverlay)
|
||||||
|
|
||||||
|
if (player != null && player is Pocketed) drawAimGuide(frameDelta, player)
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.color = Color.WHITE
|
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() {
|
private fun invokeInit() {
|
||||||
if (!initDone) {
|
if (!initDone) {
|
||||||
|
|||||||
@@ -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 ->
|
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long = mouseInInteractableRange(actor) { mx, my, mtx, mty ->
|
||||||
|
val (throwPos, throwForce) = getThrowPosAndVector(actor)
|
||||||
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 lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor().newInstance() as ActorWithBody
|
val lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor().newInstance() as ActorWithBody
|
||||||
lobbed.setPosition(playerCentrePos)
|
lobbed.setPosition(throwPos)
|
||||||
lobbed.externalV.set(powX, powY)
|
lobbed.externalV.set(throwForce)
|
||||||
setupLobbedActor(lobbed)
|
setupLobbedActor(lobbed)
|
||||||
|
|
||||||
Terrarum.ingame?.queueActorAddition(lobbed)
|
Terrarum.ingame?.queueActorAddition(lobbed)
|
||||||
@@ -52,6 +44,24 @@ open class ItemThrowable(originalID: ItemID, private val throwableActorClassName
|
|||||||
|
|
||||||
1L
|
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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user