Separated langpack, concept art for inventory UI

Former-commit-id: 7a98df93b4ef50b47283abcd99576d6fbefc9cc5
Former-commit-id: db6e34417ccf84e59ba68547f30459cb4b188eb7
This commit is contained in:
Song Minjae
2016-07-04 23:08:16 +09:00
parent 2ed435165a
commit 2e46df67a8
91 changed files with 70088 additions and 720 deletions

View File

@@ -118,7 +118,7 @@ open class ActorWithBody : Actor(), Visible {
var isNoCollideWorld = false
var isNoSubjectToFluidResistance = false
/** Time-freezing. The actor won't even budge but the velocity will accumulate
* EXCEPT FOR friction, gravity and buoyancy SHOULD NOT.
* EXCEPT FOR friction, gravity and buoyancy.
*
* (this would give something to do to the player otherwise it would be dull to travel far,
* think of a grass cutting on the Zelda games. It would also make a great puzzle to solve.
@@ -175,7 +175,7 @@ open class ActorWithBody : Actor(), Visible {
@Transient private val CCD_TRY_MAX = 12800
// just some trivial magic numbers
@Transient private val A_PIXEL = 1.4
@Transient private val A_PIXEL = 1.0
@Transient private val COLLIDING_TOP = 0
@Transient private val COLLIDING_RIGHT = 1
@Transient private val COLLIDING_BOTTOM = 2
@@ -234,7 +234,7 @@ open class ActorWithBody : Actor(), Visible {
baseHitboxH * scale)
}
override fun run() = update(Terrarum.appgc, Terrarum.game.DELTA_T)
override fun run() = update(Terrarum.appgc, Terrarum.game.UPDATE_DELTA)
/**
* Add vector value to the velocity, in the time unit of single frame.
@@ -274,19 +274,21 @@ open class ActorWithBody : Actor(), Visible {
/**
* 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()
//applyBuoyancy()
}
// hard limit velocity
veloX = veloX.bipolarClamp(VELO_HARD_LIMIT)
veloY = veloY.bipolarClamp(VELO_HARD_LIMIT)
applyControllerMovement()
moveDelta.set(velocity + Vector2(walkX, walkY))
// applyBuoyancy()
if (!isChronostasis) {
// Actors are subject to the gravity and the buoyancy if they are not levitating
if (!isNoSubjectToGrav) {
applyGravitation()
}
// hard limit velocity
veloX = veloX.bipolarClamp(VELO_HARD_LIMIT)
veloY = veloY.bipolarClamp(VELO_HARD_LIMIT)
// Set 'next' position (hitbox) from canonical and walking velocity
setNewNextHitbox()
@@ -309,8 +311,25 @@ open class ActorWithBody : Actor(), Visible {
clampHitbox()
}
walledLeft = isColliding(hitbox, COLLIDING_LEFT)
walledRight = isColliding(hitbox, COLLIDING_RIGHT)
// useless
walledLeft = false//isColliding(hitbox, COLLIDING_LEFT)
walledRight = false//isColliding(hitbox, COLLIDING_RIGHT)
}
}
private fun applyControllerMovement() {
// decide whether ignore walkX
if (!(isCollidingSide(hitbox, COLLIDING_LEFT) && walkX < 0)
|| !(isCollidingSide(hitbox, COLLIDING_RIGHT) && walkX > 0)
) {
moveDelta.x = veloX + walkX
}
// decide whether ignore walkY
if (!(isCollidingSide(hitbox, COLLIDING_TOP) && walkY < 0)
|| !(isCollidingSide(hitbox, COLLIDING_BOTTOM) && walkY > 0)
) {
moveDelta.y = veloY + walkY
}
}
@@ -320,7 +339,7 @@ open class ActorWithBody : Actor(), Visible {
* Apply only if not grounded; normal force is precessed separately.
*/
private fun applyGravitation() {
if (!grounded) {//(!isColliding(COLLIDING_BOTTOM)) { // or !grounded
if (!isTouchingSide(hitbox, COLLIDING_BOTTOM)) {//(!isColliding(COLLIDING_BOTTOM)) { // or !grounded
/**
* weight; gravitational force in action
* W = mass * G (9.8 [m/s^2])
@@ -346,7 +365,7 @@ open class ActorWithBody : Actor(), Visible {
if (!isNoCollideWorld) {
// axis Y
if (moveDelta.y >= 0.0) { // was moving downward?
if (ccdCollided) { // actor hit something on its bottom
if (isTouchingSide(nextHitbox, COLLIDING_BOTTOM)) { // actor hit something on its bottom
hitAndReflectY()
grounded = true
}
@@ -356,14 +375,15 @@ open class ActorWithBody : Actor(), Visible {
}
else if (moveDelta.y < 0.0) { // or was moving upward?
grounded = false
if (ccdCollided) { // actor hit something on its top
if (isTouchingSide(nextHitbox, COLLIDING_TOP)) { // actor hit something on its top
hitAndReflectY()
}
else { // the actor is not grounded at all
}
}
// axis X
if (ccdCollided && moveDelta.x != 0.0) { // check right and left
if (isTouchingSide(nextHitbox, COLLIDING_LEFT) && isTouchingSide(nextHitbox, COLLIDING_RIGHT)
&& moveDelta.x != 0.0) { // check right and left
// the actor is hitting the wall
hitAndReflectX()
}
@@ -376,23 +396,26 @@ open class ActorWithBody : Actor(), Visible {
private fun displaceByCCD() {
if (!isNoCollideWorld){
// do some CCD between hitbox and nextHitbox
val ccdBox = hitbox.clone()
val ccdDelta = hitbox.toVector() to nextHitbox.toVector()
val ccdStep = Math.max(ccdDelta.x, ccdDelta.y)
val ccdBox = nextHitbox.clone().snapToPixel()
val ccdDelta = nextHitbox.toVector() to hitbox.toVector()
val deltaMax = Math.max(ccdDelta.x.abs(), ccdDelta.y.abs())
// set ccdDelta so that CCD move a pixel per round
if (deltaMax > 1.0)
ccdDelta *= (1.0 / deltaMax)
for (step in 0..ccdStep.floorInt()) {
ccdBox.translate(ccdDelta * (step.toDouble() / ccdStep))
//println("deltaMax: $deltaMax")
//println("ccdDelta: $ccdDelta")
println(ccdDelta * (step.toDouble() / ccdStep))
println(ccdBox)
while (!ccdDelta.isZero && isColliding(ccdBox)) {
nextHitbox.translate(ccdDelta)
ccdCollided = true
if (isColliding(ccdBox)) {
ccdCollided = true
break
}
ccdBox.reassign(nextHitbox).snapToPixel()
}
nextHitbox.reassign(ccdBox)
nextHitbox.snapToPixel()
//println("ccdCollided: $ccdCollided")
}
else {
ccdCollided = false
@@ -470,10 +493,99 @@ open class ActorWithBody : Actor(), Visible {
}
}
val txStart = x1.div(TSIZE).floorInt()
val txEnd = x2.div(TSIZE).floorInt()
val tyStart = y1.div(TSIZE).floorInt()
val tyEnd = y2.div(TSIZE).floorInt()
val txStart = x1.div(TSIZE).roundInt()
val txEnd = x2.div(TSIZE).roundInt()
val tyStart = y1.div(TSIZE).roundInt()
val tyEnd = y2.div(TSIZE).roundInt()
for (y in tyStart..tyEnd) {
for (x in txStart..txEnd) {
val tile = map.getTileFromTerrain(x, y)
if (TilePropCodex.getProp(tile).isSolid)
return true
}
}
return false
}
private fun isTouchingSide(hitbox: Hitbox, option: Int): Boolean {
val x1: Double; val x2: Double; val y1: Double; val y2: Double
if (option == COLLIDING_TOP) {
x1 = hitbox.posX
x2 = hitbox.endPointX
y1 = hitbox.posY - A_PIXEL
y2 = y1
}
else if (option == COLLIDING_BOTTOM) {
x1 = hitbox.posX
x2 = hitbox.endPointX
y1 = hitbox.endPointY + A_PIXEL
y2 = y1
}
else if (option == COLLIDING_LEFT) {
x1 = hitbox.posX - A_PIXEL
x2 = x1
y1 = hitbox.posY
y2 = hitbox.endPointY
}
else if (option == COLLIDING_RIGHT) {
x1 = hitbox.endPointX + A_PIXEL
x2 = x1
y1 = hitbox.posY
y2 = hitbox.endPointY
}
else throw IllegalArgumentException()
val txStart = x1.div(TSIZE).roundInt()
val txEnd = x2.div(TSIZE).roundInt()
val tyStart = y1.div(TSIZE).roundInt()
val tyEnd = y2.div(TSIZE).roundInt()
for (y in tyStart..tyEnd) {
for (x in txStart..txEnd) {
val tile = map.getTileFromTerrain(x, y)
if (TilePropCodex.getProp(tile).isSolid)
return true
}
}
return false
}
private fun isCollidingSide(hitbox: Hitbox, option: Int): Boolean {
val x1: Double; val x2: Double; val y1: Double; val y2: Double
if (option == COLLIDING_TOP) {
x1 = hitbox.posX
x2 = hitbox.endPointX
y1 = hitbox.posY
y2 = y1
}
else if (option == COLLIDING_BOTTOM) {
x1 = hitbox.posX
x2 = hitbox.endPointX
y1 = hitbox.endPointY
y2 = y1
}
else if (option == COLLIDING_LEFT) {
x1 = hitbox.posX
x2 = x1
y1 = hitbox.posY
y2 = hitbox.endPointY
}
else if (option == COLLIDING_RIGHT) {
x1 = hitbox.endPointX
x2 = x1
y1 = hitbox.posY
y2 = hitbox.endPointY
}
else throw IllegalArgumentException()
val txStart = x1.div(TSIZE).roundInt()
val txEnd = x2.div(TSIZE).roundInt()
val tyStart = y1.div(TSIZE).roundInt()
val tyEnd = y2.div(TSIZE).roundInt()
for (y in tyStart..tyEnd) {
for (x in txStart..txEnd) {
@@ -792,7 +904,7 @@ open class ActorWithBody : Actor(), Visible {
fun Double.sqr() = this * this
fun Int.abs() = if (this < 0) -this else this
fun Double.bipolarClamp(limit: Double) =
if (this > 0 && this > limit) limit
if (this > 0 && this > limit) limit
else if (this < 0 && this < -limit) -limit
else this
@@ -800,11 +912,12 @@ open class ActorWithBody : Actor(), Visible {
// errors
if (baseHitboxW == 0 || baseHitboxH == 0)
throw RuntimeException("Hitbox dimension was not set.")
if (sprite == null && isVisible)
throw RuntimeException("Actor ${this.javaClass.canonicalName} is visible but the sprite was not set.")
// warnings
if (!isVisible && sprite != null)
println("[ActorWithBody] Caution: actor ${this.javaClass.canonicalName} is invisible but the sprite was given.")
if (sprite == null && isVisible)
println("[ActorWithBody] Caution: actor ${this.javaClass.simpleName} is visible but the sprite was not set.")
else if (sprite != null && !isVisible)
println("[ActorWithBody] Caution: actor ${this.javaClass.simpleName} is invisible but the sprite was given.")
assertPrinted = true
}

View File

@@ -17,6 +17,8 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
var height: Double = 0.0
private set
val HALF_PIXEL = 0.5
init {
hitboxStart = Point2d(x1, y1)
hitboxEnd = Point2d(x1 + width, y1 + height)
@@ -54,62 +56,56 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
* @param width
* @param height
*/
fun set(x1: Double, y1: Double, width: Double, height: Double) {
fun set(x1: Double, y1: Double, width: Double, height: Double): Hitbox {
hitboxStart = Point2d(x1, y1)
hitboxEnd = Point2d(x1 + width, y1 + height)
this.width = width
this.height = height
return this
}
fun reassign(other: Hitbox) = set(other.posX, other.posY, other.width, other.height)
fun reassign(other: Hitbox) {
set(other.posX, other.posY, other.width, other.height)
}
fun translate(x: Double, y: Double) = setPosition(posX + x, posY + y)
fun translate(vec: Vector2) = translate(vec.x, vec.y)
fun translate(x: Double, y: Double) {
setPosition(posX + x, posY + y)
}
fun translate(vec: Vector2) {
translate(vec.x, vec.y)
}
fun setPosition(x1: Double, y1: Double) {
fun setPosition(x1: Double, y1: Double): Hitbox {
hitboxStart = Point2d(x1, y1)
hitboxEnd = Point2d(x1 + width, y1 + height)
return this
}
fun setPosition(vector: Vector2) = setPosition(vector.x, vector.y)
fun setPositionX(x: Double) {
setPosition(x, posY)
}
fun setPositionX(x: Double) = setPosition(x, posY)
fun setPositionY(y: Double) = setPosition(posX, y)
fun setPositionY(y: Double) {
setPosition(posX, y)
}
fun setPositionFromPoint(x1: Double, y1: Double) {
fun setPositionFromPoint(x1: Double, y1: Double): Hitbox {
hitboxStart = Point2d(x1 - width / 2, y1 - height)
hitboxEnd = Point2d(hitboxStart.x + width, hitboxStart.y + height)
return this
}
fun setPositionXFromPoint(x: Double) {
setPositionFromPoint(x, pointedY)
}
fun setPositionYFromPoint(y: Double) {
setPositionFromPoint(pointedX, y)
}
fun translatePosX(d: Double) {
fun translatePosX(d: Double): Hitbox {
setPositionX(posX + d)
return this
}
fun translatePosY(d: Double) {
fun translatePosY(d: Double): Hitbox {
setPositionY(posY + d)
return this
}
fun setDimension(w: Double, h: Double) {
fun setDimension(w: Double, h: Double): Hitbox {
width = w
height = h
return this
}
fun snapToPixel(): Hitbox {
hitboxStart.x = Math.round(hitboxStart.x - HALF_PIXEL).toDouble()
hitboxStart.y = Math.round(hitboxStart.y - HALF_PIXEL).toDouble()
hitboxEnd.x = Math.round(hitboxEnd.x - HALF_PIXEL).toDouble()
hitboxEnd.y = Math.round(hitboxEnd.y - HALF_PIXEL).toDouble()
return this
}
/**
@@ -132,9 +128,7 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
val centeredY: Double
get() = (hitboxStart.y + hitboxEnd.y) * 0.5f
fun toVector(): Vector2 {
return Vector2(posX, posY)
}
fun toVector(): Vector2 = Vector2(posX, posY)
fun clone(): Hitbox = Hitbox(posX, posY, width, height)
}