ability to change current player as other NPC (maybe… maybe not…)

Former-commit-id: 54773bfa17456aaf42003c1d514e80dd860f58eb
Former-commit-id: e84f8312c99cff0e0692a492b7b850d09ffe4e44
This commit is contained in:
Song Minjae
2016-10-23 17:21:20 +09:00
parent 2b31bb962a
commit 9e8171b5b9
12 changed files with 106 additions and 30 deletions

View File

@@ -58,7 +58,9 @@ constructor() : BasicGameState() {
lateinit var debugWindow: UIHandler lateinit var debugWindow: UIHandler
lateinit var notifier: UIHandler lateinit var notifier: UIHandler
lateinit internal var player: Player lateinit internal var playerWrapper: AnyPlayer
internal val player: HistoricalFigure // currently POSSESSED actor :)
get() = playerWrapper.actor
//private var GRADIENT_IMAGE: Image? = null //private var GRADIENT_IMAGE: Image? = null
//private var skyBox: Rectangle? = null //private var skyBox: Rectangle? = null
@@ -119,7 +121,7 @@ constructor() : BasicGameState() {
// add new player and put it to actorContainer // add new player and put it to actorContainer
player = PBSigrid.create() playerWrapper = AnyPlayer(PBSigrid.create())
//player = PBCynthia.create() //player = PBCynthia.create()
//player.setNoClip(true); //player.setNoClip(true);
addActor(player) addActor(player)
@@ -199,6 +201,8 @@ constructor() : BasicGameState() {
/////////////////////////// ///////////////////////////
// actor-related updates // // actor-related updates //
/////////////////////////// ///////////////////////////
repossessActor()
// determine whether the inactive actor should be re-active // determine whether the inactive actor should be re-active
wakeDormantActors() wakeDormantActors()
// determine whether the actor should be active or dormant // determine whether the actor should be active or dormant
@@ -226,6 +230,31 @@ constructor() : BasicGameState() {
Terrarum.gameConfig["smoothlighting"] = KeyToggler.isOn(KEY_LIGHTMAP_SMOOTH) Terrarum.gameConfig["smoothlighting"] = KeyToggler.isOn(KEY_LIGHTMAP_SMOOTH)
} }
private fun repossessActor() {
// check if currently pocessed actor is removed from game
if (!hasActor(player))
// re-possess canonical player
changePossession(Player.PLAYER_REF_ID) // TODO completely other behaviour?
}
private fun changePossession(newActor: AnyPlayer) {
if (!hasActor(player)) {
throw IllegalArgumentException("No such actor in actorContainer: $newActor")
}
playerWrapper = newActor
WorldSimulator(world, player, UPDATE_DELTA)
}
private fun changePossession(refid: Int) {
if (!hasActor(refid)) {
throw IllegalArgumentException("No such actor in actorContainer: $refid")
}
playerWrapper = AnyPlayer(getActorByID(refid) as HistoricalFigure)
WorldSimulator(world, player, UPDATE_DELTA)
}
private fun setAppTitle() { private fun setAppTitle() {
Terrarum.appgc.setTitle( Terrarum.appgc.setTitle(
"${Terrarum.NAME}" + "${Terrarum.NAME}" +
@@ -319,7 +348,7 @@ constructor() : BasicGameState() {
} }
// fluidmap debug // fluidmap debug
if (KeyToggler.isOn(Key.F4)) if (KeyToggler.isOn(Key.F4))
WorldSimulator.drawFluidMapDebug(player, g) WorldSimulator.drawFluidMapDebug(g)
////////////// //////////////
@@ -482,7 +511,7 @@ constructor() : BasicGameState() {
fun Double.sqr() = this * this fun Double.sqr() = this * this
fun Int.sqr() = this * this fun Int.sqr() = this * this
private fun distToActorSqr(a: Visible, p: Player): Double = private fun distToActorSqr(a: Visible, p: ActorWithBody): Double =
(a.hitbox.centeredX - p.hitbox.centeredX).sqr() + (a.hitbox.centeredY - p.hitbox.centeredY).sqr() (a.hitbox.centeredX - p.hitbox.centeredX).sqr() + (a.hitbox.centeredY - p.hitbox.centeredY).sqr()
/** whether the actor is within screen */ /** whether the actor is within screen */
private fun Visible.inScreen() = distToActorSqr(this, player) <= private fun Visible.inScreen() = distToActorSqr(this, player) <=

View File

@@ -3,6 +3,8 @@ package net.torvald.terrarum.gameactors
import net.torvald.terrarum.gameactors.ai.ActorAI import net.torvald.terrarum.gameactors.ai.ActorAI
/** /**
* Note: AI-controlled actor must be 'Controllable'
*
* Created by minjaesong on 16-03-14. * Created by minjaesong on 16-03-14.
*/ */
interface AIControlled { interface AIControlled {

View File

@@ -443,8 +443,7 @@ open class ActorWithBody : Actor(), Visible {
else if (moveDelta.y < 0.0) { // or was moving upward? else if (moveDelta.y < 0.0) { // or was moving upward?
grounded = false grounded = false
if (isTouchingSide(nextHitbox, COLLIDING_TOP)) { // actor hit something on its top if (isTouchingSide(nextHitbox, COLLIDING_TOP)) { // actor hit something on its top
//hitAndForciblyReflectY() hitAndForciblyReflectY() // prevents sticking to the ceiling
hitAndReflectY()
} }
else { // the actor is not grounded at all else { // the actor is not grounded at all
} }
@@ -507,7 +506,9 @@ open class ActorWithBody : Actor(), Visible {
} }
} }
@Deprecated("it's no use!") /**
* prevents sticking to the ceiling
*/
private fun hitAndForciblyReflectY() { private fun hitAndForciblyReflectY() {
if (veloY.abs() * CEILING_HIT_ELASTICITY > A_PIXEL) if (veloY.abs() * CEILING_HIT_ELASTICITY > A_PIXEL)
veloY = -veloY * CEILING_HIT_ELASTICITY veloY = -veloY * CEILING_HIT_ELASTICITY
@@ -965,7 +966,7 @@ open class ActorWithBody : Actor(), Visible {
private fun assertInit() { private fun assertInit() {
// errors // errors
if (baseHitboxW == 0 || baseHitboxH == 0) if (baseHitboxW == 0 || baseHitboxH == 0)
throw RuntimeException("Hitbox dimension was not set.") throw Error("Hitbox dimension was not set.")
// warnings // warnings
if (sprite == null && isVisible) if (sprite == null && isVisible)

View File

@@ -0,0 +1,23 @@
package net.torvald.terrarum.gameactors
import org.newdawn.slick.Input
/**
* Created by minjaesong on 16-10-23.
*/
class AnyPlayer(val actor: HistoricalFigure) {
init {
if (actor !is Controllable)
throw IllegalArgumentException("Player must be 'Controllable'!")
}
fun processInput(input: Input) {
(actor as Controllable).processInput(input)
}
fun keyPressed(key: Int, c: Char) {
(actor as Controllable).keyPressed(key, c)
}
}

View File

@@ -1,14 +1,17 @@
package net.torvald.terrarum.gameactors package net.torvald.terrarum.gameactors
import net.torvald.terrarum.gameworld.WorldTime import net.torvald.terrarum.gameworld.WorldTime
import org.newdawn.slick.Input
/** /**
* An actor (NPC) which has life and death, * An actor (NPC) which has life and death,
* though death might not exist if it has achieved immortality :) * though death might not exist if it has achieved immortality :)
* *
* NOTE: all canonical NPCs are must be HistoricalFigure!! (double excl mark, bitch)
*
* Created by minjaesong on 16-10-10. * Created by minjaesong on 16-10-10.
*/ */
open class HistoricalFigure(born: GameDate, dead: GameDate? = null) : ActorWithBody() { open class HistoricalFigure(val born: GameDate, val dead: GameDate? = null) : ActorWithBody(), Controllable {
init { init {
this.actorValue["_bornyear"] = born.year this.actorValue["_bornyear"] = born.year
@@ -20,6 +23,21 @@ open class HistoricalFigure(born: GameDate, dead: GameDate? = null) : ActorWithB
} }
} }
override fun processInput(input: Input) {
// let out children play
}
override fun keyPressed(key: Int, c: Char) {
// let out children play
}
open internal var noClip = false
open fun isNoClip() = noClip
open fun setNoClip(b: Boolean) {
noClip = b
}
} }
data class GameDate(val year: Int, val yearlyDay: Int) { data class GameDate(val year: Int, val yearlyDay: Int) {

View File

@@ -46,7 +46,7 @@ object PBSigrid {
* fixed value, or 'base value', from creature strength of Dwarf Fortress. * fixed value, or 'base value', from creature strength of Dwarf Fortress.
* Human race uses 1000. (see CreatureHuman.json) * Human race uses 1000. (see CreatureHuman.json)
*/ */
p.actorValue[AVKey.STRENGTH] = 1414 p.actorValue[AVKey.STRENGTH] = 1414 // this is test character, after all.
p.actorValue[AVKey.ENCUMBRANCE] = 1000 p.actorValue[AVKey.ENCUMBRANCE] = 1000
p.actorValue[AVKey.BASEHEIGHT] = 46 p.actorValue[AVKey.BASEHEIGHT] = 46
@@ -59,8 +59,8 @@ object PBSigrid {
p.actorValue[AVKey.BASEDEFENCE] = 141 p.actorValue[AVKey.BASEDEFENCE] = 141
p.actorValue[AVKey.__PLAYER_QUICKBARSEL] = 0 p.actorValue[AVKey.__PLAYER_QUICKBARSEL] = 0
p.actorValue["__selectedtile"] = 16 // test code; replace with <tile_item>.primaryUse(gc, delta) p.actorValue["__selectedtile"] = 147 // test code; replace with <tile_item>.primaryUse(gc, delta)
p.actorValue["__aimhelper"] = true p.actorValue["__aimhelper"] = true // TODO when you'll gonna implement it?
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 10, 0) p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 10, 0)

View File

@@ -16,6 +16,8 @@ import org.newdawn.slick.SlickException
import java.util.* import java.util.*
/** /**
* Game player (YOU!)
*
* Created by minjaesong on 16-03-14. * Created by minjaesong on 16-03-14.
*/ */
@@ -53,7 +55,7 @@ class Player(born: GameDate) : HistoricalFigure(born), Controllable, Pocketed, F
@Transient private var prevHMoveKey = KEY_NULL @Transient private var prevHMoveKey = KEY_NULL
@Transient private var prevVMoveKey = KEY_NULL @Transient private var prevVMoveKey = KEY_NULL
internal var noClip = false override internal var noClip = false
@Transient private val AXIS_POSMAX = 1.0f @Transient private val AXIS_POSMAX = 1.0f
@Transient private val GAMEPAD_JUMP = 7 @Transient private val GAMEPAD_JUMP = 7
@@ -491,11 +493,11 @@ class Player(born: GameDate) : HistoricalFigure(born), Controllable, Pocketed, F
} }
} }
fun isNoClip(): Boolean { override fun isNoClip(): Boolean {
return noClip return noClip
} }
fun setNoClip(b: Boolean) { override fun setNoClip(b: Boolean) {
noClip = b noClip = b
} }

View File

@@ -11,9 +11,8 @@ object PlayerBuilder {
private val JSONPATH = "./assets/raw/" private val JSONPATH = "./assets/raw/"
private val jsonString = String() private val jsonString = String()
@Throws(IOException::class, SlickException::class) fun create(): Actor {
fun create(): Player { val p: Actor = Player(Terrarum.ingame.world.time.currentTimeAsGameDate)
val p: Player = Player(Terrarum.ingame.world.time.currentTimeAsGameDate)
CreatureRawInjector.inject(p.actorValue, "CreatureHuman.json") CreatureRawInjector.inject(p.actorValue, "CreatureHuman.json")
// attach sprite // attach sprite

View File

@@ -32,8 +32,8 @@ object GameController {
if (!Terrarum.ingame.consoleHandler.isTakingControl) { if (!Terrarum.ingame.consoleHandler.isTakingControl) {
if (Terrarum.ingame.player.vehicleRiding != null) { if (Terrarum.ingame.player is Player && (Terrarum.ingame.player as Player).vehicleRiding != null) {
Terrarum.ingame.player.vehicleRiding!!.processInput(input) (Terrarum.ingame.player as Player).vehicleRiding!!.processInput(input)
} }
Terrarum.ingame.player.processInput(input) Terrarum.ingame.player.processInput(input)
@@ -83,8 +83,8 @@ object GameController {
if (!Terrarum.ingame.consoleHandler.isTakingControl) { if (!Terrarum.ingame.consoleHandler.isTakingControl) {
if (Terrarum.ingame.player.vehicleRiding != null) { if (Terrarum.ingame.player is Player && (Terrarum.ingame.player as Player).vehicleRiding != null) {
Terrarum.ingame.player.vehicleRiding!!.keyPressed(key, c) (Terrarum.ingame.player as Player).vehicleRiding!!.keyPressed(key, c)
} }
Terrarum.ingame.player.keyPressed(key, c) Terrarum.ingame.player.keyPressed(key, c)

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.gameworld
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.HistoricalFigure
import net.torvald.terrarum.gameactors.Player import net.torvald.terrarum.gameactors.Player
import net.torvald.terrarum.gameactors.roundInt import net.torvald.terrarum.gameactors.roundInt
import net.torvald.terrarum.gameworld.WorldSimulator.isSolid import net.torvald.terrarum.gameworld.WorldSimulator.isSolid
@@ -37,14 +38,15 @@ object WorldSimulator {
val colourNone = Color(0x808080) val colourNone = Color(0x808080)
val colourWater = Color(0x66BBFF) val colourWater = Color(0x66BBFF)
operator fun invoke(world: GameWorld, p: Player, delta: Int) { // TODO future Kotlin feature -- typealias AnyPlayer: HistoricalFigure
operator fun invoke(world: GameWorld, p: HistoricalFigure, delta: Int) {
updateXFrom = p.hitbox.centeredX.div(MapDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt() updateXFrom = p.hitbox.centeredX.div(MapDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
updateYFrom = p.hitbox.centeredY.div(MapDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt() updateYFrom = p.hitbox.centeredY.div(MapDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
updateXTo = updateXFrom + DOUBLE_RADIUS updateXTo = updateXFrom + DOUBLE_RADIUS
updateYTo = updateYFrom + DOUBLE_RADIUS updateYTo = updateYFrom + DOUBLE_RADIUS
moveFluids(world, p, delta) moveFluids(world, delta)
displaceFallables(world, p, delta) displaceFallables(world, delta)
} }
/** /**
@@ -52,7 +54,7 @@ object WorldSimulator {
* which means you'll need to modify the code A LOT if you're going to implement zero- or * which means you'll need to modify the code A LOT if you're going to implement zero- or
* reverse-gravity. * reverse-gravity.
*/ */
fun moveFluids(world: GameWorld, p: Player, delta: Int) { fun moveFluids(world: GameWorld, delta: Int) {
//////////////////// ////////////////////
// build fluidmap // // build fluidmap //
//////////////////// ////////////////////
@@ -121,7 +123,7 @@ object WorldSimulator {
* displace fallable tiles. It is scanned bottom-left first. To achieve the sens ofreal * displace fallable tiles. It is scanned bottom-left first. To achieve the sens ofreal
* falling, each tiles are displaced by ONLY ONE TILE below. * falling, each tiles are displaced by ONLY ONE TILE below.
*/ */
fun displaceFallables(world: GameWorld, p: Player, delta: Int) { fun displaceFallables(world: GameWorld, delta: Int) {
for (y in updateYFrom..updateYTo) { for (y in updateYFrom..updateYTo) {
for (x in updateXFrom..updateXTo) { for (x in updateXFrom..updateXTo) {
val tile = world.getTileFromTerrain(x, y) ?: TileNameCode.STONE val tile = world.getTileFromTerrain(x, y) ?: TileNameCode.STONE
@@ -146,7 +148,7 @@ object WorldSimulator {
} }
} }
fun drawFluidMapDebug(p: Player, g: Graphics) { fun drawFluidMapDebug(g: Graphics) {
g.font = Terrarum.fontSmallNumbers g.font = Terrarum.fontSmallNumbers
g.color = colourWater g.color = colourWater

View File

@@ -100,7 +100,7 @@ class BasicDebugInfoWindow : UICanvas {
printLine(g, 5, "grounded $ccG${player.grounded}") printLine(g, 5, "grounded $ccG${player.grounded}")
printLine(g, 6, "noClip $ccG${player.noClip}") printLine(g, 6, "noClip $ccG${player.noClip}")
printLine(g, 7, "jump $ccG${player.jumpAcc}") //printLine(g, 7, "jump $ccG${player.jumpAcc}")
val lightVal: String val lightVal: String
val mtX = mouseTileX.toString() val mtX = mouseTileX.toString()

View File

@@ -24,7 +24,7 @@ class UIQuickBar : UICanvas, MouseControlled {
override var handler: UIHandler? = null override var handler: UIHandler? = null
private var selection: Int private var selection: Int
get() = Terrarum.ingame.player.actorValue.getAsInt(AVKey.__PLAYER_QUICKBARSEL)!! get() = Terrarum.ingame.player.actorValue.getAsInt(AVKey.__PLAYER_QUICKBARSEL) ?: 0
set(value) { Terrarum.ingame.player.actorValue[AVKey.__PLAYER_QUICKBARSEL] = value } set(value) { Terrarum.ingame.player.actorValue[AVKey.__PLAYER_QUICKBARSEL] = value }
override fun update(gc: GameContainer, delta: Int) { override fun update(gc: GameContainer, delta: Int) {