AI auto jump test

Former-commit-id: f48972fa48a526e8f697a47cde90b26240f549a3
Former-commit-id: c45dcbcae2f7d85c801ed87c049c403609a6d6d0
This commit is contained in:
Song Minjae
2017-01-07 00:37:46 +09:00
parent aab8da6ac7
commit e499c24c0d
11 changed files with 96 additions and 63 deletions

View File

@@ -49,5 +49,6 @@ class Point2d(var x: Double, var y: Double) : Cloneable {
fun toVector() = Vector2(x, y)
fun length(other: Point2d) = ((this.x - other.x).sqr() + (this.y - other.y).sqr()).sqrt()
fun length(other: Point2d) = distSqr(other).sqrt()
fun distSqr(other: Point2d) = ((this.x - other.x).sqr() + (this.y - other.y).sqr())
}

View File

@@ -533,7 +533,7 @@ constructor() : BasicGameState() {
* NOTE: concurrency for actor updating is currently disabled because of it's poor performance
*/
fun updateActors(gc: GameContainer, delta: Int) {
if (false) { // don't multithread this for now, it's SLOWER //if (Terrarum.MULTITHREAD) {
if (false) { // don't multithread this for now, it's SLOWER //if (Terrarum.MULTITHREAD && actorContainer.size > Terrarum.THREADS) {
val actors = actorContainer.size.toFloat()
// set up indices
for (i in 0..Terrarum.THREADS - 1) {

View File

@@ -62,8 +62,8 @@ internal object Teleport : ConsoleCommand {
}
fromActor.setPosition(
targetActor.feetPosition.x,
targetActor.feetPosition.y
targetActor.feetPosVector.x,
targetActor.feetPosVector.y
)
}
else if (args.size == 5) {

View File

@@ -347,11 +347,6 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null)
if (airJumpingAllowed ||
(!airJumpingAllowed && grounded)) {
jumping = true
if (!isGamer) {
println("[ActorHumanoid] jumping = true")
}
}
jump()
}

View File

@@ -305,12 +305,16 @@ open class ActorWithBody : Actor() {
baseHitboxH * scale)
}
val centrePosition: Vector2
val centrePosVector: Vector2
get() = Vector2(hitbox.centeredX, hitbox.centeredY)
val centrePosPoint: Point2d
get() = Point2d(hitbox.centeredX, hitbox.centeredY)
val feetPosition: Vector2
get() = Vector2(hitbox.centeredX, hitbox.posY + hitbox.height)
val feetPosVector: Vector2
get() = Vector2(hitbox.centeredX, hitbox.endPointY)
val feetPosPoint: Point2d
get() = Point2d(hitbox.centeredX, hitbox.endPointY)
val feetPosTile: IntArray
get() = intArrayOf(tilewiseHitbox.centeredX.floorInt(), tilewiseHitbox.endPointY.floorInt())
override fun run() = update(gameContainer, updateDelta)

View File

@@ -2,7 +2,6 @@ package net.torvald.terrarum.gameactors
import net.torvald.terrarum.gameactors.ActorHumanoid
import net.torvald.terrarum.gameactors.ai.AILuaAPI
import net.torvald.terrarum.gameactors.ai.scripts.EncapsulatedString
import net.torvald.terrarum.gameitem.EquipPosition
import net.torvald.terrarum.gameitem.InventoryItem
import org.luaj.vm2.*
@@ -19,9 +18,7 @@ import java.io.Reader
/**
* Created by minjaesong on 16-01-31.
*/
open class HumanoidNPC(luaScript: EncapsulatedString, born: GameDate) : ActorHumanoid(born), AIControlled, CanBeAnItem {
override val scriptPath: String = ""
open class HumanoidNPC(override val scriptPath: String, born: GameDate) : ActorHumanoid(born), AIControlled, CanBeAnItem {
protected val luag: Globals = JsePlatform.standardGlobals()
@@ -39,7 +36,8 @@ open class HumanoidNPC(luaScript: EncapsulatedString, born: GameDate) : ActorHum
luag["luajava"] = LuaValue.NIL
aiLuaAPI = AILuaAPI(luag, this)
// load the script and execute it (initialises target script)
luaInstance = luag.load(luaScript.getString(), luaScript.javaClass.simpleName)
val inputStream = javaClass.getResourceAsStream(scriptPath)
luaInstance = luag.load(InputStreamReader(inputStream), scriptPath.split(Regex("[\\/]")).last())
luaInstance.call()
}

View File

@@ -2,7 +2,6 @@ package net.torvald.terrarum.gameactors
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.gameactors.ActorHumanoid
import net.torvald.terrarum.gameactors.ai.scripts.PokemonNPCAI
import net.torvald.terrarum.mapdrawer.FeaturesDrawer
/**
@@ -12,7 +11,8 @@ object PlayerBuilderCynthia {
operator fun invoke(): ActorWithBody {
//val p: Player = Player(GameDate(100, 143)) // random value thrown
val p: HumanoidNPC = HumanoidNPC(PokemonNPCAI, GameDate(100, 143)) // random value thrown
val p: HumanoidNPC = HumanoidNPC("/net/torvald/terrarum/gameactors/ai/scripts/PokemonNPCAI.lua",
GameDate(100, 143)) // random value thrown
InjectCreatureRaw(p.actorValue, "CreatureHuman.json")
p.actorValue[AVKey.__PLAYER_QUICKBARSEL] = 0

View File

@@ -5,10 +5,9 @@ import net.torvald.terrarum.gameactors.AIControlled
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.mapdrawer.LightmapRenderer
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaFunction
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import net.torvald.terrarum.tileproperties.TileCodex
import org.luaj.vm2.*
import org.luaj.vm2.lib.OneArgFunction
import org.luaj.vm2.lib.ZeroArgFunction
/**
@@ -16,6 +15,8 @@ import org.luaj.vm2.lib.ZeroArgFunction
*/
internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
// FIXME when actor jumps, the actor releases left/right stick
init {
if (actor !is AIControlled)
throw IllegalArgumentException("The actor is not AIControlled! $actor")
@@ -37,6 +38,7 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
g["ai"]["moveTo"] = MoveTo(actor)
g["ai"]["jump"] = Jump(actor)
g["ai"]["getNearbyTiles"] = GetNearbyTiles(actor)
g["game"] = LuaValue.tableOf()
g["game"]["version"] = GameVersion()
@@ -48,7 +50,7 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
* Reads arbitrary ActorWithBody and returns its information as Lua table
*/
fun composeActorObject(actor: ActorWithBody): LuaTable {
val t: LuaTable = LuaValue.tableOf()
val t: LuaTable = LuaTable()
t["name"] = actor.actorValue.getAsString(AVKey.NAME).toLua()
t["posX"] = actor.hitbox.centeredX.toLua()
@@ -84,7 +86,7 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
fun Double?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
fun Int?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
fun String?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
fun Boolean.toInt() = if (this) 1 else 0
}
class GetSelfActorInfo(val actor: ActorWithBody) : ZeroArgFunction() {
@@ -212,16 +214,57 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
}
}
class GetNearbyTiles(val actor: ActorWithBody) : OneArgFunction() {
/** @param radius: lookahead
*
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
*
* Index: [-3: y][-3: x] ... [0: y][0: x] ... [3: y][3: x]
* Return value: bitset (int 0-7)
* 1 -- solidity
* 2 -- liquidity
* 3 -- gravity
*/
override fun call(radius: LuaValue): LuaValue {
val radius = radius.checkint()
if (radius < 0) {
return LuaValue.NONE
}
else {
val luatable = LuaTable()
val feetTilePos = actor.feetPosTile
for (y in feetTilePos[1] - radius..feetTilePos[1] + radius) {
luatable[y - feetTilePos[1]] = LuaTable()
for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) {
val tile = TileCodex[Terrarum.ingame.world.getTileFromTerrain(x, y) ?: 4096]
val solidity = tile.isSolid.toInt()
val liquidity = tile.isFluid.toInt()
val gravity = tile.isFallable.toInt()
val tileFlag: Int = gravity.shl(2) + liquidity.shl(1) + solidity
luatable[y - feetTilePos[1]][x - feetTilePos[0]] =
LuaInteger.valueOf(tileFlag)
}
}
return luatable
}
}
}
class GameVersion() : ZeroArgFunction() {
class GameVersion : ZeroArgFunction() {
override fun call(): LuaValue {
return Terrarum.VERSION_STRING.toLua()
}
}
class GameVersionRaw() : ZeroArgFunction() {
class GameVersionRaw : ZeroArgFunction() {
override fun call(): LuaValue {
return Terrarum.VERSION_RAW.toLua()
}

View File

@@ -1,11 +0,0 @@
package net.torvald.terrarum.gameactors.ai.scripts
/**
* Encapsulated text file
*
* Created by SKYHi14 on 2016-12-28.
*/
abstract class EncapsulatedString {
abstract fun getString(): String
override fun toString() = getString()
}

View File

@@ -1,36 +1,42 @@
package net.torvald.terrarum.gameactors.ai.scripts
/**
* Randomly roams around.
*
* Created by SKYHi14 on 2016-12-23.
*/
object PokemonNPCAI : EncapsulatedString() {
override fun getString() = """
--
-- Created by minjaesong on 2017-01-06.
--
timeCounter = 0
countMax = 0
moveMode = math.random() >= 0.5 and "left" or "right"
currentMode = "turn"
currentMode = "move"
local function generateCountMax()
function generateTurn()
local function generateTurn()
return 4600 + 1250 * math.random()
end
function generateWalk()
return 568 + 342 * math.random()
local function generateWalk()
return 1645 + 402 * math.random()
end
return (currentMode == "move") and generateWalk() or generateTurn()
end
local function moveToDirection()
local function moveToDirection(delta)
local tiles = ai.getNearbyTiles(1)
if moveMode == "left" then
ai.moveLeft(0.5)
if bit32.band(bit32.bor(tiles[0][-1], tiles[-1][-1]), 1) == 1 then
ai.moveLeft(0.75)
ai.jump()
else
timeCounter = timeCounter + delta -- no countup when jumping
ai.moveLeft(0.5)
end
elseif moveMode == "right" then
ai.moveRight(0.5)
if bit32.band(bit32.bor(tiles[0][1], tiles[-1][1]), 1) == 1 then
ai.moveRight(0.75)
ai.jump()
else
timeCounter = timeCounter + delta -- no countup when jumping
ai.moveRight(0.5)
end
end
end
@@ -47,10 +53,10 @@ end
countMax = generateCountMax()
function update(delta)
timeCounter = timeCounter + delta
if currentMode == "move" then
moveToDirection()
moveToDirection(delta)
else
timeCounter = timeCounter + delta -- no countup when jumping
end
if timeCounter >= countMax then
@@ -62,6 +68,3 @@ function update(delta)
end
end
end
"""
}

View File

@@ -115,7 +115,7 @@ object GameController {
/*if (button == 0) {
Terrarum.ingame.addActor(ProjectileSimple(
0,
Terrarum.ingame.player.centrePosition,
Terrarum.ingame.player.centrePosVector,
Vector2(mouseX.toDouble(), mouseY.toDouble())
))
}*/