ActorWithBody: broke CCD again for fundamental error-catching, new tile STONE_BRICKS

Former-commit-id: 3d98f83f3d40f4423b403eae717a06ac6fc22531
Former-commit-id: 13616655a392941e0c91c3384384475ae0adb5db
This commit is contained in:
Song Minjae
2016-06-29 01:15:13 +09:00
parent 659921ae92
commit 2ed435165a
25 changed files with 289 additions and 1085 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 KiB

After

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

After

Width:  |  Height:  |  Size: 340 KiB

View File

@@ -51,7 +51,7 @@
"CONTEXT_DESCRIPTION_BIG";"[Adjective]";"Big";"Gros";"Grande";"Groß";"Grande";"Grande";"Grande";"Большой";"Μεγάλο";"Büyük";"Stor";"Stor";"Stor";"Groot";"Duży";"Iso";"大";"大";"大";"대";"Velký";"Nagy";"Mare";"ใหญ่";"Голям";"גדול";"だい";"Stór"
"CONTEXT_DESCRIPTION_HUGE";"[Adjective] Very large";"Huge";"Énorme";"Enorme";"Riesig";"Enorme";"Enorme";"Enorme";"Огромный";"Τεράστιο";"Devasa";"Enorm";"Enorm";"Enorm";"Enorm";"Ogromny";"Jättimäinen";"巨大";"极大";"極大";"특대";"Obrovský";"Hatalmas";"Enorm";"ใหญ่มาก";"Огромен";"ענק";"きょだい";"Gífurlegur"
"CONTEXT_DESCRIPTION_SMALL";"[Adjective]";"Small";"Petit";"Pequeño";"Klein";"Piccolo";"Pequeno";"Pequeno";"Маленький";"Μικρό";"Küçük";"Lille";"Liten";"Liten";"Klein";"Mały";"Pieni";"小";"小";"小";"소";"Malý";"Kicsi";"Mic";"เล็ก";"Малък";"קטן";"";"Lítill"
"CONTEXT_DESCRIPTION_SMALL";"[Adjective]";"Small";"Petit";"Pequeño";"Klein";"Piccolo";"Pequeno";"Pequeno";"Маленький";"Μικρό";"Küçük";"Lille";"Liten";"Liten";"Klein";"Mały";"Pieni";"小";"小";"小";"소";"Malý";"Kicsi";"Mic";"เล็ก";"Малък";"קטן";"しょう";"Lítill"
"CONTEXT_DESCRIPTION_TINY";"[Adjective] Very small";"Tiny";"Minuscule";"Diminuto";"Winzig";"Minuscolo";"Muito pequeno";"Muito pequeno";"Крошечный";"Μικροσκοπικό";"Minik";"Lillebitte";"Bitteliten";"Pytteliten";"Minuscuul";"Malutki";"Pikkuriikkinen";"極小";"极小";"極小";"특소";"Maličký";"Apró";"Minuscul";"เล็กจิ๋ว";"Миниатюрен";"קטנטן";"きょくしょう";"Pínulítill"
"CONTEXT_ITEM_ARMOR";"[Noun] Body armor";"Armor";"Armure";"Armadura";"Rüstung";"Armatura";"Armadura";"Armadura";"Броня";"Πανοπλία";"Zırh";"Rustning";"Rustning";"Rustning";"Pantser";"Zbroja";"Panssari";"鎧";"护甲";"護甲";"갑옷";"Brnění";"Páncél";"Armură";"ชุดเกราะ";"Броня";"שריון";"よろい";"brynja"
1 STRING_ID IETF language tag(s) without dash enUS frFR esES deDE itIT ptBR ptPT ruRU elGR trTR daDK noNB svSE nlNL plPL fiFI jaJP zhCN zhTW koKR csCZ huHU roRO thTH bgBG heIL jakanaJP isIC
51 CONTEXT_ITEM_ARROW [Noun] Ammo for archers Arrow Flèche Flecha Pfeil Freccia Flecha Seta Стрела Βέλος Ok Pil Pil Pil Pijl Strzała Nuoli 화살 Šíp Nyílvessző Săgeată ลูกธนู Стрела חץ Ör
52 CONTEXT_ITEM_ARROW_PLURAL [Noun/Plural] Ammo for archers Arrows Flèches Flechas Pfeile Frecce Flechas Setas Стрелы Βέλη Oklar Pile Piler Pilar Pijlen Strzały Nuolet 화살 Šípy Nyílvesszők Săgeți ลูกธนู Стрели חיצים Örvar
53 CONTEXT_ITEM_BOMB [Noun] Bomb Bombe Bomba Bombe Bomba Bomba Bomba Бомба Βόμβα Bomba Bombe Bombe Bomb Bom Bomba Pommi 爆弾 炸弹 炸彈 폭탄 Bomba Bomba Bombă ระเบิด Бомба פצצה ばくだん Bomba
54 CONTEXT_ITEM_BOOK [Noun] Book Livre Libro Buch Libro Livro Livro Книга Βιβλίο Kitap Bog Bok Bok Boek Książka Kirja Kniha Könyv Carte หนังสือ Книга ספר ほん Bók
55 CONTEXT_ITEM_BOOTS [Noun/Plural] Boots Boots Bottes Botas Stiefel Scarponi Botas Botas Ботинки Μπότες Bot Støvler Støvler Kängor Schoenen Buty Saappaat 신발 Boty Csizma Bocanci รองเท้าบูท Ботуши מגפיים くつ Skór
56 CONTEXT_ITEM_BOW [Noun] Used by archers Bow Arc Arco Bogen Arco Arco Arco Лук Τόξο Yay Bue Bue Båge Boog Łuk Jousi Luk Íj Arc ธนู Лък קשת ゆみ Bógur
57 CONTEXT_ITEM_CARD [Noun] Card Carte Carta Karte Carta Carta Carta Карта Κάρτα Kart Kort Kort Kort Kaart Karta Kortti カード 卡片 卡片 카드 Karta Kártya Carte การ์ด Карта קלף カード Kort

View File

@@ -5,6 +5,10 @@ package net.torvald.point
*/
class Point2d(var x: Double, var y: Double) : Cloneable {
override fun toString(): String {
return "($x, $y)"
}
fun set(x: Double, y: Double) {
this.x = x
this.y = y

View File

@@ -4,7 +4,7 @@
package net.torvald.spriteanimation
import net.torvald.terrarum.Game
import net.torvald.terrarum.StateGame
import net.torvald.terrarum.Terrarum
import com.jme3.math.FastMath
import org.newdawn.slick.Graphics

View File

@@ -2,8 +2,52 @@
Copyright 2015-2016 Torvald. All rights reserved.
mailto: skyhi14 *64* __115875741922660__ *46* __6516589__
----
* *Simplex Noise Generator*, version 2012-03-09 by Stefan Gustavson
Released as public domain
----
* *Joise* modular noise library
Copyright (C) 2013 Jason Taylor. Released as open-source under Apache License, Version 2.0.
Copyright (C) 2013 Jason Taylor.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
----
* *Vector2* from Dyn4j
Copyright (c) 2010-2015 William Bittle http://www.dyn4j.org/
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the
distribution.
* Neither the name of dyn4j nor the names of its contributors may be used to endorse or
promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Kotlin translated and modified code Copyright (c) 2016 Torvald aka skyhi14.

View File

@@ -0,0 +1,31 @@
package net.torvald.terrarum
import org.newdawn.slick.Font
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
import org.newdawn.slick.state.BasicGameState
import org.newdawn.slick.state.StateBasedGame
/**
* Created by minjaesong on 16-06-28.
*/
class StateFontPrinter : BasicGameState() {
val textToPrint = "Font printer 서체 인쇄기"
lateinit var canvas: Graphics
lateinit var gameFont: Font
override fun init(gc: GameContainer, game: StateBasedGame) {
canvas = Graphics(1024, 1024)
}
override fun update(gc: GameContainer, game: StateBasedGame, delta: Int) {
}
override fun render(gc: GameContainer, game: StateBasedGame, g: Graphics) {
}
override fun getID(): Int = 666
}

View File

@@ -35,7 +35,7 @@ import java.util.*
/**
* Created by minjaesong on 15-12-30.
*/
class Game @Throws(SlickException::class)
class StateGame @Throws(SlickException::class)
constructor() : BasicGameState() {
private val ACTOR_UPDATE_RANGE = 4096
@@ -315,9 +315,7 @@ constructor() : BasicGameState() {
GameController.controllerButtonReleased(controller, button)
}
override fun getID(): Int {
return Terrarum.SCENE_ID_GAME
}
override fun getID(): Int = Terrarum.SCENE_ID_GAME
private fun drawSkybox(g: Graphics) {
val skyColourFill = GradientFill(

View File

@@ -57,7 +57,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
appgc.input.enableKeyRepeat()
game = Game()
game = StateGame()
addState(game)
}
@@ -84,7 +84,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
var VSYNC = true
val VSYNC_TRIGGER_THRESHOLD = 56
lateinit var game: Game
lateinit var game: StateGame
lateinit var gameConfig: GameConfig
lateinit var OSName: String

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.Game
import net.torvald.terrarum.StateGame
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.ui.ConsoleWindow

View File

@@ -1,7 +1,7 @@
package net.torvald.terrarum.console
import net.torvald.imagefont.GameFontBase
import net.torvald.terrarum.Game
import net.torvald.terrarum.StateGame
import net.torvald.terrarum.Terrarum
/**

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.Game
import net.torvald.terrarum.StateGame
import net.torvald.terrarum.mapdrawer.MapDrawer
import net.torvald.terrarum.Terrarum

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.Game
import net.torvald.terrarum.StateGame
import net.torvald.terrarum.Terrarum
/**

View File

@@ -1,15 +1,12 @@
package net.torvald.terrarum.gameactors
import net.torvald.random.HQRNG
import net.torvald.terrarum.*
import net.torvald.terrarum.gamemap.GameMap
import net.torvald.terrarum.mapdrawer.MapDrawer
import net.torvald.terrarum.tileproperties.TilePropCodex
import net.torvald.spriteanimation.SpriteAnimation
import com.jme3.math.FastMath
import net.torvald.terrarum.tileproperties.TileNameCode
import org.dyn4j.Epsilon
import org.dyn4j.geometry.ChainedVector2
import org.dyn4j.geometry.Vector2
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
@@ -21,14 +18,26 @@ import org.newdawn.slick.Graphics
*/
open class ActorWithBody : Actor(), Visible {
override var referenceID: Int = generateUniqueReferenceID()
override var actorValue: ActorValue = ActorValue()
@Transient var sprite: SpriteAnimation? = null
@Transient var spriteGlow: SpriteAnimation? = null
@Transient private val map: GameMap = Terrarum.game.map
var hitboxTranslateX: Double = 0.0// relative to spritePosX
var hitboxTranslateY: Double = 0.0// relative to spritePosY
var baseHitboxW: Int = 0
var baseHitboxH: Int = 0
@Transient private val map: GameMap = Terrarum.game.map
internal var baseSpriteWidth: Int = 0
internal var baseSpriteHeight: Int = 0
/**
* * Position: top-left point
* * Unit: pixel
*/
override val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
@Transient val nextHitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
/**
* Velocity vector for newtonian sim.
@@ -46,31 +55,7 @@ open class ActorWithBody : Actor(), Visible {
var walkX: Double = 0.0
var walkY: Double = 0.0
val moveDelta = Vector2(0.0, 0.0)
@Transient private val VELO_HARD_LIMIT = 10000.0
var grounded = false
@Transient var sprite: SpriteAnimation? = null
@Transient var spriteGlow: SpriteAnimation? = null
/** Default to 'false' */
var isVisible = false
/** Default to 'true' */
var isUpdate = true
var isNoSubjectToGrav = false
var isNoCollideWorld = false
var isNoSubjectToFluidResistance = false
internal var baseSpriteWidth: Int = 0
internal var baseSpriteHeight: Int = 0
override var referenceID: Int = generateUniqueReferenceID()
/**
* * Position: top-left point
* * Unit: pixel
*/
override val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
@Transient val nextHitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
@Transient private val VELO_HARD_LIMIT = 100.0
/**
* Physical properties.
@@ -92,6 +77,7 @@ open class ActorWithBody : Actor(), Visible {
actorValue[AVKey.BASEMASS] = value
}
@Transient private val MASS_DEFAULT: Double = 60.0
/** Valid range: [0, 1] */
var elasticity: Double = 0.0
set(value) {
@@ -119,6 +105,31 @@ open class ActorWithBody : Actor(), Visible {
private var density = 1000.0
/**
* Flags and Properties
*/
var grounded = false
/** Default to 'false' */
var isVisible = false
/** Default to 'true' */
var isUpdate = true
var isNoSubjectToGrav = false
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.
*
* (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.
* --minjaesong)
*/
var isChronostasis = false
/**
* Constants
*/
@Transient private val METER = 24.0
/**
* [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
@@ -148,44 +159,23 @@ open class ActorWithBody : Actor(), Visible {
@Transient private val UD_COMPENSATOR_MAX = TSIZE
@Transient private val LR_COMPENSATOR_MAX = TSIZE
/**
* A constant to make falling faster so that the game is more playable
*/
@Transient private val G_MUL_PLAYABLE_CONST = 1.4142
/**
* Post-hit invincibility, in milliseconds
*/
@Transient val INVINCIBILITY_TIME: Int = 500
@Transient private val MASS_DEFAULT: Double = 60.0
internal var physSleep: Boolean = false
private set
/**
* for collide-to-world compensation
*/
@Transient private var posAdjustX = 0
@Transient private var posAdjustY = 0
@Transient internal val BASE_FRICTION = 0.3
@Transient val KINEMATIC = 1 // does not be budged by external forces
@Transient val DYNAMIC = 2
@Transient val STATIC = 3 // does not be budged by external forces, target of collision
var collisionType = DYNAMIC
@Transient private val CCD_TICK = 1.0 / 256.0
@Transient private val CCD_TRY_MAX = 25600
// to use with Controller (incl. player)
internal var walledLeft = false
internal var walledRight = false
@Transient private val CCD_TICK = 1.0 / 16.0
@Transient private val CCD_TRY_MAX = 12800
// just some trivial magic numbers
@Transient private val A_PIXEL = 2.0
@Transient private val A_PIXEL = 1.4
@Transient private val COLLIDING_TOP = 0
@Transient private val COLLIDING_RIGHT = 1
@Transient private val COLLIDING_BOTTOM = 2
@@ -194,8 +184,18 @@ open class ActorWithBody : Actor(), Visible {
@Transient private val COLLIDING_LR = 5
@Transient private val COLLIDING_ALLSIDE = 6
/**
* Temporary variables
*/
@Transient private var assertPrinted = false
// to use with Controller (incl. player)
internal var walledLeft = false
internal var walledRight = false
var ccdCollided = false
init {
// some initialiser goes here...
}
@@ -240,17 +240,22 @@ open class ActorWithBody : Actor(), Visible {
* Add vector value to the velocity, in the time unit of single frame.
*
* Since we're adding some value every frame, the value is equivalent to the acceleration.
* Find about Newton's second law for the background knowledge.
* Look for Newton's second law for the background knowledge.
* @param vec : Acceleration in Vector2
*/
fun applyForce(vec: Vector2) {
velocity += vec
physSleep = false
}
override fun update(gc: GameContainer, delta: Int) {
if (isUpdate) {
/**
* Temporary variables to reset
*/
ccdCollided = false
/******************************/
if (!assertPrinted) assertInit()
// make NoClip work for player
@@ -276,22 +281,22 @@ open class ActorWithBody : Actor(), Visible {
}
// hard limit velocity
if (veloX > VELO_HARD_LIMIT) veloX = VELO_HARD_LIMIT
if (veloY > VELO_HARD_LIMIT) veloY = VELO_HARD_LIMIT
veloX = veloX.bipolarClamp(VELO_HARD_LIMIT)
veloY = veloY.bipolarClamp(VELO_HARD_LIMIT)
moveDelta.set(velocity + Vector2(walkX, walkY))
if (!physSleep) {
if (!isChronostasis) {
// Set 'next' position (hitbox) from canonical and walking velocity
setNewNextHitbox()
applyNormalForce()
/**
* solveCollision()?
* If and only if:
* This body is NON-STATIC and the other body is STATIC
*/
displaceByCCD()
applyNormalForce()
setHorizontalFriction()
if (isPlayerNoClip) // or hanging on the rope, etc.
@@ -304,8 +309,8 @@ open class ActorWithBody : Actor(), Visible {
clampHitbox()
}
walledLeft = isColliding(COLLIDING_LEFT)
walledRight = isColliding(COLLIDING_RIGHT)
walledLeft = isColliding(hitbox, COLLIDING_LEFT)
walledRight = isColliding(hitbox, COLLIDING_RIGHT)
}
}
@@ -340,10 +345,8 @@ open class ActorWithBody : Actor(), Visible {
private fun applyNormalForce() {
if (!isNoCollideWorld) {
// axis Y
if (moveDelta.y >= 0.0) { // check downward
//FIXME "isColliding" (likely the newer one) is the perkeleen vittupää
if (isColliding(COLLIDING_UD)) {
// the actor is hitting the ground
if (moveDelta.y >= 0.0) { // was moving downward?
if (ccdCollided) { // actor hit something on its bottom
hitAndReflectY()
grounded = true
}
@@ -351,17 +354,16 @@ open class ActorWithBody : Actor(), Visible {
grounded = false
}
}
else if (moveDelta.y < 0.0) { // check upward
else if (moveDelta.y < 0.0) { // or was moving upward?
grounded = false
if (isColliding(COLLIDING_UD)) {
// the actor is hitting the ceiling
if (ccdCollided) { // actor hit something on its top
hitAndReflectY()
}
else { // the actor is not grounded at all
}
}
// axis X
if (isColliding(COLLIDING_LR) && moveDelta.x != 0.0) { // check right and left
if (ccdCollided && moveDelta.x != 0.0) { // check right and left
// the actor is hitting the wall
hitAndReflectX()
}
@@ -373,48 +375,27 @@ open class ActorWithBody : Actor(), Visible {
*/
private fun displaceByCCD() {
if (!isNoCollideWorld){
// vector, toward the previous position; implies linear interpolation
val deltaNegative = Vector2(hitbox.toVector() - nextHitbox.toVector()) // we need to traverse back, so may as well negate at the first place
val ccdDelta = if (deltaNegative.magnitudeSquared > CCD_TICK.sqr())
deltaNegative.setMagnitude(CCD_TICK)
else
deltaNegative
var ccdCount = 0
// 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)
// Q&D fix: quantise hitbox by direction
/*if (deltaNegative.y < 0) {
if (deltaNegative.x > 0)
nextHitbox.setPosition(
nextHitbox.posX.floor(),
nextHitbox.endPointY.ceil().minus(nextHitbox.height)
)
else if (deltaNegative.x < 0)
nextHitbox.setPosition(
nextHitbox.endPointX.ceil().minus(nextHitbox.width),
nextHitbox.endPointY.ceil().minus(nextHitbox.height)
)
}
else if (deltaNegative.y > 0) {
if (deltaNegative.x > 0)
nextHitbox.setPosition(
nextHitbox.posX.floor(),
nextHitbox.posY.floor()
)
else if (deltaNegative.x < 0)
nextHitbox.setPosition(
nextHitbox.endPointX.ceil().minus(nextHitbox.width),
nextHitbox.posY.floor()
)
}*/
for (step in 0..ccdStep.floorInt()) {
ccdBox.translate(ccdDelta * (step.toDouble() / ccdStep))
while (isColliding(COLLIDING_ALLSIDE) && ccdCount < CCD_TRY_MAX) { // no thresholding?
nextHitbox.translate(ccdDelta)
ccdCount += 1
println(ccdDelta * (step.toDouble() / ccdStep))
println(ccdBox)
if (isColliding(ccdBox)) {
ccdCollided = true
break
}
}
if (ccdCount > 0) {
println("Displacement: ${ccdDelta.magnitude * ccdCount} ($ccdCount times)")
}
nextHitbox.reassign(ccdBox)
}
else {
ccdCollided = false
}
}
@@ -440,9 +421,9 @@ open class ActorWithBody : Actor(), Visible {
}
}
private fun isColliding() = isColliding(0)
private fun isColliding(hitbox: Hitbox) = isColliding(hitbox, 0)
private fun isColliding(option: Int): Boolean {
private fun isColliding(hitbox: Hitbox, option: Int): Boolean {
if (isNoCollideWorld) return false
// offsets will stretch and shrink detection box according to the argument
@@ -451,41 +432,41 @@ open class ActorWithBody : Actor(), Visible {
val offsetX = if (option == COLLIDING_LR) A_PIXEL else 0.0
val offsetY = if (option == COLLIDING_UD) A_PIXEL else 0.0
x1 = nextHitbox.posX - offsetX + offsetY
x2 = nextHitbox.posX + offsetX - offsetY + nextHitbox.width
y1 = nextHitbox.posY + offsetX - offsetY
y2 = nextHitbox.posY - offsetX + offsetY + nextHitbox.height
x1 = hitbox.posX - offsetX + offsetY
x2 = hitbox.posX + offsetX - offsetY + hitbox.width
y1 = hitbox.posY + offsetX - offsetY
y2 = hitbox.posY - offsetX + offsetY + hitbox.height
}
else {
if (option == COLLIDING_LEFT) {
x1 = nextHitbox.posX - A_PIXEL
x2 = nextHitbox.posX - A_PIXEL + nextHitbox.width
y1 = nextHitbox.posY + A_PIXEL
y2 = nextHitbox.posY - A_PIXEL + nextHitbox.height
x1 = hitbox.posX - A_PIXEL
x2 = hitbox.posX - A_PIXEL + hitbox.width
y1 = hitbox.posY + A_PIXEL
y2 = hitbox.posY - A_PIXEL + hitbox.height
}
else if (option == COLLIDING_RIGHT) {
x1 = nextHitbox.posX + A_PIXEL
x2 = nextHitbox.posX + A_PIXEL + nextHitbox.width
y1 = nextHitbox.posY + A_PIXEL
y2 = nextHitbox.posY - A_PIXEL + nextHitbox.height
x1 = hitbox.posX + A_PIXEL
x2 = hitbox.posX + A_PIXEL + hitbox.width
y1 = hitbox.posY + A_PIXEL
y2 = hitbox.posY - A_PIXEL + hitbox.height
}
else if (option == COLLIDING_TOP) {
x1 = nextHitbox.posX + A_PIXEL
x2 = nextHitbox.posX - A_PIXEL + nextHitbox.width
y1 = nextHitbox.posY - A_PIXEL
y2 = nextHitbox.posY - A_PIXEL + nextHitbox.height
x1 = hitbox.posX + A_PIXEL
x2 = hitbox.posX - A_PIXEL + hitbox.width
y1 = hitbox.posY - A_PIXEL
y2 = hitbox.posY - A_PIXEL + hitbox.height
}
else if (option == COLLIDING_BOTTOM) {
x1 = nextHitbox.posX + A_PIXEL
x2 = nextHitbox.posX - A_PIXEL + nextHitbox.width
y1 = nextHitbox.posY + A_PIXEL
y2 = nextHitbox.posY + A_PIXEL + nextHitbox.height
x1 = hitbox.posX + A_PIXEL
x2 = hitbox.posX - A_PIXEL + hitbox.width
y1 = hitbox.posY + A_PIXEL
y2 = hitbox.posY + A_PIXEL + hitbox.height
}
else {
x1 = nextHitbox.posX
x2 = nextHitbox.posX + nextHitbox.width
y1 = nextHitbox.posY
y2 = nextHitbox.posY + nextHitbox.height
x1 = hitbox.posX
x2 = hitbox.posX + hitbox.width
y1 = hitbox.posY
y2 = hitbox.posY + hitbox.height
}
}
@@ -707,7 +688,7 @@ open class ActorWithBody : Actor(), Visible {
)
}
private fun updateHitbox() = hitbox.set(nextHitbox)
private fun updateHitbox() = hitbox.reassign(nextHitbox)
override fun drawGlow(gc: GameContainer, g: Graphics) {
if (isVisible && spriteGlow != null) {
@@ -810,6 +791,10 @@ open class ActorWithBody : Actor(), Visible {
fun Double.abs() = Math.abs(this)
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
else if (this < 0 && this < -limit) -limit
else this
private fun assertInit() {
// errors
@@ -851,19 +836,3 @@ open class ActorWithBody : Actor(), Visible {
}
}
}
/**
* Give new random ReferenceID and initialise ActorValue
*/
/**
= = ↑
=== ===@!
=↑ =↑
=↑ =
=↑ =
=@ (pressing R) =
================== ==================
Fig. 1: the fix was not applied
*/

View File

@@ -1,13 +1,12 @@
package net.torvald.terrarum.gameactors
import net.torvald.point.Point2d
import org.dyn4j.geometry.ChainedVector2
import org.dyn4j.geometry.Vector2
/**
* Created by minjaesong on 16-01-15.
*/
class Hitbox(x1: Double, y1: Double, width: Double, height: Double) : Cloneable {
class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
@Volatile var hitboxStart: Point2d
private set
@@ -25,6 +24,10 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) : Cloneable
this.height = height
}
override fun toString(): String {
return "[$hitboxStart - $hitboxEnd]"
}
/**
* Returns bottom-centered point of hitbox.
* @return pointX
@@ -58,10 +61,7 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) : Cloneable
this.height = height
}
/**
* Set this hitbox from other
*/
fun set(other: Hitbox) {
fun reassign(other: Hitbox) {
set(other.posX, other.posY, other.width, other.height)
}
@@ -69,10 +69,6 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) : Cloneable
setPosition(posX + x, posY + y)
}
fun translate(vec: ChainedVector2) {
translate(vec.x, vec.y)
}
fun translate(vec: Vector2) {
translate(vec.x, vec.y)
}
@@ -139,4 +135,6 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) : Cloneable
fun toVector(): Vector2 {
return Vector2(posX, posY)
}
fun clone(): Hitbox = Hitbox(posX, posY, width, height)
}

View File

@@ -111,6 +111,9 @@ object MapCamera {
*/
val TILES_CONNECT_MUTUAL = arrayOf(
TileNameCode.STONE
, TileNameCode.STONE_QUARRIED
, TileNameCode.STONE_TILE_WHITE
, TileNameCode.STONE_BRICKS
, TileNameCode.DIRT
, TileNameCode.GRASS
, TileNameCode.PLANK_BIRCH

View File

@@ -11,6 +11,8 @@ object TileNameCode {
val STONE = TilePropCodex.idDamageToIndex(1, 0)
val STONE_QUARRIED = TilePropCodex.idDamageToIndex(1, 1)
val STONE_TILE_WHITE = TilePropCodex.idDamageToIndex(1, 2)
val STONE_BRICKS = TilePropCodex.idDamageToIndex(1, 3)
val DIRT = TilePropCodex.idDamageToIndex(2, 0)
val GRASS = TilePropCodex.idDamageToIndex(2, 1)

View File

@@ -24,16 +24,23 @@ object TilePropUtil {
val random = HQRNG();
var flickerPatternThis = getNewRandom()
var flickerPatternNext = getNewRandom()
//var flickerPatternThis = getNewRandom()
//var flickerPatternNext = getNewRandom()
var flickerP0 = getNewRandom()
var flickerP1 = getNewRandom()
var flickerP2 = getNewRandom()
var flickerP3 = getNewRandom()
init {
}
private fun getTorchFlicker(baseLum: Int): Int {
val funcY = linearInterpolation1D(flickerPatternThis, flickerPatternNext,
flickerFuncX.toFloat() / flickerFuncDomain
//val funcY = linearInterpolation1D(flickerPatternThis, flickerPatternNext,
// flickerFuncX.toFloat() / flickerFuncDomain
//)
val funcY = FastMath.interpolateCatmullRom(0.0f, flickerFuncX.toFloat() / flickerFuncDomain,
flickerP0, flickerP1, flickerP2, flickerP3
)
return LightmapRenderer.alterBrightnessUniform(baseLum, funcY)
@@ -63,8 +70,12 @@ object TilePropUtil {
if (flickerFuncX > flickerFuncDomain) {
flickerFuncX -= flickerFuncDomain
flickerPatternThis = flickerPatternNext
flickerPatternNext = getNewRandom()
//flickerPatternThis = flickerPatternNext
//flickerPatternNext = getNewRandom()
flickerP0 = flickerP1
flickerP1 = flickerP2
flickerP2 = flickerP3
flickerP3 = getNewRandom()
}
// breath-related vars

View File

@@ -2,6 +2,8 @@
"0"; "0";"TILE_AIR" ; "8396808"; "0"; "1"; "1"; "0"; "0"; "0"; "0"; "0"; "0"; "0";"4"
"1"; "0";"TILE_STONE" ; "33587232"; "25";"2400"; "0"; "1"; "1"; "0"; "1"; "0"; "0"; "0";"16"
"1"; "1";"TILE_STONE_QUARRIED" ; "33587232"; "25";"2400"; "0"; "1"; "1"; "0"; "1"; "1"; "0"; "0";"16"
"1"; "2";"TILE_STONE_TILE_WHITE" ; "33587232"; "25";"2400"; "0"; "1"; "1"; "0"; "1"; "2"; "0"; "0";"16"
"1"; "3";"TILE_STONE_BRICKS" ; "33587232"; "25";"2400"; "0"; "1"; "1"; "0"; "1"; "3"; "0"; "0";"16"
"2"; "0";"TILE_DIRT" ; "33587232"; "6";"1400"; "0"; "1"; "1"; "0"; "2"; "0"; "0"; "0";"16"
"2"; "1";"TILE_GRASS" ; "33587232"; "6";"1400"; "0"; "1"; "1"; "0"; "2"; "1"; "0"; "0";"16"
"3"; "0";"TILE_PLANK_NORMAL" ; "33587232"; "12"; "740"; "0"; "1"; "1"; "0"; "3"; "0"; "0"; "0";"16"
Can't render this file because it contains an unexpected character in line 1 and column 18.

View File

@@ -89,8 +89,8 @@ class BasicDebugInfoWindow:UICanvas {
+ (hitbox.pointedY / MapDrawer.TILE_SIZE).toInt().toString()
+ ")")
printLine(g, 3, "veloX reported $ccG${if (player.physSleep) "(sleep)" else player.moveDelta.x}")
printLine(g, 4, "veloY reported $ccG${if (player.physSleep) "(sleep)" else player.moveDelta.y}")
printLine(g, 3, "veloX reported $ccG${player.moveDelta.x}")
printLine(g, 4, "veloY reported $ccG${player.moveDelta.y}")
printLineColumn(g, 2, 3, "veloX measured $ccG${xdelta}")
printLineColumn(g, 2, 4, "veloY measured $ccG${ydelta}")

View File

@@ -1,873 +0,0 @@
/*
* Copyright (c) 2010-2015 William Bittle http://www.dyn4j.org/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of dyn4j nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Kotlin translated and modified code Copyright (c) 2016 Torvald aka skyhi14.
*/
package org.dyn4j.geometry
import org.dyn4j.Epsilon
/**
* This class represents a vector or point in 2D space.
*
*
* The operations [ChainedVector2.setMagnitude], [ChainedVector2.getNormalized],
* [ChainedVector2.project], and [ChainedVector2.normalize] require the [ChainedVector2]
* to be non-zero in length.
*
*
* Some methods also return the vector to facilitate chaining. For example:
*
* Vector a = new Vector();
* a.zero().plus(1, 2).times(2);
*
* In this Kotlin code, you can use regular operations like + - * /.
*
* |operator |function |
* |-----------|------------|
* |a + b |a.plus(b) | equivalent of plusAssign
* |a - b |a.minus(b) | equivalent of minusAssign
* |a * b |a.times(b) | equivalent of timesAssign
* |a / b |a.div(b) | equivalent of divAssign
* |a dot b |a.dot(b) | equivalent of dotAssign
* |a cross b |a.cross(b) | equivalent of crossAssign
* |!a |negate(a) |
* |a rotate th|a.rotate(th)| equivalent of rotateAssign
*
* @author William Bittle
* *
* @version 3.1.11
* *
* @since 1.0.0
*/
class ChainedVector2 {
/** The magnitude of the x component of this [ChainedVector2] */
var x: Double = 0.toDouble()
/** The magnitude of the y component of this [ChainedVector2] */
var y: Double = 0.toDouble()
/** Default constructor. */
constructor() {
}
/**
* Copy constructor.
* @param vector the [ChainedVector2] to copy from
*/
constructor(vector: ChainedVector2) {
this.x = vector.x
this.y = vector.y
}
/**
* Optional constructor.
* @param x the x component
* *
* @param y the y component
*/
constructor(x: Double, y: Double) {
this.x = x
this.y = y
}
/**
* Optional constructor.
* @param vector non-chainable Vector2
*/
constructor(vector: Vector2) {
this.x = vector.x
this.y = vector.y
}
/**
* Creates a [ChainedVector2] from the first point to the second point.
* @param x1 the x coordinate of the first point
* *
* @param y1 the y coordinate of the first point
* *
* @param x2 the x coordinate of the second point
* *
* @param y2 the y coordinate of the second point
*/
constructor(x1: Double, y1: Double, x2: Double, y2: Double) {
this.x = x2 - x1
this.y = y2 - y1
}
/**
* Creates a [ChainedVector2] from the first point to the second point.
* @param p1 the first point
* *
* @param p2 the second point
*/
constructor(p1: ChainedVector2, p2: ChainedVector2) {
this.x = p2.x - p1.x
this.y = p2.y - p1.y
}
/**
* Creates a unit length vector in the given direction.
* @param direction the direction in radians
* *
* @since 3.0.1
*/
constructor(direction: Double) {
this.x = Math.cos(direction)
this.y = Math.sin(direction)
}
/**
* Returns a copy of this [ChainedVector2].
* @return [ChainedVector2]
*/
fun copy(): ChainedVector2 {
return ChainedVector2(this.x, this.y)
}
/**
* Returns the distance from this point to the given point.
* @param x the x coordinate of the point
* *
* @param y the y coordinate of the point
* *
* @return double
*/
fun distance(x: Double, y: Double): Double {
//return Math.hypot(this.x - x, this.y - y);
val dx = this.x - x
val dy = this.y - y
return Math.sqrt(dx * dx + dy * dy)
}
/**
* Returns the distance from this point to the given point.
* @param point the point
* *
* @return double
*/
fun distance(point: ChainedVector2): Double {
//return Math.hypot(this.x - point.x, this.y - point.y);
val dx = this.x - point.x
val dy = this.y - point.y
return Math.sqrt(dx * dx + dy * dy)
}
/**
* Returns the distance from this point to the given point squared.
* @param x the x coordinate of the point
* *
* @param y the y coordinate of the point
* *
* @return double
*/
fun distanceSquared(x: Double, y: Double): Double {
//return (this.x - x) * (this.x - x) + (this.y - y) * (this.y - y);
val dx = this.x - x
val dy = this.y - y
return dx * dx + dy * dy
}
/**
* Returns the distance from this point to the given point squared.
* @param point the point
* *
* @return double
*/
fun distanceSquared(point: ChainedVector2): Double {
//return (this.x - point.x) * (this.x - point.x) + (this.y - point.y) * (this.y - point.y);
val dx = this.x - point.x
val dy = this.y - point.y
return dx * dx + dy * dy
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
override fun hashCode(): Int {
val prime = 31
var result = 1
var temp: Long
temp = java.lang.Double.doubleToLongBits(x)
result = prime * result + (temp xor temp.ushr(32)).toInt()
temp = java.lang.Double.doubleToLongBits(y)
result = prime * result + (temp xor temp.ushr(32)).toInt()
return result
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
override fun equals(obj: Any?): Boolean {
if (obj == null) return false
if (obj === this) return true
if (obj is ChainedVector2) {
return this.x == obj.x && this.y == obj.y
}
return false
}
/**
* Returns true if the x and y components of this [ChainedVector2]
* are the same as the given [ChainedVector2].
* @param vector the [ChainedVector2] to compare to
* *
* @return boolean
*/
fun equals(vector: ChainedVector2?): Boolean {
if (vector == null) return false
if (this === vector) {
return true
}
else {
return this.x == vector.x && this.y == vector.y
}
}
/**
* Returns true if the x and y components of this [ChainedVector2]
* are the same as the given x and y components.
* @param x the x coordinate of the [ChainedVector2] to compare to
* *
* @param y the y coordinate of the [ChainedVector2] to compare to
* *
* @return boolean
*/
fun equals(x: Double, y: Double): Boolean {
return this.x == x && this.y == y
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
override fun toString(): String {
val sb = StringBuilder()
sb.append("(").append(this.x).append(", ").append(this.y).append(")")
return sb.toString()
}
/**
* Sets this [ChainedVector2] to the given [ChainedVector2].
* @param vector the [ChainedVector2] to set this [ChainedVector2] to
* *
* @return [ChainedVector2] this vector
*/
fun set(vector: ChainedVector2): ChainedVector2 {
this.x = vector.x
this.y = vector.y
return this
}
/**
* Sets this [ChainedVector2] to the given [ChainedVector2].
* @param x the x component of the [ChainedVector2] to set this [ChainedVector2] to
* *
* @param y the y component of the [ChainedVector2] to set this [ChainedVector2] to
* *
* @return [ChainedVector2] this vector
*/
fun set(x: Double, y: Double): ChainedVector2 {
this.x = x
this.y = y
return this
}
/**
* Returns the x component of this [ChainedVector2].
* @return [ChainedVector2]
*/
val xComponent: ChainedVector2
get() = ChainedVector2(this.x, 0.0)
/**
* Returns the y component of this [ChainedVector2].
* @return [ChainedVector2]
*/
val yComponent: ChainedVector2
get() = ChainedVector2(0.0, this.y)
/**
* Returns the magnitude of this [ChainedVector2].
* @return double
*/
// the magnitude is just the pathagorean theorem
val magnitude: Double
get() = Math.sqrt(this.x * this.x + this.y * this.y)
/**
* Returns the magnitude of this [ChainedVector2] squared.
* @return double
*/
val magnitudeSquared: Double
get() = this.x * this.x + this.y * this.y
/**
* Sets the magnitude of the [ChainedVector2].
* @param magnitude the magnitude
* *
* @return [ChainedVector2] this vector
*/
fun setMagnitude(magnitude: Double): ChainedVector2 {
// check the given magnitude
if (Math.abs(magnitude) <= Epsilon.E) {
this.x = 0.0
this.y = 0.0
return this
}
// is this vector a zero vector?
if (this.isZero) {
return this
}
// get the magnitude
var mag = Math.sqrt(this.x * this.x + this.y * this.y)
// normalize and multiply by the new magnitude
mag = magnitude / mag
this.x *= mag
this.y *= mag
return this
}
/**
* Returns the direction of this [ChainedVector2]
* as an angle in radians.
* @return double angle in radians [-, ]
*/
val direction: Double
get() = Math.atan2(this.y, this.x)
/**
* Sets the direction of this [ChainedVector2].
* @param angle angle in radians
* *
* @return [ChainedVector2] this vector
*/
fun setDirection(angle: Double): ChainedVector2 {
//double magnitude = Math.hypot(this.x, this.y);
val magnitude = Math.sqrt(this.x * this.x + this.y * this.y)
this.x = magnitude * Math.cos(angle)
this.y = magnitude * Math.sin(angle)
return this
}
/**
* Adds the given [ChainedVector2] to this [ChainedVector2].
* @param vector the [ChainedVector2]
* *
* @return [ChainedVector2] this vector
*/
fun plus(vector: ChainedVector2): ChainedVector2 {
this.x += vector.x
this.y += vector.y
return this
}
/**
* Adds the given [ChainedVector2] to this [ChainedVector2].
* @param x the x component of the [ChainedVector2]
* *
* @param y the y component of the [ChainedVector2]
* *
* @return [ChainedVector2] this vector
*/
fun plus(x: Double, y: Double): ChainedVector2 {
this.x += x
this.y += y
return this
}
/**
* Adds this [ChainedVector2] and the given [ChainedVector2] returning
* a new [ChainedVector2] containing the result.
* @param vector the [ChainedVector2]
* *
* @return [ChainedVector2]
*/
fun sum(vector: ChainedVector2): ChainedVector2 {
return ChainedVector2(this.x + vector.x, this.y + vector.y)
}
/**
* Adds this [ChainedVector2] and the given [ChainedVector2] returning
* a new [ChainedVector2] containing the result.
* @param x the x component of the [ChainedVector2]
* *
* @param y the y component of the [ChainedVector2]
* *
* @return [ChainedVector2]
*/
fun sum(x: Double, y: Double): ChainedVector2 {
return ChainedVector2(this.x + x, this.y + y)
}
/**
* Subtracts the given [ChainedVector2] from this [ChainedVector2].
* @param vector the [ChainedVector2]
* *
* @return [ChainedVector2] this vector
*/
fun minus(vector: ChainedVector2): ChainedVector2 {
this.x -= vector.x
this.y -= vector.y
return this
}
/**
* Subtracts the given [ChainedVector2] from this [ChainedVector2].
* @param x the x component of the [ChainedVector2]
* *
* @param y the y component of the [ChainedVector2]
* *
* @return [ChainedVector2] this vector
*/
fun minus(x: Double, y: Double): ChainedVector2 {
this.x -= x
this.y -= y
return this
}
/**
* Subtracts the given [ChainedVector2] from this [ChainedVector2] returning
* a new [ChainedVector2] containing the result.
* @param vector the [ChainedVector2]
* *
* @return [ChainedVector2]
*/
fun difference(vector: ChainedVector2): ChainedVector2 {
return ChainedVector2(this.x - vector.x, this.y - vector.y)
}
/**
* Subtracts the given [ChainedVector2] from this [ChainedVector2] returning
* a new [ChainedVector2] containing the result.
* @param x the x component of the [ChainedVector2]
* *
* @param y the y component of the [ChainedVector2]
* *
* @return [ChainedVector2]
*/
fun difference(x: Double, y: Double): ChainedVector2 {
return ChainedVector2(this.x - x, this.y - y)
}
/**
* Creates a [ChainedVector2] from this [ChainedVector2] to the given [ChainedVector2].
* @param vector the [ChainedVector2]
* *
* @return [ChainedVector2]
*/
fun to(vector: ChainedVector2): ChainedVector2 {
return ChainedVector2(vector.x - this.x, vector.y - this.y)
}
/**
* Creates a [ChainedVector2] from this [ChainedVector2] to the given [ChainedVector2].
* @param x the x component of the [ChainedVector2]
* *
* @param y the y component of the [ChainedVector2]
* *
* @return [ChainedVector2]
*/
fun to(x: Double, y: Double): ChainedVector2 {
return ChainedVector2(x - this.x, y - this.y)
}
/**
* Multiplies this [ChainedVector2] by the given scalar.
* @param scalar the scalar
* *
* @return [ChainedVector2] this vector
*/
fun times(scalar: Double): ChainedVector2 {
this.x *= scalar
this.y *= scalar
return this
}
/**
* Multiplies this [ChainedVector2] by the given scalar.
* @param scalar the scalar
* *
* @return [ChainedVector2] this vector
*/
fun div(scalar: Double): ChainedVector2 {
this.x /= scalar
this.y /= scalar
return this
}
/**
* Multiplies this [ChainedVector2] by the given scalar returning
* a new [ChainedVector2] containing the result.
* @param scalar the scalar
* *
* @return [ChainedVector2]
*/
fun product(scalar: Double): ChainedVector2 {
return ChainedVector2(this.x * scalar, this.y * scalar)
}
/**
* Returns the dot product of the given [ChainedVector2]
* and this [ChainedVector2].
* @param vector the [ChainedVector2]
* *
* @return double
*/
fun dot(vector: ChainedVector2): Double {
return this.x * vector.x + this.y * vector.y
}
/**
* Returns the dot product of the given [ChainedVector2]
* and this [ChainedVector2].
* @param x the x component of the [ChainedVector2]
* *
* @param y the y component of the [ChainedVector2]
* *
* @return double
*/
fun dot(x: Double, y: Double): Double {
return this.x * x + this.y * y
}
/**
* Returns the cross product of the this [ChainedVector2] and the given [ChainedVector2].
* @param vector the [ChainedVector2]
* *
* @return double
*/
fun cross(vector: ChainedVector2): Double {
return this.x * vector.y - this.y * vector.x
}
/**
* Returns the cross product of the this [ChainedVector2] and the given [ChainedVector2].
* @param x the x component of the [ChainedVector2]
* *
* @param y the y component of the [ChainedVector2]
* *
* @return double
*/
fun cross(x: Double, y: Double): Double {
return this.x * y - this.y * x
}
/**
* Returns the cross product of this [ChainedVector2] and the z value of the right [ChainedVector2].
* @param z the z component of the [ChainedVector2]
* *
* @return [ChainedVector2]
*/
fun cross(z: Double): ChainedVector2 {
return ChainedVector2(-1.0 * this.y * z, this.x * z)
}
/**
* Returns true if the given [ChainedVector2] is orthogonal (perpendicular)
* to this [ChainedVector2].
*
*
* If the dot product of this vector and the given vector is
* zero then we know that they are perpendicular
* @param vector the [ChainedVector2]
* *
* @return boolean
*/
fun isOrthogonal(vector: ChainedVector2): Boolean {
return if (Math.abs(this.x * vector.x + this.y * vector.y) <= Epsilon.E) true else false
}
/**
* Returns true if the given [ChainedVector2] is orthogonal (perpendicular)
* to this [ChainedVector2].
*
*
* If the dot product of this vector and the given vector is
* zero then we know that they are perpendicular
* @param x the x component of the [ChainedVector2]
* *
* @param y the y component of the [ChainedVector2]
* *
* @return boolean
*/
fun isOrthogonal(x: Double, y: Double): Boolean {
return if (Math.abs(this.x * x + this.y * y) <= Epsilon.E) true else false
}
/**
* Returns true if this [ChainedVector2] is the zero [ChainedVector2].
* @return boolean
*/
val isZero: Boolean
get() = Math.abs(this.x) <= Epsilon.E && Math.abs(this.y) <= Epsilon.E
/**
* Negates this [ChainedVector2].
* @return [ChainedVector2] this vector
*/
fun not() = negate()
/**
* Negates this [ChainedVector2].
* @return [ChainedVector2] this vector
*/
fun negate(): ChainedVector2 {
this.x *= -1.0
this.y *= -1.0
return this
}
/**
* Returns a [ChainedVector2] which is the negative of this [ChainedVector2].
* @return [ChainedVector2]
*/
val negative: ChainedVector2
get() = ChainedVector2(-this.x, -this.y)
/**
* Sets the [ChainedVector2] to the zero [ChainedVector2]
* @return [ChainedVector2] this vector
*/
fun zero(): ChainedVector2 {
this.x = 0.0
this.y = 0.0
return this
}
/**
* Rotates about the origin.
* @param theta the rotation angle in radians
* *
* @return [ChainedVector2] this vector
*/
fun rotate(theta: Double): ChainedVector2 {
val cos = Math.cos(theta)
val sin = Math.sin(theta)
val x = this.x
val y = this.y
this.x = x * cos - y * sin
this.y = x * sin + y * cos
return this
}
/**
* Rotates the [ChainedVector2] about the given coordinates.
* @param theta the rotation angle in radians
* *
* @param x the x coordinate to rotate about
* *
* @param y the y coordinate to rotate about
* *
* @return [ChainedVector2] this vector
*/
fun rotate(theta: Double, x: Double, y: Double): ChainedVector2 {
this.x -= x
this.y -= y
this.rotate(theta)
this.x += x
this.y += y
return this
}
/**
* Rotates the [ChainedVector2] about the given point.
* @param theta the rotation angle in radians
* *
* @param point the point to rotate about
* *
* @return [ChainedVector2] this vector
*/
fun rotate(theta: Double, point: ChainedVector2): ChainedVector2 {
return this.rotate(theta, point.x, point.y)
}
/**
* Projects this [ChainedVector2] onto the given [ChainedVector2].
* @param vector the [ChainedVector2]
* *
* @return [ChainedVector2] the projected [ChainedVector2]
*/
fun project(vector: ChainedVector2): ChainedVector2 {
val dotProd = this.dot(vector)
var denominator = vector.dot(vector)
if (denominator <= Epsilon.E) return ChainedVector2()
denominator = dotProd / denominator
return ChainedVector2(denominator * vector.x, denominator * vector.y)
}
/**
* Returns the right-handed normal of this vector.
* @return [ChainedVector2] the right hand orthogonal [ChainedVector2]
*/
val rightHandOrthogonalVector: ChainedVector2
get() = ChainedVector2(-this.y, this.x)
/**
* Sets this vector to the right-handed normal of this vector.
* @return [ChainedVector2] this vector
* *
* @see .getRightHandOrthogonalVector
*/
fun right(): ChainedVector2 {
val temp = this.x
this.x = -this.y
this.y = temp
return this
}
/**
* Returns the left-handed normal of this vector.
* @return [ChainedVector2] the left hand orthogonal [ChainedVector2]
*/
val leftHandOrthogonalVector: ChainedVector2
get() = ChainedVector2(this.y, -this.x)
/**
* Sets this vector to the left-handed normal of this vector.
* @return [ChainedVector2] this vector
* *
* @see .getLeftHandOrthogonalVector
*/
fun left(): ChainedVector2 {
val temp = this.x
this.x = this.y
this.y = -temp
return this
}
/**
* Returns a unit [ChainedVector2] of this [ChainedVector2].
*
*
* This method requires the length of this [ChainedVector2] is not zero.
* @return [ChainedVector2]
*/
val normalized: ChainedVector2
get() {
var magnitude = this.magnitude
if (magnitude <= Epsilon.E) return ChainedVector2()
magnitude = 1.0 / magnitude
return ChainedVector2(this.x * magnitude, this.y * magnitude)
}
/**
* Converts this [ChainedVector2] into a unit [ChainedVector2] and returns
* the magnitude before normalization.
*
*
* This method requires the length of this [ChainedVector2] is not zero.
* @return double
*/
fun normalize(): Double {
val magnitude = Math.sqrt(this.x * this.x + this.y * this.y)
if (magnitude <= Epsilon.E) return 0.0
val m = 1.0 / magnitude
this.x *= m
this.y *= m
//return 1.0 / m;
return magnitude
}
/**
* Returns the smallest angle between the given [ChainedVector2]s.
*
*
* Returns the angle in radians in the range - to .
* @param vector the [ChainedVector2]
* *
* @return angle in radians [-, ]
*/
fun getAngleBetween(vector: ChainedVector2): Double {
val a = Math.atan2(vector.y, vector.x) - Math.atan2(this.y, this.x)
if (a > Math.PI) return a - 2.0 * Math.PI
if (a < -Math.PI) return a + 2.0 * Math.PI
return a
}
fun toVector(): Vector2 {
return Vector2(x, y)
}
companion object {
/** A vector representing the x-axis; this vector should not be changed at runtime; used internally */
internal val X_AXIS = ChainedVector2(1.0, 0.0)
/** A vector representing the y-axis; this vector should not be changed at runtime; used internally */
internal val Y_AXIS = ChainedVector2(0.0, 1.0)
/**
* Returns a new [ChainedVector2] given the magnitude and direction.
* @param magnitude the magnitude of the [ChainedVector2]
* *
* @param direction the direction of the [ChainedVector2] in radians
* *
* @return [ChainedVector2]
*/
fun create(magnitude: Double, direction: Double): ChainedVector2 {
val x = magnitude * Math.cos(direction)
val y = magnitude * Math.sin(direction)
return ChainedVector2(x, y)
}
/**
* The triple product of [ChainedVector2]s is defined as:
*
* a x (b x c)
*
* However, this method performs the following triple product:
*
* (a x b) x c
*
* this can be simplified to:
*
* -a * (b c) + b * (a c)
*
* or:
*
* b * (a c) - a * (b c)
*
* @param a the a [ChainedVector2] in the above equation
* *
* @param b the b [ChainedVector2] in the above equation
* *
* @param c the c [ChainedVector2] in the above equation
* *
* @return [ChainedVector2]
*/
fun tripleProduct(a: ChainedVector2, b: ChainedVector2, c: ChainedVector2): ChainedVector2 {
// expanded version of above formula
val r = ChainedVector2()
// perform a.dot(c)
val ac = a.x * c.x + a.y * c.y
// perform b.dot(c)
val bc = b.x * c.x + b.y * c.y
// perform b * a.dot(c) - a * b.dot(c)
r.x = b.x * ac - a.x * bc
r.y = b.y * ac - a.y * bc
return r
}
}
}

View File

@@ -40,22 +40,23 @@ import org.dyn4j.Epsilon
*
* Chaining is not available.
*
* In this Kotlin code, you can use regular operations like + - * /.
* In this Kotlin code, you can use regular operators like + - * /.
*
* |operator |function |
* |-----------|------------|
* |a + b |Vector(a).plus(b) |
* |a - b |Vector(a).minus(b) |
* |a * b |Vector(a).times(b) |
* |a / b |Vector(a).div(b) |
* |a += b |Vector(a).plusAssign(b)|
* |a -= b |Vector(a).minusAssign(b)|
* |a *= b |Vector(a).timesAssign(b)|
* |a /= b |Vector(a).divAssign(b)|
* |a dot b |Vector(a).dot(b) |
* |a cross b |Vector(a).cross(b) |
* |!a |Vector(negate(a) |
* |a rotate th|Vector(a).rotate(th)|
* |operator |function |
* |-----------|---------------------|
* |a + b |Vector2(a).plus(b) |
* |a - b |Vector2(a).minus(b) |
* |a * b |Vector2(a).times(b) |
* |a / b |Vector2(a).div(b) |
* |a += b |a.plusAssign(b) |
* |a -= b |a.minusAssign(b) |
* |a *= b |a.timesAssign(b) |
* |a /= b |a.divAssign(b) |
* |a dot b |Vector2(a).dot(b) |
* |a cross b |Vector2(a).cross(b) |
* |!a |this.negative |
* |a rotate th|Vector2(a).rotate(th)|
* |a to b |Vector2(a).to(b) |
*
* @author William Bittle
* *
@@ -392,22 +393,22 @@ class Vector2 {
/**
* Creates a [Vector2] from this [Vector2] to the given [Vector2].
* @param vector the [Vector2]
* @param other : the other [Vector2]
* *
* @return [Vector2]
*/
fun to(vector: Vector2): Vector2 {
return Vector2(vector.x - this.x, vector.y - this.y)
infix fun to(other: Vector2): Vector2 {
return Vector2(other.x - this.x, other.y - this.y)
}
/**
* Multiplies this [Vector2] by the given scalar.
* Get product of this vector.
* @param scalar the scalar
* *
* @return [Vector2] this vector
*/
operator fun times(scalar: Double): Vector2 {
return Vector2(this.x * scalar, this.y * scalar)
return product(scalar)
}
operator fun timesAssign(scalar: Double) {
@@ -540,21 +541,13 @@ class Vector2 {
* Negates this [Vector2].
* @return [Vector2] this vector
*/
operator fun not() = negate()
operator fun not() = this.negative
/**
* Negates this [Vector2].
* @return [Vector2] this vector
*/
operator fun unaryMinus() = negate()
/**
* Negates this [Vector2].
* @return [Vector2] this vector
*/
fun negate(): Vector2 {
return Vector2(-x, -y)
}
operator fun unaryMinus() = this.negative
/**
* Returns a [Vector2] which is the negative of this [Vector2].

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" renderorder="right-down" width="512" height="100" tilewidth="16" tileheight="16" nextobjectid="3">
<tileset firstgid="1" name="TerrarumTerrain" tilewidth="16" tileheight="16" tilecount="65536" columns="256">
<image source="../res/graphics/terrain/terrain.png" width="4096" height="4096"/>
</tileset>
<tileset firstgid="65537" name="TerrarumWall" tilewidth="16" tileheight="16" tilecount="65536" columns="256">
<image source="../res/graphics/terrain/wall.png" width="4096" height="4096"/>
</tileset>
<imagelayer name="Image Layer 1">
<image source="../../../../Pictures/tiledmap_background_512_100.png"/>
</imagelayer>
<layer name="Wall" width="512" height="100">
<data encoding="base64" compression="zlib">
eJzt2TEOwjAQRcEYTsL9L4loECBsLGC9gZ2RfpUi7p6jbBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQ4dTaddWeAUBVe+qx/gNAjNseVhsAVJXd4MwBQFXZDc4cAFSV3eDMAUBV2Q2+rB3vt+q9AFDVqtY+22P3V98DAKCq6Mb29qr9K+4AAFBVZF9H038AyBPZ19H0HwDyRPZ1NP0HgDyRfR1N/wEgT6+Lo2Z+49ls/yPPAgBV6T8A1KP/AFBPr5HR8/8fAPJE9nU0/QeAtSKbOjv9B4C1Ips6O/0HgLUimzo7/QeAtSKbOrs2ucgzAMCva4d2t1mRfR3N9z8AfO7d/u+d/gNAn/5rPwD1/Gv/AYA+/QcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPnEGIseuBw==
</data>
</layer>
<layer name="Terrain" width="512" height="100">
<data encoding="base64" compression="zlib">
eJzt3WtrE0EYhuHdtKhEWvCAYL7VA1LB///3TNDFsG7SPUx23p25brjwS9VASZ7ZNEmbRpIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSVIJvd/lvgWSJGntTvvvDCBJUj2ddr+1/5IkVZX9lySprrrtb50BJEmqpv7+OwNIklR2Q9vf7b8zgCRJZXZp/50BpHr72TbNl6Nvbe5bIukWXdt+PweQ6u35uPtPR1/tv1RU3XX9S9vvDCDVmf2XymvK7jsDSHVm/6Vt1F3PjzFn+9vev9H/fyWVlf2X4rdk01OcBTw3IJWX/ZfitvR6PvV5QFI5Rdv//V3TvPrr/i73rZHyFWn77b9UXlH2v9v912eb/+AcoEqLtv3OAFJ55d7/x4Hd7/fgDKCKirr99l8qq9z7P7a39l+FF3n3nQGk8rL/Up5SvWfPGUDSnOy/dL3D7v+tHnKtlO/Rj8D+S9sv5/5/2DfNp/2fbf94/PPdBd3XSGt3mLiJt/hMnojsv7T9Ilz/j9l2+68cfQ6wtVGNfe5Dqq2t3C/svzTclGv/2m3l8U5K1Zjn+iLdL7rf9Xvuyf5Lg7n2dwaQ+s35mV6Ens/2vs/+S/9y7Z/+DOBsoK2V6nU8Efp13PjvF/zIvP9e/6co2f40Z4Chx03PEShSa71mV8M9vvDZf12nzwB84wygG3ZIfJ/n+vkgUlN+t/KU930qfxHekyMpbq75850Dcu5rii1wFohXtPfdSopT/zN9cj8+cNmSa/O1P5PhlrfV8xDD5byuH0vSul373L7cjweQUmnnhZxnuCjfn9T67/3r263g/ux1hvuFf19lNvbzdkt4XIBccu+R++66Lr33r7PW7ei2vJ3JOWFeqXbVfR9gW6Ls/1qWPj9R2u7m/n4AkEdt+z/X3J9t2F0AIrL/AFAf+w8A9bH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAq/AQvXoTU=
</data>
</layer>
</map>