WIP collision solver, colour-codes in game fonts

Former-commit-id: 0bb85999176d89956398bbcc24e1b33cacd3e87c
Former-commit-id: 0ef0c1ac9b88f8fe42a7439fee69a8d4792be96a
This commit is contained in:
Song Minjae
2016-04-23 23:08:42 +09:00
parent cffc9a9ba2
commit 1a1159b643
33 changed files with 557 additions and 230 deletions

View File

@@ -5,15 +5,20 @@ import org.newdawn.slick.GameContainer
/**
* Created by minjaesong on 16-03-14.
*/
interface Actor {
abstract class Actor : Comparable<Actor> {
fun update(gc: GameContainer, delta_t: Int)
abstract fun update(gc: GameContainer, delta_t: Int)
/**
* Valid RefID is equal to or greater than 32768.
* @return Reference ID. (32768-0xFFFF_FFFF)
*/
var referenceID: Int
abstract var referenceID: Int
var actorValue: ActorValue
abstract var actorValue: ActorValue
override fun equals(other: Any?) = referenceID == (other as Actor).referenceID
override fun hashCode() = referenceID
override fun toString() = "ActorID: ${hashCode()}"
override fun compareTo(other: Actor): Int = this.referenceID - other.referenceID
}

View File

@@ -16,7 +16,7 @@ import org.newdawn.slick.Graphics
*
* Created by minjaesong on 16-03-14.
*/
open class ActorWithBody constructor() : Actor, Visible, Glowing {
open class ActorWithBody constructor() : Actor(), Visible {
override var actorValue: ActorValue = ActorValue()
@@ -26,15 +26,13 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
var baseHitboxH: Int = 0
/**
* Velocity for newtonian sim.
* Fluctuation in, otherwise still, velocity is equal to acceleration.
* Velocity vector (broken down by axes) for newtonian sim.
* Acceleration: used in code like:
* veloY += 3.0
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
*/
@Volatile var veloX: Float = 0.toFloat()
@Volatile var veloY: Float = 0.toFloat()
var veloX: Float = 0.toFloat()
var veloY: Float = 0.toFloat()
@Transient private val VELO_HARD_LIMIT = 10000f
var grounded = false
@@ -61,16 +59,17 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
@Transient val nextHitbox = Hitbox(0f,0f,0f,0f)
/**
* Physical properties
* Physical properties.
* Values derived from ActorValue must be @Transient.
*/
@Volatile @Transient var scale = 1f
@Volatile @Transient var mass = 2f
@Transient var scale = 1f
@Transient var mass = 2f
@Transient private val MASS_LOWEST = 2f
/** Valid range: [0, 1] */
var elasticity = 0f
set(value) {
if (value < 0)
throw IllegalArgumentException("[ActorWithBody] $value: valid elasticity value is [0, 1].")
throw IllegalArgumentException("[ActorWithBody] Invalid elasticity value: $value; valid elasticity value is [0, 1].")
else if (value > 1) {
println("[ActorWithBody] Elasticity were capped to 1.")
field = ELASTICITY_MAX
@@ -89,11 +88,11 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
*/
@Transient private val METER = 24f
/**
* [m / s^2] * SI_TO_GAME_ACC -> [px / IFrame^2]
* [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
*/
@Transient private val SI_TO_GAME_ACC = METER / FastMath.sqr(Terrarum.TARGET_FPS.toFloat())
/**
* [m / s] * SI_TO_GAME_VEL -> [px / IFrame]
* [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame]
*/
@Transient private val SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS
@@ -131,6 +130,8 @@ open class ActorWithBody constructor() : Actor, Visible, Glowing {
@Transient private val MASS_DEFAULT = 60f
internal val physSleep: Boolean
get() = veloX.abs() < 0.5 && veloY.abs() < 0.5
private var posAdjustX = 0
private var posAdjustY = 0

View File

@@ -0,0 +1,104 @@
package net.torvald.terrarum.gameactors
import com.jme3.math.FastMath
import net.torvald.terrarum.Terrarum
import java.util.*
/**
* Created by minjaesong on 16-04-22.
*/
object CollisionSolver {
private const val STARTPOINT = 1
private const val ENDPOINT = 2
private const val COLL_LIST_SIZE = 256
private const val COLL_CANDIDATES_SIZE = 128
private const val COLL_FINAL_CANDIDATES_SIZE = 16
private val collListX = ArrayList<CollisionMarkings>(COLL_LIST_SIZE)
private val collListY = ArrayList<CollisionMarkings>(COLL_LIST_SIZE)
private val collCandidateX = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_CANDIDATES_SIZE)
private val collCandidateY = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_CANDIDATES_SIZE)
private val collCandidates = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_FINAL_CANDIDATES_SIZE)
/**
* @link https://www.toptal.com/game/video-game-physics-part-ii-collision-detection-for-solid-objects
*/
fun process() {
// mark list x
Terrarum.game.actorContainer.forEach { it ->
if (it is ActorWithBody) {
collListX.add(CollisionMarkings(it.hitbox.hitboxStart.x, STARTPOINT, it.referenceID))
collListX.add(CollisionMarkings(it.hitbox.hitboxEnd.x, ENDPOINT, it.referenceID))
}
}
// sort list x (will use Timsort with Java SE >= 8, Mergesort otherwise)
collListX.sortBy { it.pos }
// set candidateX
// mark list y
Terrarum.game.actorContainer.forEach { it ->
if (it is ActorWithBody) {
collListY.add(CollisionMarkings(it.hitbox.hitboxStart.y, STARTPOINT, it.referenceID))
collListY.add(CollisionMarkings(it.hitbox.hitboxEnd.y, ENDPOINT, it.referenceID))
}
}
// sort list y
collListY.sortBy { it.pos }
// set candidateY
// look for overlaps in candidate X/Y and put them into collCandidates
// solve collision for actors in collCandidates
}
private fun solveCollision(a: ActorWithBody, b: ActorWithBody) {
}
private infix fun ActorWithBody.isCollidingWith(other: ActorWithBody): Boolean {
val ax = this.hitbox.centeredX
val ay = this.hitbox.centeredY
val bx = other.hitbox.centeredX
val by = other.hitbox.centeredY
// will refer 'actor_dist_t' as 't' afterward
val actor_dist_t_sqr = ((ay - by).sqr() + (ax - bx).sqr()) // no sqrt; 'power' is slower than 'times'
val dist_x = (ax - bx).abs() // 'tx'
val dist_y = (ay - by).abs() // 'ty'
val tangent = dist_y / dist_x
var t_ax: Float; var t_ay: Float
if (dist_x > dist_y) {
t_ax = this.hitbox.width / 2
t_ay = t_ax * tangent
}
else {
t_ay = this.hitbox.height / 2
t_ax = t_ay * tangent
}
return (t_ax.sqr() + t_ay.sqr()) < actor_dist_t_sqr
}
fun Float.abs() = if (this < 0) -this else this
fun Float.sqr() = this * this
data class CollisionMarkings(
val pos: Float,
val kind: Int,
val actorID: Int
)
/**
* === Some useful physics knowledge ===
*
* * Momentum = mass × Velocity
*/
}

View File

@@ -1,13 +0,0 @@
package net.torvald.terrarum.gameactors
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
/**
* Created by minjaesong on 16-03-14.
*/
interface Glowing {
fun drawGlow(gc: GameContainer, g: Graphics)
fun updateGlowSprite(gc: GameContainer, delta: Int)
}

View File

@@ -15,7 +15,7 @@ class PhysTestBall : ActorWithBody {
constructor(): super() {
setHitboxDimension(16, 16, 0, 0)
isVisible = true
mass = 10f
actorValue[AVKey.BASEMASS] = 10f
color = RoguelikeRandomiser.composeColourFrom(RoguelikeRandomiser.POTION_PRIMARY_COLSET)
}
@@ -23,9 +23,9 @@ class PhysTestBall : ActorWithBody {
override fun drawBody(gc: GameContainer, g: Graphics) {
g.color = color
g.fillOval(
hitbox!!.posX,
hitbox!!.posY,
hitbox!!.width,
hitbox!!.height)
hitbox.posX,
hitbox.posY,
hitbox.width,
hitbox.height)
}
}

View File

@@ -12,4 +12,8 @@ interface Visible {
fun drawBody(gc: GameContainer, g: Graphics)
fun updateBodySprite(gc: GameContainer, delta: Int)
fun drawGlow(gc: GameContainer, g: Graphics)
fun updateGlowSprite(gc: GameContainer, delta: Int)
}