mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 02:54:04 +09:00
tiles with light level <= 1 will be rendered as black square, phys support for non-self-moving bodies (e.g. balls)
Former-commit-id: 5611e2d89f4601e57d014c45f0479600778217f6 Former-commit-id: d900c0733a6d1dcbd9aaed8e9f7f1671c3866624
This commit is contained in:
@@ -851,4 +851,16 @@ final public class FastMath {
|
|||||||
for (int i = 1; i < f.length; i++) max = (f[i] > max) ? f[i] : max;
|
for (int i = 1; i < f.length; i++) max = (f[i] > max) ? f[i] : max;
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int min(int... f) {
|
||||||
|
int min = f[0];
|
||||||
|
for (int i = 1; i < f.length; i++) min = (f[i] < min) ? f[i] : min;
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int max(int... f) {
|
||||||
|
int max = f[0];
|
||||||
|
for (int i = 1; i < f.length; i++) max = (f[i] > max) ? f[i] : max;
|
||||||
|
return max;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -703,7 +703,7 @@ constructor() : Font {
|
|||||||
Pair(0x14.toChar(), Color(0xFFA0E0)), //f uchsia
|
Pair(0x14.toChar(), Color(0xFFA0E0)), //f uchsia
|
||||||
Pair(0x15.toChar(), Color(0xE0A0FF)), //*m agenta (purple)
|
Pair(0x15.toChar(), Color(0xE0A0FF)), //*m agenta (purple)
|
||||||
Pair(0x16.toChar(), Color(0x8080FF)), //*b lue
|
Pair(0x16.toChar(), Color(0x8080FF)), //*b lue
|
||||||
Pair(0x17.toChar(), Color(0xFF80FF)), //c yan
|
Pair(0x17.toChar(), Color(0x80FFFF)), //c yan
|
||||||
Pair(0x18.toChar(), Color(0x80FF80)), //*g reen
|
Pair(0x18.toChar(), Color(0x80FF80)), //*g reen
|
||||||
Pair(0x19.toChar(), Color(0x008000)), //v iridian
|
Pair(0x19.toChar(), Color(0x008000)), //v iridian
|
||||||
Pair(0x1A.toChar(), Color(0x805030)), //x (khaki)
|
Pair(0x1A.toChar(), Color(0x805030)), //x (khaki)
|
||||||
|
|||||||
@@ -381,15 +381,35 @@ constructor() : BasicGameState() {
|
|||||||
actor.hitbox.posX.toFloat(),
|
actor.hitbox.posX.toFloat(),
|
||||||
actor.hitbox.pointedY.toFloat() + 4
|
actor.hitbox.pointedY.toFloat() + 4
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// debug physics
|
||||||
|
if (KeyToggler.isOn(Key.F11)) {
|
||||||
|
actorContainer.forEachIndexed { i, actor ->
|
||||||
|
if (actor is ActorWithSprite) {
|
||||||
|
worldG.color = Color(1f, 0f, 1f, 1f)
|
||||||
|
worldG.font = Terrarum.fontSmallNumbers
|
||||||
|
worldG.lineWidth = 1f
|
||||||
|
worldG.drawRect(
|
||||||
|
actor.hitbox.posX.toFloat(),
|
||||||
|
actor.hitbox.posY.toFloat(),
|
||||||
|
actor.hitbox.width.toFloat(),
|
||||||
|
actor.hitbox.height.toFloat()
|
||||||
|
)
|
||||||
|
|
||||||
if (DEBUG_ARRAY) {
|
// velocity
|
||||||
worldG.color = GameFontBase.codeToCol["g"]
|
worldG.color = Color(0x80FFFF)
|
||||||
worldG.drawString(
|
worldG.drawString(
|
||||||
i.toString(),
|
"vX ${actor.velocity.x}", // doesn't work for NPCs/Player
|
||||||
actor.hitbox.posX.toFloat(),
|
actor.hitbox.posX.toFloat(),
|
||||||
actor.hitbox.pointedY.toFloat() + 4 + 10
|
actor.hitbox.pointedY.toFloat() + 4 + 8
|
||||||
)
|
)
|
||||||
}
|
worldG.drawString(
|
||||||
|
"vY ${actor.velocity.y}",
|
||||||
|
actor.hitbox.posX.toFloat(),
|
||||||
|
actor.hitbox.pointedY.toFloat() + 4 + 8 * 2
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -674,17 +694,30 @@ constructor() : BasicGameState() {
|
|||||||
* Check for duplicates, append actor and sort the list
|
* Check for duplicates, append actor and sort the list
|
||||||
*/
|
*/
|
||||||
fun addActor(actor: Actor) {
|
fun addActor(actor: Actor) {
|
||||||
if (hasActor(actor.referenceID))
|
if (hasActor(actor.referenceID)) {
|
||||||
throw RuntimeException("Actor with ID ${actor.referenceID} already exists.")
|
println("[StateInGame] Replacing actor $actor")
|
||||||
actorContainer.add(actor)
|
removeActor(actor)
|
||||||
insertionSortLastElem(actorContainer) // we can do this as we are only adding single actor
|
addActor(actor)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
actorContainer.add(actor)
|
||||||
|
insertionSortLastElem(actorContainer) // we can do this as we are only adding single actor
|
||||||
|
|
||||||
if (actor is ActorVisible) {
|
if (actor is ActorVisible) {
|
||||||
when (actor.renderOrder) {
|
when (actor.renderOrder) {
|
||||||
ActorOrder.BEHIND -> { actorsRenderBehind.add(actor); insertionSortLastElemAV(actorsRenderBehind) }
|
ActorOrder.BEHIND -> {
|
||||||
ActorOrder.MIDDLE -> { actorsRenderMiddle.add(actor); insertionSortLastElemAV(actorsRenderMiddle) }
|
actorsRenderBehind.add(actor); insertionSortLastElemAV(actorsRenderBehind)
|
||||||
ActorOrder.MIDTOP -> { actorsRenderMidTop.add(actor); insertionSortLastElemAV(actorsRenderMidTop) }
|
}
|
||||||
ActorOrder.FRONT -> { actorsRenderFront .add(actor); insertionSortLastElemAV(actorsRenderFront ) }
|
ActorOrder.MIDDLE -> {
|
||||||
|
actorsRenderMiddle.add(actor); insertionSortLastElemAV(actorsRenderMiddle)
|
||||||
|
}
|
||||||
|
ActorOrder.MIDTOP -> {
|
||||||
|
actorsRenderMidTop.add(actor); insertionSortLastElemAV(actorsRenderMidTop)
|
||||||
|
}
|
||||||
|
ActorOrder.FRONT -> {
|
||||||
|
actorsRenderFront.add(actor); insertionSortLastElemAV(actorsRenderFront)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -693,11 +726,6 @@ constructor() : BasicGameState() {
|
|||||||
particlesContainer.add(particle)
|
particlesContainer.add(particle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the game should display actorContainer elem number when F3 is on
|
|
||||||
*/
|
|
||||||
val DEBUG_ARRAY = false
|
|
||||||
|
|
||||||
fun getActorByID(ID: Int): Actor {
|
fun getActorByID(ID: Int): Actor {
|
||||||
if (actorContainer.size == 0 && actorContainerInactive.size == 0)
|
if (actorContainer.size == 0 && actorContainerInactive.size == 0)
|
||||||
throw IllegalArgumentException("Actor with ID $ID does not exist.")
|
throw IllegalArgumentException("Actor with ID $ID does not exist.")
|
||||||
@@ -743,10 +771,11 @@ constructor() : BasicGameState() {
|
|||||||
private fun ArrayList<out Actor>.binarySearch(ID: Int): Int {
|
private fun ArrayList<out Actor>.binarySearch(ID: Int): Int {
|
||||||
// code from collections/Collections.kt
|
// code from collections/Collections.kt
|
||||||
var low = 0
|
var low = 0
|
||||||
var high = actorContainer.size - 1
|
var high = this.size - 1
|
||||||
|
|
||||||
while (low <= high) {
|
while (low <= high) {
|
||||||
val mid = (low + high).ushr(1) // safe from overflows
|
val mid = (low + high).ushr(1) // safe from overflows
|
||||||
|
|
||||||
val midVal = get(mid)
|
val midVal = get(mid)
|
||||||
|
|
||||||
if (ID > midVal.referenceID)
|
if (ID > midVal.referenceID)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import net.torvald.terrarum.gameactors.PhysTestBall
|
|||||||
import net.torvald.terrarum.mapdrawer.TilesDrawer
|
import net.torvald.terrarum.mapdrawer.TilesDrawer
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.mapdrawer.MapCamera
|
import net.torvald.terrarum.mapdrawer.MapCamera
|
||||||
|
import org.dyn4j.geometry.Vector2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-03-05.
|
* Created by minjaesong on 16-03-05.
|
||||||
@@ -13,10 +14,26 @@ import net.torvald.terrarum.mapdrawer.MapCamera
|
|||||||
internal object SpawnPhysTestBall : ConsoleCommand {
|
internal object SpawnPhysTestBall : ConsoleCommand {
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override fun execute(args: Array<String>) {
|
override fun execute(args: Array<String>) {
|
||||||
if (args.size == 2) {
|
val mouseX = Terrarum.appgc.input.mouseX
|
||||||
val mouseX = Terrarum.appgc.input.mouseX
|
val mouseY = Terrarum.appgc.input.mouseY
|
||||||
val mouseY = Terrarum.appgc.input.mouseY
|
|
||||||
|
|
||||||
|
if (args.size >= 3) {
|
||||||
|
val elasticity = args[1].toDouble()
|
||||||
|
|
||||||
|
val xvel = args[2].toDouble()
|
||||||
|
val yvel = if (args.size >= 4) args[3].toDouble() else 0.0
|
||||||
|
|
||||||
|
val ball = PhysTestBall()
|
||||||
|
ball.setPosition(
|
||||||
|
(mouseX + MapCamera.x).toDouble(),
|
||||||
|
(mouseY + MapCamera.y).toDouble()
|
||||||
|
)
|
||||||
|
ball.elasticity = elasticity
|
||||||
|
ball.applyForce(Vector2(xvel, yvel))
|
||||||
|
|
||||||
|
Terrarum.ingame.addActor(ball)
|
||||||
|
}
|
||||||
|
else if (args.size == 2) {
|
||||||
val elasticity = args[1].toDouble()
|
val elasticity = args[1].toDouble()
|
||||||
|
|
||||||
val ball = PhysTestBall()
|
val ball = PhysTestBall()
|
||||||
@@ -34,6 +51,6 @@ internal object SpawnPhysTestBall : ConsoleCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun printUsage() {
|
override fun printUsage() {
|
||||||
Echo("usage: spawnball [elasticity]")
|
Echo("usage: spawnball elasticity [x velocity] [y velocity]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.util.*
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Humanoid actor class to provide same controlling function (such as work, jump)
|
* Humanoid actor class to provide same controlling function (such as work, jump)
|
||||||
|
* Also applies unreal air friction for movement control
|
||||||
*
|
*
|
||||||
* Created by minjaesong on 16-10-24.
|
* Created by minjaesong on 16-10-24.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.torvald.spriteanimation.SpriteAnimation
|
|||||||
import net.torvald.terrarum.gamecontroller.Key
|
import net.torvald.terrarum.gamecontroller.Key
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
import net.torvald.terrarum.mapdrawer.FeaturesDrawer.TILE_SIZE
|
import net.torvald.terrarum.mapdrawer.FeaturesDrawer.TILE_SIZE
|
||||||
|
import net.torvald.terrarum.mapdrawer.MapCamera
|
||||||
import net.torvald.terrarum.tileproperties.Tile
|
import net.torvald.terrarum.tileproperties.Tile
|
||||||
import net.torvald.terrarum.tileproperties.TileProp
|
import net.torvald.terrarum.tileproperties.TileProp
|
||||||
import org.dyn4j.Epsilon
|
import org.dyn4j.Epsilon
|
||||||
@@ -19,17 +20,19 @@ import org.newdawn.slick.GameContainer
|
|||||||
import org.newdawn.slick.Graphics
|
import org.newdawn.slick.Graphics
|
||||||
import org.newdawn.slick.Image
|
import org.newdawn.slick.Image
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.reflect.jvm.internal.impl.resolve.constants.DoubleValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for every actor that has animated sprites. This includes furnishings, paintings, gadgets, etc.
|
* Base class for every actor that has animated sprites. This includes furnishings, paintings, gadgets, etc.
|
||||||
* Also has all the physics
|
* Also has all the physics
|
||||||
*
|
*
|
||||||
* @param renderOrder Rendering order (BEHIND, MIDDLE, MIDTOP, FRONT)
|
* @param renderOrder Rendering order (BEHIND, MIDDLE, MIDTOP, FRONT)
|
||||||
* @param physics
|
* @param immobileBody use realistic air friction (1/1000 of "unrealistic" canonical setup)
|
||||||
|
* @param physics use physics simulation
|
||||||
*
|
*
|
||||||
* Created by minjaesong on 16-01-13.
|
* Created by minjaesong on 16-01-13.
|
||||||
*/
|
*/
|
||||||
open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : ActorVisible(renderOrder) {
|
open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = false, physics: Boolean = true) : ActorVisible(renderOrder) {
|
||||||
|
|
||||||
/** !! ActorValue macros are on the very bottom of the source !! **/
|
/** !! ActorValue macros are on the very bottom of the source !! **/
|
||||||
|
|
||||||
@@ -343,6 +346,8 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
velocity += acc.times(speedMultByTile)
|
velocity += acc.times(speedMultByTile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val bounceDampenVelThreshold = 0.5
|
||||||
|
|
||||||
override fun update(gc: GameContainer, delta: Int) {
|
override fun update(gc: GameContainer, delta: Int) {
|
||||||
if (isUpdate && !flagDespawn) {
|
if (isUpdate && !flagDespawn) {
|
||||||
|
|
||||||
@@ -388,7 +393,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
}
|
}
|
||||||
|
|
||||||
setHorizontalFriction()
|
setHorizontalFriction()
|
||||||
if (isPlayerNoClip) { // TODO also hanging on the rope, etc.
|
if (immobileBody || isPlayerNoClip) { // TODO also hanging on the rope, etc.
|
||||||
setVerticalFriction()
|
setVerticalFriction()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,28 +429,28 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
// decide whether to ignore walkX
|
// decide whether to ignore walkX
|
||||||
if (!(isCollidingSide(hitbox, COLLIDING_LEFT) && walkX < 0)
|
if (!(isCollidingSide(hitbox, COLLIDING_LEFT) && walkX < 0)
|
||||||
|| !(isCollidingSide(hitbox, COLLIDING_RIGHT) && walkX > 0)
|
|| !(isCollidingSide(hitbox, COLLIDING_RIGHT) && walkX > 0)
|
||||||
) {
|
) {
|
||||||
moveDelta.x = veloX + walkX
|
moveDelta.x = veloX + walkX
|
||||||
}
|
}
|
||||||
|
|
||||||
// decide whether to ignore walkY
|
// decide whether to ignore walkY
|
||||||
if (!(isCollidingSide(hitbox, COLLIDING_TOP) && walkY < 0)
|
if (!(isCollidingSide(hitbox, COLLIDING_TOP) && walkY < 0)
|
||||||
|| !(isCollidingSide(hitbox, COLLIDING_BOTTOM) && walkY > 0)
|
|| !(isCollidingSide(hitbox, COLLIDING_BOTTOM) && walkY > 0)
|
||||||
) {
|
) {
|
||||||
moveDelta.y = veloY + walkY
|
moveDelta.y = veloY + walkY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!isCollidingSide(hitbox, COLLIDING_LEFT)
|
if (!isCollidingSide(hitbox, COLLIDING_LEFT)
|
||||||
|| !isCollidingSide(hitbox, COLLIDING_RIGHT)
|
|| !isCollidingSide(hitbox, COLLIDING_RIGHT)
|
||||||
) {
|
) {
|
||||||
moveDelta.x = veloX
|
moveDelta.x = veloX
|
||||||
}
|
}
|
||||||
|
|
||||||
// decide whether to ignore walkY
|
// decide whether to ignore walkY
|
||||||
if (!isCollidingSide(hitbox, COLLIDING_TOP)
|
if (!isCollidingSide(hitbox, COLLIDING_TOP)
|
||||||
|| !isCollidingSide(hitbox, COLLIDING_BOTTOM)
|
|| !isCollidingSide(hitbox, COLLIDING_BOTTOM)
|
||||||
) {
|
) {
|
||||||
moveDelta.y = veloY
|
moveDelta.y = veloY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -771,6 +776,13 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
return contactAreaCounter
|
return contactAreaCounter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getTileFriction(tile: Int) =
|
||||||
|
if (immobileBody && tile == Tile.AIR)
|
||||||
|
TileCodex[Tile.AIR].friction.frictionToMult().div(1000)
|
||||||
|
.times(if (!grounded) elasticity else 1.0)
|
||||||
|
else
|
||||||
|
TileCodex[tile].friction.frictionToMult()
|
||||||
|
|
||||||
/** about stopping
|
/** about stopping
|
||||||
* for about get moving, see updateMovementControl */
|
* for about get moving, see updateMovementControl */
|
||||||
private fun setHorizontalFriction() {
|
private fun setHorizontalFriction() {
|
||||||
@@ -778,7 +790,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
BASE_FRICTION * TileCodex[Tile.STONE].friction.frictionToMult()
|
BASE_FRICTION * TileCodex[Tile.STONE].friction.frictionToMult()
|
||||||
else {
|
else {
|
||||||
// TODO status quo if !submerged else linearBlend(feetFriction, bodyFriction, submergedRatio)
|
// TODO status quo if !submerged else linearBlend(feetFriction, bodyFriction, submergedRatio)
|
||||||
BASE_FRICTION * (if (grounded) feetFriction else bodyFriction).frictionToMult()
|
BASE_FRICTION * if (grounded) feetFriction else bodyFriction
|
||||||
}
|
}
|
||||||
|
|
||||||
if (veloX < 0) {
|
if (veloX < 0) {
|
||||||
@@ -806,7 +818,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
val friction = if (isPlayerNoClip)
|
val friction = if (isPlayerNoClip)
|
||||||
BASE_FRICTION * TileCodex[Tile.STONE].friction.frictionToMult()
|
BASE_FRICTION * TileCodex[Tile.STONE].friction.frictionToMult()
|
||||||
else
|
else
|
||||||
BASE_FRICTION * bodyFriction.frictionToMult()
|
BASE_FRICTION * bodyFriction
|
||||||
|
|
||||||
if (veloY < 0) {
|
if (veloY < 0) {
|
||||||
veloY += friction
|
veloY += friction
|
||||||
@@ -859,22 +871,24 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
).toDouble()
|
).toDouble()
|
||||||
|
|
||||||
|
|
||||||
internal val bodyFriction: Int
|
internal val bodyFriction: Double
|
||||||
get() {
|
get() {
|
||||||
var friction = 0
|
var friction = 0.0
|
||||||
forEachOccupyingTile { // get max friction
|
forEachOccupyingTileNum {
|
||||||
if (it?.friction ?: TileCodex[Tile.AIR].friction > friction)
|
// get max friction
|
||||||
friction = it?.friction ?: TileCodex[Tile.AIR].friction
|
if (getTileFriction(it ?: Tile.AIR) > friction)
|
||||||
|
friction = getTileFriction(it ?: Tile.AIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
return friction
|
return friction
|
||||||
}
|
}
|
||||||
internal val feetFriction: Int
|
internal val feetFriction: Double
|
||||||
get() {
|
get() {
|
||||||
var friction = 0
|
var friction = 0.0
|
||||||
forEachFeetTile { // get max friction
|
forEachFeetTileNum {
|
||||||
if (it?.friction ?: TileCodex[Tile.AIR].friction > friction)
|
// get max friction
|
||||||
friction = it?.friction ?: TileCodex[Tile.AIR].friction
|
if (getTileFriction(it ?: Tile.AIR) > friction)
|
||||||
|
friction = getTileFriction(it ?: Tile.AIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
return friction
|
return friction
|
||||||
@@ -885,7 +899,8 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
internal val bodyViscosity: Int
|
internal val bodyViscosity: Int
|
||||||
get() {
|
get() {
|
||||||
var viscosity = 0
|
var viscosity = 0
|
||||||
forEachOccupyingTile { // get max viscosity
|
forEachOccupyingTile {
|
||||||
|
// get max viscosity
|
||||||
if (it?.viscosity ?: 0 > viscosity)
|
if (it?.viscosity ?: 0 > viscosity)
|
||||||
viscosity = it?.viscosity ?: 0
|
viscosity = it?.viscosity ?: 0
|
||||||
}
|
}
|
||||||
@@ -895,7 +910,8 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
internal val feetViscosity: Int
|
internal val feetViscosity: Int
|
||||||
get() {
|
get() {
|
||||||
var viscosity = 0
|
var viscosity = 0
|
||||||
forEachFeetTile { // get max viscosity
|
forEachFeetTile {
|
||||||
|
// get max viscosity
|
||||||
if (it?.viscosity ?: 0 > viscosity)
|
if (it?.viscosity ?: 0 > viscosity)
|
||||||
viscosity = it?.viscosity ?: 0
|
viscosity = it?.viscosity ?: 0
|
||||||
}
|
}
|
||||||
@@ -921,9 +937,9 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
get() {
|
get() {
|
||||||
if (!isPlayerNoClip) {
|
if (!isPlayerNoClip) {
|
||||||
val notSubmergedAccel = if (grounded)
|
val notSubmergedAccel = if (grounded)
|
||||||
feetFriction.frictionToMult()
|
feetFriction
|
||||||
else
|
else
|
||||||
bodyFriction.frictionToMult()
|
bodyFriction
|
||||||
val normalisedViscocity = bodyViscosity.viscosityToMult()
|
val normalisedViscocity = bodyViscosity.viscosityToMult()
|
||||||
|
|
||||||
return interpolateLinear(submergedRatio, notSubmergedAccel, normalisedViscocity)
|
return interpolateLinear(submergedRatio, notSubmergedAccel, normalisedViscocity)
|
||||||
@@ -992,7 +1008,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
|
|
||||||
private fun updateHitbox() = hitbox.reassign(nextHitbox)
|
private fun updateHitbox() = hitbox.reassign(nextHitbox)
|
||||||
|
|
||||||
override open fun drawGlow(g: Graphics) {
|
override fun drawGlow(g: Graphics) {
|
||||||
if (isVisible && spriteGlow != null) {
|
if (isVisible && spriteGlow != null) {
|
||||||
blendLightenOnly()
|
blendLightenOnly()
|
||||||
|
|
||||||
@@ -1033,25 +1049,12 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// debug hitbox
|
|
||||||
if (KeyToggler.isOn(Key.F11)) {
|
|
||||||
g.color = Color(1f, 0f, 1f, 1f)
|
|
||||||
blendNormal()
|
|
||||||
g.lineWidth = 1f
|
|
||||||
g.drawRect(
|
|
||||||
hitbox.posX.toFloat(),
|
|
||||||
hitbox.posY.toFloat(),
|
|
||||||
hitbox.width.toFloat(),
|
|
||||||
hitbox.height.toFloat()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override open fun drawBody(g: Graphics) {
|
private val halfWorldW = world.width.times(TILE_SIZE).ushr(1)
|
||||||
if (isVisible && sprite != null) {
|
|
||||||
|
|
||||||
|
override fun drawBody(g: Graphics) {
|
||||||
|
if (isVisible && sprite != null) {
|
||||||
|
|
||||||
when (drawMode) {
|
when (drawMode) {
|
||||||
BLEND_NORMAL -> blendNormal()
|
BLEND_NORMAL -> blendNormal()
|
||||||
@@ -1282,7 +1285,9 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
|
|
||||||
var avBaseScale: Double // use canonical "scale" for apparent scale (base * buff)
|
var avBaseScale: Double // use canonical "scale" for apparent scale (base * buff)
|
||||||
get() = actorValue.getAsDouble(AVKey.SCALE) ?: 1.0
|
get() = actorValue.getAsDouble(AVKey.SCALE) ?: 1.0
|
||||||
set(value) { actorValue[AVKey.SCALE] = value }
|
set(value) {
|
||||||
|
actorValue[AVKey.SCALE] = value
|
||||||
|
}
|
||||||
/** Apparent strength */
|
/** Apparent strength */
|
||||||
var avStrength: Double
|
var avStrength: Double
|
||||||
get() = (actorValue.getAsDouble(AVKey.STRENGTH) ?: 0.0) *
|
get() = (actorValue.getAsDouble(AVKey.STRENGTH) ?: 0.0) *
|
||||||
@@ -1294,10 +1299,14 @@ open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : A
|
|||||||
}
|
}
|
||||||
var avBaseStrength: Double?
|
var avBaseStrength: Double?
|
||||||
get() = actorValue.getAsDouble(AVKey.STRENGTH)
|
get() = actorValue.getAsDouble(AVKey.STRENGTH)
|
||||||
set(value) { actorValue[AVKey.STRENGTH] = value!! }
|
set(value) {
|
||||||
|
actorValue[AVKey.STRENGTH] = value!!
|
||||||
|
}
|
||||||
var avBaseMass: Double
|
var avBaseMass: Double
|
||||||
get() = actorValue.getAsDouble(AVKey.BASEMASS) ?: MASS_DEFAULT
|
get() = actorValue.getAsDouble(AVKey.BASEMASS) ?: MASS_DEFAULT
|
||||||
set(value) { actorValue[AVKey.BASEMASS] = value }
|
set(value) {
|
||||||
|
actorValue[AVKey.BASEMASS] = value
|
||||||
|
}
|
||||||
val avAcceleration: Double
|
val avAcceleration: Double
|
||||||
get() = actorValue.getAsDouble(AVKey.ACCEL)!! *
|
get() = actorValue.getAsDouble(AVKey.ACCEL)!! *
|
||||||
actorValue.getAsDouble(AVKey.ACCELBUFF)!! *
|
actorValue.getAsDouble(AVKey.ACCELBUFF)!! *
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import net.torvald.spriteanimation.SpriteAnimation
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-06-17.
|
* Created by minjaesong on 16-06-17.
|
||||||
*/
|
*/
|
||||||
open class FixtureBase(physics: Boolean = true) : ActorWithSprite(ActorOrder.BEHIND, physics) {
|
open class FixtureBase(physics: Boolean = true) :
|
||||||
|
ActorWithSprite(ActorOrder.BEHIND, immobileBody = true, physics = physics) {
|
||||||
/**
|
/**
|
||||||
* 0: Open
|
* 0: Open
|
||||||
* 1: Blocked
|
* 1: Blocked
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import org.newdawn.slick.Input
|
|||||||
*
|
*
|
||||||
* Created by minjaesong on 16-10-10.
|
* Created by minjaesong on 16-10-10.
|
||||||
*/
|
*/
|
||||||
open class HistoricalFigure(val born: GameDate, val dead: GameDate? = null) : ActorWithSprite(ActorOrder.MIDDLE) {
|
open class HistoricalFigure(val born: GameDate, val dead: GameDate? = null, realAirFriction: Boolean = false) : ActorWithSprite(ActorOrder.MIDDLE, realAirFriction) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.actorValue["_bornyear"] = born.year
|
this.actorValue["_bornyear"] = born.year
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import org.newdawn.slick.Graphics
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-03-05.
|
* Created by minjaesong on 16-03-05.
|
||||||
*/
|
*/
|
||||||
class PhysTestBall : ActorWithSprite(ActorOrder.MIDDLE) {
|
class PhysTestBall : ActorWithSprite(ActorOrder.MIDDLE, immobileBody = true) {
|
||||||
|
|
||||||
private var color = Color.orange
|
private var color = Color.orange
|
||||||
|
|
||||||
|
|||||||
@@ -432,17 +432,12 @@ object LightmapRenderer {
|
|||||||
if (darken < 0 || darken >= COLOUR_RANGE_SIZE)
|
if (darken < 0 || darken >= COLOUR_RANGE_SIZE)
|
||||||
throw IllegalArgumentException("darken: out of range ($darken)")
|
throw IllegalArgumentException("darken: out of range ($darken)")
|
||||||
|
|
||||||
// use equation with magic number 6.5:
|
// use equation with magic number 9.0
|
||||||
// =>> val r = data.r() * (1f + brighten.r() * 6.5f) <<=
|
// smooooooth
|
||||||
// gives 8-visible-tile penetration of sunlight, fairly smooth,
|
|
||||||
// DOES NOT GO BELOW (2,2,2)
|
|
||||||
|
|
||||||
val r = data.r() * (1f - darken.r() * 6.5f)
|
val r = data.r() * (1f - darken.r() * 9.0f)
|
||||||
val g = data.g() * (1f - darken.g() * 6.5f)
|
val g = data.g() * (1f - darken.g() * 9.0f)
|
||||||
val b = data.b() * (1f - darken.b() * 6.5f)
|
val b = data.b() * (1f - darken.b() * 9.0f)
|
||||||
//val r = data.r() - darken.r()
|
|
||||||
//val g = data.g() - darken.g()
|
|
||||||
//val b = data.b() - darken.b()
|
|
||||||
|
|
||||||
return constructRGBFromFloat(r.clampZero(), g.clampZero(), b.clampZero())
|
return constructRGBFromFloat(r.clampZero(), g.clampZero(), b.clampZero())
|
||||||
}
|
}
|
||||||
@@ -629,6 +624,13 @@ object LightmapRenderer {
|
|||||||
private fun Float.clampChannel() = if (this > CHANNEL_MAX_DECIMAL) CHANNEL_MAX_DECIMAL else this
|
private fun Float.clampChannel() = if (this > CHANNEL_MAX_DECIMAL) CHANNEL_MAX_DECIMAL else this
|
||||||
|
|
||||||
fun getValueFromMap(x: Int, y: Int): Int? = getLight(x, y)
|
fun getValueFromMap(x: Int, y: Int): Int? = getLight(x, y)
|
||||||
|
fun getLowestRGB(x: Int, y: Int): Int? {
|
||||||
|
val value = getLight(x, y)
|
||||||
|
if (value == null)
|
||||||
|
return null
|
||||||
|
else
|
||||||
|
return FastMath.min(value.rawR(), value.rawG(), value.rawB())
|
||||||
|
}
|
||||||
|
|
||||||
private fun purgeLightmap() {
|
private fun purgeLightmap() {
|
||||||
for (y in 0..LIGHTMAP_HEIGHT - 1) {
|
for (y in 0..LIGHTMAP_HEIGHT - 1) {
|
||||||
|
|||||||
@@ -11,14 +11,18 @@ object MapCamera {
|
|||||||
private val world: GameWorld = Terrarum.ingame.world
|
private val world: GameWorld = Terrarum.ingame.world
|
||||||
private val TILE_SIZE = FeaturesDrawer.TILE_SIZE
|
private val TILE_SIZE = FeaturesDrawer.TILE_SIZE
|
||||||
|
|
||||||
var x = 0
|
var x: Int = 0
|
||||||
private set
|
private set
|
||||||
var y = 0
|
var y: Int = 0
|
||||||
private set
|
private set
|
||||||
var width: Int = 0
|
var width: Int = 0
|
||||||
private set
|
private set
|
||||||
var height: Int = 0
|
var height: Int = 0
|
||||||
private set
|
private set
|
||||||
|
val xCentre: Int
|
||||||
|
get() = x + width.ushr(1)
|
||||||
|
val yCentre: Int
|
||||||
|
get() = y + height.ushr(1)
|
||||||
|
|
||||||
fun update() {
|
fun update() {
|
||||||
val player = Terrarum.ingame.player
|
val player = Terrarum.ingame.player
|
||||||
|
|||||||
@@ -278,6 +278,8 @@ object TilesDrawer {
|
|||||||
blendNormal()
|
blendNormal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val tileDrawLightThreshold = 2
|
||||||
|
|
||||||
private fun drawTiles(g: Graphics, mode: Int, drawModeTilesBlendMul: Boolean) {
|
private fun drawTiles(g: Graphics, mode: Int, drawModeTilesBlendMul: Boolean) {
|
||||||
val for_y_start = y / TILE_SIZE
|
val for_y_start = y / TILE_SIZE
|
||||||
val for_y_end = TilesDrawer.clampHTile(for_y_start + (height / TILE_SIZE) + 2)
|
val for_y_end = TilesDrawer.clampHTile(for_y_start + (height / TILE_SIZE) + 2)
|
||||||
@@ -305,59 +307,72 @@ object TilesDrawer {
|
|||||||
|
|
||||||
// draw
|
// draw
|
||||||
try {
|
try {
|
||||||
if (
|
if ((mode == WALL || mode == TERRAIN) && // not an air tile
|
||||||
(mode == WALL || mode == TERRAIN) && // not an air tile
|
(thisTile ?: 0) != Tile.AIR) {
|
||||||
(thisTile ?: 0) > 0) //&& // commented out: meh
|
|
||||||
// check if light level of nearby or this tile is illuminated
|
// check if light level of nearby or this tile is illuminated
|
||||||
/*( LightmapRenderer.getValueFromMap(x, y) ?: 0 > 0 ||
|
if ( LightmapRenderer.getLowestRGB(x, y) ?: 0 >= tileDrawLightThreshold ||
|
||||||
LightmapRenderer.getValueFromMap(x - 1, y) ?: 0 > 0 ||
|
LightmapRenderer.getLowestRGB(x - 1, y) ?: 0 >= tileDrawLightThreshold ||
|
||||||
LightmapRenderer.getValueFromMap(x + 1, y) ?: 0 > 0 ||
|
LightmapRenderer.getLowestRGB(x + 1, y) ?: 0 >= tileDrawLightThreshold ||
|
||||||
LightmapRenderer.getValueFromMap(x, y - 1) ?: 0 > 0 ||
|
LightmapRenderer.getLowestRGB(x, y - 1) ?: 0 >= tileDrawLightThreshold ||
|
||||||
LightmapRenderer.getValueFromMap(x, y + 1) ?: 0 > 0 ||
|
LightmapRenderer.getLowestRGB(x, y + 1) ?: 0 >= tileDrawLightThreshold ||
|
||||||
LightmapRenderer.getValueFromMap(x - 1, y - 1) ?: 0 > 0 ||
|
LightmapRenderer.getLowestRGB(x - 1, y - 1) ?: 0 >= tileDrawLightThreshold ||
|
||||||
LightmapRenderer.getValueFromMap(x + 1, y + 1) ?: 0 > 0 ||
|
LightmapRenderer.getLowestRGB(x + 1, y + 1) ?: 0 >= tileDrawLightThreshold ||
|
||||||
LightmapRenderer.getValueFromMap(x + 1, y - 1) ?: 0 > 0 ||
|
LightmapRenderer.getLowestRGB(x + 1, y - 1) ?: 0 >= tileDrawLightThreshold ||
|
||||||
LightmapRenderer.getValueFromMap(x - 1, y + 1) ?: 0 > 0)
|
LightmapRenderer.getLowestRGB(x - 1, y + 1) ?: 0 >= tileDrawLightThreshold) {
|
||||||
)*/ {
|
// blackness
|
||||||
val nearbyTilesInfo: Int
|
/*if (zeroTileCounter > 0) {
|
||||||
if (isPlatform(thisTile)) {
|
g.color = Color.black
|
||||||
nearbyTilesInfo = getNearbyTilesInfoPlatform(x, y)
|
g.fillRect(
|
||||||
}
|
(x - zeroTileCounter) * TILE_SIZE.toFloat(), y * TILE_SIZE.toFloat(),
|
||||||
else if (isWallSticker(thisTile)) {
|
zeroTileCounter * TILE_SIZE.toFloat(), TILE_SIZE.toFloat()
|
||||||
nearbyTilesInfo = getNearbyTilesInfoWallSticker(x, y)
|
)
|
||||||
}
|
g.color = Color.white
|
||||||
else if (isConnectMutual(thisTile)) {
|
zeroTileCounter = 0
|
||||||
nearbyTilesInfo = getNearbyTilesInfoNonSolid(x, y, mode)
|
}*/
|
||||||
}
|
|
||||||
else if (isConnectSelf(thisTile)) {
|
|
||||||
nearbyTilesInfo = getNearbyTilesInfo(x, y, mode, thisTile)
|
val nearbyTilesInfo: Int
|
||||||
}
|
if (isPlatform(thisTile)) {
|
||||||
|
nearbyTilesInfo = getNearbyTilesInfoPlatform(x, y)
|
||||||
|
}
|
||||||
|
else if (isWallSticker(thisTile)) {
|
||||||
|
nearbyTilesInfo = getNearbyTilesInfoWallSticker(x, y)
|
||||||
|
}
|
||||||
|
else if (isConnectMutual(thisTile)) {
|
||||||
|
nearbyTilesInfo = getNearbyTilesInfoNonSolid(x, y, mode)
|
||||||
|
}
|
||||||
|
else if (isConnectSelf(thisTile)) {
|
||||||
|
nearbyTilesInfo = getNearbyTilesInfo(x, y, mode, thisTile)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nearbyTilesInfo = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val thisTileX: Int
|
||||||
|
if (!noDamageLayer)
|
||||||
|
thisTileX = PairedMapLayer.RANGE * ((thisTile ?: 0) % PairedMapLayer.RANGE) + nearbyTilesInfo
|
||||||
|
else
|
||||||
|
thisTileX = nearbyTilesInfo
|
||||||
|
|
||||||
|
val thisTileY = (thisTile ?: 0) / PairedMapLayer.RANGE
|
||||||
|
|
||||||
|
if (drawModeTilesBlendMul) {
|
||||||
|
if (TilesDrawer.isBlendMul(thisTile)) {
|
||||||
|
drawTile(mode, x, y, thisTileX, thisTileY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// do NOT add "if (!isBlendMul(thisTile))"!
|
||||||
|
// or else they will not look like they should be when backed with wall
|
||||||
|
drawTile(mode, x, y, thisTileX, thisTileY)
|
||||||
|
}
|
||||||
|
} // end if (is illuminated)
|
||||||
else {
|
else {
|
||||||
nearbyTilesInfo = 0
|
zeroTileCounter++
|
||||||
|
drawTile(mode, x, y, 1, 0) // black patch
|
||||||
}
|
}
|
||||||
|
} // end if (not an air)
|
||||||
|
|
||||||
val thisTileX: Int
|
|
||||||
if (!noDamageLayer)
|
|
||||||
thisTileX = PairedMapLayer.RANGE * ((thisTile ?: 0) % PairedMapLayer.RANGE) + nearbyTilesInfo
|
|
||||||
else
|
|
||||||
thisTileX = nearbyTilesInfo
|
|
||||||
|
|
||||||
val thisTileY = (thisTile ?: 0) / PairedMapLayer.RANGE
|
|
||||||
|
|
||||||
if (drawModeTilesBlendMul) {
|
|
||||||
if (TilesDrawer.isBlendMul(thisTile)) {
|
|
||||||
drawTile(mode, x, y, thisTileX, thisTileY)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// do NOT add "if (!isBlendMul(thisTile))"!
|
|
||||||
// or else they will not look like they should be when backed with wall
|
|
||||||
drawTile(mode, x, y, thisTileX, thisTileY)
|
|
||||||
}
|
|
||||||
} // end if (not an air and is illuminated)
|
|
||||||
else {
|
|
||||||
zeroTileCounter++
|
|
||||||
}
|
|
||||||
} catch (e: NullPointerException) {
|
} catch (e: NullPointerException) {
|
||||||
// do nothing. WARNING: This exception handling may hide erratic behaviour completely.
|
// do nothing. WARNING: This exception handling may hide erratic behaviour completely.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ object WeatherMixer {
|
|||||||
lateinit var mixedWeather: BaseModularWeather
|
lateinit var mixedWeather: BaseModularWeather
|
||||||
|
|
||||||
val globalLightNow = Color(0)
|
val globalLightNow = Color(0)
|
||||||
|
private val world = Terrarum.ingame.world
|
||||||
|
|
||||||
// Weather indices
|
// Weather indices
|
||||||
const val WEATHER_GENERIC = "generic"
|
const val WEATHER_GENERIC = "generic"
|
||||||
@@ -90,9 +91,17 @@ object WeatherMixer {
|
|||||||
)
|
)
|
||||||
Terrarum.ingame.addParticle(rainParticle)
|
Terrarum.ingame.addParticle(rainParticle)
|
||||||
}
|
}
|
||||||
|
globalLightNow.set(getGlobalLightOfTime(world.time.elapsedSeconds).darker(0.3f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Color.set(other: Color) {
|
||||||
|
this.r = other.r
|
||||||
|
this.g = other.g
|
||||||
|
this.b = other.b
|
||||||
|
this.a = other.a
|
||||||
|
}
|
||||||
|
|
||||||
fun render(g: Graphics) {
|
fun render(g: Graphics) {
|
||||||
|
|
||||||
// we will not care for nextSkybox for now
|
// we will not care for nextSkybox for now
|
||||||
|
|||||||
Reference in New Issue
Block a user