mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
physics objects (ActorWithBody) will now sleep if ||v|| < 0.5, faction ID is now positive integer (64-bit) only
Former-commit-id: 437cff82cf5748c36c5ad72bc43b4fc172b168c8 Former-commit-id: 3ab0500f83da229ec77b85c09ec42fd332ef62ce
This commit is contained in:
@@ -31,8 +31,8 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
* veloY += 3.0
|
||||
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
|
||||
*/
|
||||
var veloX: Float = 0.toFloat()
|
||||
var veloY: Float = 0.toFloat()
|
||||
@Volatile var veloX: Float = 0.toFloat()
|
||||
@Volatile var veloY: Float = 0.toFloat()
|
||||
@Transient private val VELO_HARD_LIMIT = 10000f
|
||||
|
||||
var grounded = false
|
||||
@@ -132,10 +132,10 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
internal val physSleep: Boolean
|
||||
get() = veloX.abs() < 0.5 && veloY.abs() < 0.5
|
||||
|
||||
private var posAdjustX = 0
|
||||
private var posAdjustY = 0
|
||||
@Transient private var posAdjustX = 0
|
||||
@Transient private var posAdjustY = 0
|
||||
|
||||
private val BASE_FRICTION = 0.3f
|
||||
@Transient private val BASE_FRICTION = 0.3f
|
||||
|
||||
init {
|
||||
map = Terrarum.game.map
|
||||
@@ -189,10 +189,11 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
|
||||
override fun update(gc: GameContainer, delta_t: Int) {
|
||||
if (isUpdate) {
|
||||
updatePhysicalInfos()
|
||||
/**
|
||||
* Update variables
|
||||
*/
|
||||
updatePhysicalInfos()
|
||||
|
||||
// make NoClip work for player
|
||||
if (this is Player) {
|
||||
isNoSubjectToGrav = isPlayerNoClip
|
||||
@@ -212,6 +213,9 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
// copy gravitational constant from the map the actor is in
|
||||
gravitation = map.gravitation
|
||||
|
||||
/**
|
||||
* Actual physics thing (altering velocity) starts from here
|
||||
*/
|
||||
// Actors are subject to the gravity and the buoyancy if they are not levitating
|
||||
if (!isNoSubjectToGrav) {
|
||||
applyGravitation()
|
||||
@@ -222,29 +226,31 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
if (veloX > VELO_HARD_LIMIT) veloX = VELO_HARD_LIMIT
|
||||
if (veloY > VELO_HARD_LIMIT) veloY = VELO_HARD_LIMIT
|
||||
|
||||
// Set 'next' position (hitbox) to fiddle with
|
||||
updateNextHitboxFromVelo()
|
||||
if (!physSleep) {
|
||||
// Set 'next' position (hitbox) to fiddle with
|
||||
updateNextHitboxFromVelo()
|
||||
|
||||
// if not horizontally moving then ...
|
||||
//if (Math.abs(veloX) < 0.5) { // fix for special situations (see fig. 1 at the bottom of the source)
|
||||
// updateVerticalPos();
|
||||
// updateHorizontalPos();
|
||||
//}
|
||||
//else {
|
||||
// compensate for colliding
|
||||
updateHorizontalCollision()
|
||||
updateVerticalCollision()
|
||||
// if not horizontally moving then ...
|
||||
//if (Math.abs(veloX) < 0.5) { // fix for special situations (see fig. 1 at the bottom of the source)
|
||||
// updateVerticalPos();
|
||||
// updateHorizontalPos();
|
||||
//}
|
||||
//else {
|
||||
// compensate for colliding
|
||||
updateHorizontalCollision()
|
||||
updateVerticalCollision()
|
||||
|
||||
setHorizontalFriction()
|
||||
//}
|
||||
setHorizontalFriction()
|
||||
//}
|
||||
|
||||
// apply our compensation to actual hitbox
|
||||
updateHitboxX()
|
||||
updateHitboxY()
|
||||
// apply our compensation to actual hitbox
|
||||
updateHitboxX()
|
||||
updateHitboxY()
|
||||
|
||||
// make sure the actor does not go out of the map
|
||||
clampNextHitbox()
|
||||
clampHitbox()
|
||||
// make sure the actor does not go out of the map
|
||||
clampNextHitbox()
|
||||
clampHitbox()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,14 +281,14 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
}
|
||||
|
||||
private fun setHorizontalFriction() {
|
||||
val friction = BASE_FRICTION * (tileFriction / 16f) // ground frction * !@#$!@#$ // default val: 0.3
|
||||
val friction = BASE_FRICTION * tileFriction.tileFrictionToMult()
|
||||
if (veloX < 0) {
|
||||
veloX += friction
|
||||
if (veloX > 0) veloX = 0f
|
||||
if (veloX > 0) veloX = 0f // compensate overshoot
|
||||
}
|
||||
else if (veloX > 0) {
|
||||
veloX -= friction
|
||||
if (veloX < 0) veloX = 0f
|
||||
if (veloX < 0) veloX = 0f // compensate overshoot
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,6 +586,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
|
||||
return friction
|
||||
}
|
||||
fun Int.tileFrictionToMult() = this / 16f
|
||||
|
||||
/**
|
||||
* Get highest density (specific gravity) value from tiles that the body occupies.
|
||||
@@ -597,20 +604,43 @@ open class ActorWithBody constructor() : Actor(), Visible {
|
||||
for (y in tilePosYStart..tilePosYEnd) {
|
||||
for (x in tilePosXStart..tilePosXEnd) {
|
||||
val tile = map.getTileFromTerrain(x, y)
|
||||
if (TilePropCodex.getProp(tile).isFluid) {
|
||||
val thisFluidDensity = TilePropCodex.getProp(tile).density
|
||||
val thisFluidDensity = TilePropCodex.getProp(tile).density
|
||||
|
||||
if (thisFluidDensity > density) density = thisFluidDensity
|
||||
}
|
||||
if (thisFluidDensity > density) density = thisFluidDensity
|
||||
}
|
||||
}
|
||||
|
||||
return density
|
||||
}
|
||||
|
||||
private fun mvmtRstcToMultiplier(movementResistanceValue: Int): Float {
|
||||
return 1f / (1 + movementResistanceValue / 16f)
|
||||
}
|
||||
/**
|
||||
* Get highest fluid resistance value from tiles that the body occupies.
|
||||
* @return
|
||||
*/
|
||||
private val fluidResistance: Int
|
||||
get() {
|
||||
var resistance = 0
|
||||
|
||||
//get highest fluid density
|
||||
val tilePosXStart = (nextHitbox.posX / TSIZE).roundToInt()
|
||||
val tilePosYStart = (nextHitbox.posY / TSIZE).roundToInt()
|
||||
val tilePosXEnd = (nextHitbox.hitboxEnd.x / TSIZE).roundToInt()
|
||||
val tilePosYEnd = (nextHitbox.hitboxEnd.y / TSIZE).roundToInt()
|
||||
for (y in tilePosYStart..tilePosYEnd) {
|
||||
for (x in tilePosXStart..tilePosXEnd) {
|
||||
val tile = map.getTileFromTerrain(x, y)
|
||||
|
||||
if (TilePropCodex.getProp(tile).isFluid) {
|
||||
val thisResistance = TilePropCodex.getProp(tile).movementResistance
|
||||
|
||||
if (thisResistance > resistance) resistance = thisResistance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resistance
|
||||
}
|
||||
fun Int.resistanceToMult(): Float = 1f / (1 + this / 16f)
|
||||
|
||||
private fun clampHitbox() {
|
||||
hitbox.setPositionFromPoint(
|
||||
|
||||
@@ -106,10 +106,21 @@ object CollisionSolver {
|
||||
// in some situation (A, C) will not making any contact with each other
|
||||
// we are going to filter them
|
||||
if (a isCollidingWith b) {
|
||||
// notify collision, but not solve it yet
|
||||
// (e.g. player vs mob, will pass by but still takes damage)
|
||||
|
||||
|
||||
// if they actually makes collision (e.g. player vs ball), solve it
|
||||
if (a makesCollisionWith b) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private infix fun ActorWithBody.makesCollisionWith(other: ActorWithBody): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
private infix fun ActorWithBody.isCollidingWith(other: ActorWithBody): Boolean {
|
||||
val ax = this.hitbox.centeredX
|
||||
val ay = this.hitbox.centeredY
|
||||
@@ -152,6 +163,10 @@ object CollisionSolver {
|
||||
/**
|
||||
* === Some useful physics knowledge ===
|
||||
*
|
||||
* * Momentum = mass × Velocity
|
||||
* * Momentum = mass × Velocity (p = mv, conserved)
|
||||
*
|
||||
* * Force = mass × acceleration (f = ma, conserved)
|
||||
*
|
||||
* * F_AB = -F_BA (Lex Tertia, does NOT apply to fictitious force like centrifugal)
|
||||
*/
|
||||
}
|
||||
@@ -7,9 +7,9 @@ import net.torvald.point.Point2f
|
||||
*/
|
||||
class Hitbox(x1: Float, y1: Float, width: Float, height: Float) {
|
||||
|
||||
var hitboxStart: Point2f
|
||||
@Volatile var hitboxStart: Point2f
|
||||
private set
|
||||
var hitboxEnd: Point2f
|
||||
@Volatile var hitboxEnd: Point2f
|
||||
private set
|
||||
var width: Float = 0.toFloat()
|
||||
private set
|
||||
|
||||
@@ -55,8 +55,6 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
|
||||
|
||||
@Transient private val TSIZE = MapDrawer.TILE_SIZE
|
||||
|
||||
private val factionSet = HashSet<Faction>()
|
||||
|
||||
@Transient private val BASE_DENSITY = 1020
|
||||
|
||||
/** Must be set by PlayerFactory */
|
||||
|
||||
12
src/net/torvald/terrarum/gameactors/WeaponSwung.kt
Normal file
12
src/net/torvald/terrarum/gameactors/WeaponSwung.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package net.torvald.terrarum.gameactors
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-04-26.
|
||||
*/
|
||||
class WeaponSwung(val itemID: Int) : ActorWithBody() {
|
||||
// just let the solver use AABB; it's cheap but works just enough
|
||||
|
||||
init {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.torvald.terrarum.gameactors.faction
|
||||
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import java.util.HashSet
|
||||
|
||||
/**
|
||||
@@ -13,7 +14,7 @@ class Faction(factionName: String) {
|
||||
lateinit var factionNeutral: HashSet<String>
|
||||
lateinit var factionHostile: HashSet<String>
|
||||
lateinit var factionFearful: HashSet<String>
|
||||
var factionID: Long = HQRNG().nextLong()
|
||||
var factionID: Long = generateUniqueID()
|
||||
|
||||
init {
|
||||
this.factionName = factionName
|
||||
@@ -59,4 +60,8 @@ class Faction(factionName: String) {
|
||||
factionFearful.remove(faction)
|
||||
}
|
||||
|
||||
fun generateUniqueID(): Long {
|
||||
fun Long.abs() = if (this < 0) -this else this
|
||||
return HQRNG().nextLong().abs() // set new ID
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,17 +331,13 @@ object MapCamera {
|
||||
tilesetBook[mode].endUse()
|
||||
}
|
||||
|
||||
private fun getGrassInfo(x: Int, y: Int, from: Int, to: Int): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* @param x
|
||||
* *
|
||||
* @param y
|
||||
* *
|
||||
* @return [0-15] 1: up, 2: right, 4: down, 8: left
|
||||
* @return binary [0-15] 1: up, 2: right, 4: down, 8: left
|
||||
*/
|
||||
private fun getNearbyTilesInfo(x: Int, y: Int, mode: Int, mark: Int?): Int {
|
||||
val nearbyTiles = IntArray(4)
|
||||
@@ -415,7 +411,6 @@ object MapCamera {
|
||||
// has tile on the bottom
|
||||
3 else 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun drawTile(mode: Int, tilewisePosX: Int, tilewisePosY: Int, sheetX: Int, sheetY: Int) {
|
||||
|
||||
@@ -85,8 +85,8 @@ class BasicDebugInfoWindow:UICanvas {
|
||||
+ (hitbox.pointedY / MapDrawer.TILE_SIZE).toInt().toString()
|
||||
+ ")")
|
||||
|
||||
printLine(g, 3, "veloX reported $ccG${player.veloX}")
|
||||
printLine(g, 4, "veloY reported $ccG${player.veloY}")
|
||||
printLine(g, 3, "veloX reported $ccG${if (player.physSleep) "(sleep)" else player.veloX}")
|
||||
printLine(g, 4, "veloY reported $ccG${if (player.physSleep) "(sleep)" else player.veloY}")
|
||||
|
||||
printLineColumn(g, 2, 3, "veloX measured $ccG${xdelta}")
|
||||
printLineColumn(g, 2, 4, "veloY measured $ccG${ydelta}")
|
||||
|
||||
Reference in New Issue
Block a user