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:
Song Minjae
2016-04-26 14:36:21 +09:00
parent 6ae31f1858
commit 7d804f24e7
8 changed files with 104 additions and 49 deletions

View File

@@ -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(

View File

@@ -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)
*/
}

View File

@@ -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

View File

@@ -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 */

View 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 {
}
}

View File

@@ -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
}
}

View File

@@ -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) {

View File

@@ -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}")