Merge branch 'newworldgen'

# Conflicts:
#	.idea/workspace.xml
#	src/net/torvald/terrarum/gameactors/Actor.kt


Former-commit-id: 533aeed3cd26565478a3b8c602c9e9aa7e15b43f
Former-commit-id: e7e851ed9734b47cc05144df1c6187ea50f7ecab
This commit is contained in:
Song Minjae
2017-01-31 01:05:38 +09:00
15 changed files with 512 additions and 133 deletions

View File

@@ -123,3 +123,16 @@ see SAVE_FORMAT.md
* Works like Ampere in electronics.
- Health: Regen per time
- Magic: Out power per time
## Civilisation ##
Based on _Millénaire_ Minecraft mod, they have limited resources, have ruler (one of those: town-ruler, country-ruler). Players can either help them or force their way into the head position, or even eliminating them.
Villages can be either independent or part of larger country (_Dwarf Fortress_)
## Level of technology ##
Anything goes as long as it does not exceed TL11 of GURPS. Although the universe has the existence of traditional sorcery, the laws of physics of the universe itself is same as we know it. Simply put: NO FUCKING PERPETUAL MOTION AND PERFECT PROPHECY

View File

@@ -3,7 +3,8 @@
### Looms for custom pattern ###
- Players can create their own décors (hang on wall), dresses.
- Two looms (216 colour mode, 4096 colour mode)
- Two looms (16 palette mode, 64 palette mode)
- __IMPLEMENTED__ — see net.torvald.terrarum.gameactors.DecodeTapestry
### Music making ###
@@ -25,13 +26,13 @@ Connect two or more tracker head to play the array of trackers play simultaneous
<actorid>.json
{
notes = [arr<int>, fixed size of 48],
notes = [arr<key: Int>(64)], // 64 notes per track
speed = 120
}
*int: (0-63) number of the note pitch that is struck. 32: Middle C (C3).
'A' just above of Middle C (A3) has base pitch of 440 Hz.
*speed: in BPM
- key: C1-D6 (63 keys)
- speed: in BPM
- tuning: A440
## Aimhack ##

View File

@@ -194,7 +194,7 @@ constructor() : BasicGameState() {
///////////////////////////
TilePropUtil.dynamicLumFuncTickClock()
world.updateWorldTime(delta)
WorldSimulator(player, delta)
//WorldSimulator(player, delta)
WeatherMixer.update(gc, delta)
TileStats.update()
if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride)
@@ -300,8 +300,8 @@ constructor() : BasicGameState() {
private fun setAppTitle() {
Terrarum.appgc.setTitle(
Terrarum.NAME +
" — F: ${Terrarum.appgc.fps} (${Terrarum.TARGET_INTERNAL_FPS})" +
" — M: ${Terrarum.memInUse}M / ${Terrarum.memTotal}M / ${Terrarum.memXmx}M")
" — F: ${Terrarum.appgc.fps} (${Terrarum.TARGET_INTERNAL_FPS})")
//" — M: ${Terrarum.memInUse}M / ${Terrarum.memTotal}M / ${Terrarum.memXmx}M")
}
override fun render(gc: GameContainer, sbg: StateBasedGame, gwin: Graphics) {
@@ -405,12 +405,12 @@ constructor() : BasicGameState() {
// velocity
worldG.color = GameFontBase.codeToCol["g"]
worldG.drawString(
"${0x7F.toChar()}X ${actor.velocity.x}", // doesn't work for NPCs/Player
"${0x7F.toChar()}X ${actor.moveDelta.x}",
actor.hitbox.posX.toFloat(),
actor.hitbox.pointedY.toFloat() + 4 + 8
)
worldG.drawString(
"${0x7F.toChar()}Y ${actor.velocity.y}",
"${0x7F.toChar()}Y ${actor.moveDelta.y}",
actor.hitbox.posX.toFloat(),
actor.hitbox.pointedY.toFloat() + 4 + 8 * 2
)

View File

@@ -0,0 +1,281 @@
package net.torvald.terrarum
import com.sudoplay.joise.Joise
import com.sudoplay.joise.module.*
import net.torvald.random.HQRNG
import net.torvald.terrarum.concurrent.ThreadParallel
import net.torvald.terrarum.gameactors.roundInt
import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
import org.newdawn.slick.ImageBuffer
import org.newdawn.slick.state.BasicGameState
import org.newdawn.slick.state.StateBasedGame
import java.util.*
/**
* WARNING! HAS SERIOUS MEMORY LEAK
*
* Created by SKYHi14 on 2017-01-30.
*/
class StateNoiseTester : BasicGameState() {
companion object {
val imagesize = 512
val sampleDensity = 1.0
val noiseImageBuffer = ImageBuffer(imagesize, imagesize)
var generating = false
}
override fun init(p0: GameContainer?, p1: StateBasedGame?) {
generateNoiseImage()
}
private fun noise(seed: Long): Joise {
/* Init */
val joiseSeed = seed
val lowlandMagic: Long = 0x44A21A114DBE56 // maria lindberg
val highlandMagic: Long = 0x0114E091 // olive oyl
val mountainMagic: Long = 0x115AA4DE2504 // lisa anderson
val selectionMagic: Long = 0x44E10D9B100 // melody blue
val ground_gradient = ModuleGradient()
ground_gradient.setGradient(0.0, 0.0, 0.0, 1.0)
/* Lowlands */
val lowland_shape_fractal = ModuleFractal()
lowland_shape_fractal.setType(ModuleFractal.FractalType.FBM)
lowland_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
lowland_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
lowland_shape_fractal.setNumOctaves(2)
lowland_shape_fractal.setFrequency(1.0)
lowland_shape_fractal.seed = joiseSeed xor lowlandMagic
val lowland_autocorrect = ModuleAutoCorrect()
lowland_autocorrect.setSource(lowland_shape_fractal)
lowland_autocorrect.setLow(0.0)
lowland_autocorrect.setHigh(1.0)
val lowland_scale = ModuleScaleOffset()
lowland_scale.setSource(lowland_autocorrect)
lowland_scale.setScale(0.2)
lowland_scale.setOffset(-0.25)
val lowland_y_scale = ModuleScaleDomain()
lowland_y_scale.setSource(lowland_scale)
lowland_y_scale.setScaleY(0.0)
val lowland_terrain = ModuleTranslateDomain()
lowland_terrain.setSource(ground_gradient)
lowland_terrain.setAxisYSource(lowland_y_scale)
/* highlands */
val highland_shape_fractal = ModuleFractal()
highland_shape_fractal.setType(ModuleFractal.FractalType.RIDGEMULTI)
highland_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
highland_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
highland_shape_fractal.setNumOctaves(2)
highland_shape_fractal.setFrequency(2.0)
highland_shape_fractal.seed = joiseSeed xor highlandMagic
val highland_autocorrect = ModuleAutoCorrect()
highland_autocorrect.setSource(highland_shape_fractal)
highland_autocorrect.setLow(0.0)
highland_autocorrect.setHigh(1.0)
val highland_scale = ModuleScaleOffset()
highland_scale.setSource(highland_autocorrect)
highland_scale.setScale(0.45)
highland_scale.setOffset(0.0)
val highland_y_scale = ModuleScaleDomain()
highland_y_scale.setSource(highland_scale)
highland_y_scale.setScaleY(0.0)
val highland_terrain = ModuleTranslateDomain()
highland_terrain.setSource(ground_gradient)
highland_terrain.setAxisYSource(highland_y_scale)
/* mountains */
val mountain_shape_fractal = ModuleFractal()
mountain_shape_fractal.setType(ModuleFractal.FractalType.BILLOW)
mountain_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
mountain_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
mountain_shape_fractal.setNumOctaves(4)
mountain_shape_fractal.setFrequency(1.0)
mountain_shape_fractal.seed = joiseSeed xor mountainMagic
val mountain_autocorrect = ModuleAutoCorrect()
mountain_autocorrect.setSource(mountain_shape_fractal)
mountain_autocorrect.setLow(0.0)
mountain_autocorrect.setHigh(1.0)
val mountain_scale = ModuleScaleOffset()
mountain_scale.setSource(mountain_autocorrect)
mountain_scale.setScale(0.75)
mountain_scale.setOffset(0.25)
val mountain_y_scale = ModuleScaleDomain()
mountain_y_scale.setSource(mountain_scale)
mountain_y_scale.setScaleY(0.1) // controls "quirkiness" of the mountain
val mountain_terrain = ModuleTranslateDomain()
mountain_terrain.setSource(ground_gradient)
mountain_terrain.setAxisYSource(mountain_y_scale)
/* selection */
val terrain_type_fractal = ModuleFractal()
terrain_type_fractal.setType(ModuleFractal.FractalType.FBM)
terrain_type_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
terrain_type_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
terrain_type_fractal.setNumOctaves(3)
terrain_type_fractal.setFrequency(0.5)
terrain_type_fractal.seed = joiseSeed xor selectionMagic
val terrain_autocorrect = ModuleAutoCorrect()
terrain_autocorrect.setSource(terrain_type_fractal)
terrain_autocorrect.setLow(0.0)
terrain_autocorrect.setHigh(1.0)
val terrain_type_cache = ModuleCache()
terrain_type_cache.setSource(terrain_autocorrect)
val highland_mountain_select = ModuleSelect()
highland_mountain_select.setLowSource(highland_terrain)
highland_mountain_select.setHighSource(mountain_terrain)
highland_mountain_select.setControlSource(terrain_type_cache)
highland_mountain_select.setThreshold(0.55)
highland_mountain_select.setFalloff(0.15)
val highland_lowland_select = ModuleSelect()
highland_lowland_select.setLowSource(lowland_terrain)
highland_lowland_select.setHighSource(highland_mountain_select)
highland_lowland_select.setControlSource(terrain_type_cache)
highland_lowland_select.setThreshold(0.25)
highland_lowland_select.setFalloff(0.15)
val ground_select = ModuleSelect()
ground_select.setLowSource(0.0)
ground_select.setHighSource(1.0)
ground_select.setThreshold(0.5)
ground_select.setControlSource(highland_lowland_select)
val joise = Joise(ground_select)
return joise
}
fun generateNoiseImage() {
val noiseModule = noise(HQRNG().nextLong()) // change noise function here
for (y in 0..imagesize - 1) {
for (x in 0..imagesize - 1) {
noiseImageBuffer.setRGBA(x, y, 0, 0, 0, 255)
}
}
for (i in 0..Terrarum.THREADS - 1) {
ThreadParallel.map(
i,
ThreadRunNoiseSampling(
imagesize.toFloat().div(Terrarum.THREADS).times(i).roundInt(),
imagesize.toFloat().div(Terrarum.THREADS).times(i.plus(1)).roundInt() - 1,
noiseModule
),
"SampleJoiseMap"
)
}
ThreadParallel.startAll()
}
override fun update(gc: GameContainer, sbg: StateBasedGame, delta: Int) {
Terrarum.appgc.setTitle("${Terrarum.NAME} — F: ${Terrarum.appgc.fps}"
+ " — M: ${Terrarum.memInUse}M / ${Terrarum.totalVMMem}M")
if (ThreadParallel.allFinished()) generating = false
}
override fun getID() = Terrarum.STATE_ID_TOOL_NOISEGEN
override fun render(gc: GameContainer, sbg: StateBasedGame, g: Graphics) {
g.color = Color.red
g.drawString("Press SPACE to generate new noise", 8f, 8f)
g.drawString("CPUs: ${Terrarum.THREADS}", Terrarum.WIDTH - 90f, 8f)
g.background = Color.cyan
g.drawImage(noiseImageBuffer.image,//noiseImage,
Terrarum.WIDTH.minus(imagesize).div(2).toFloat(),
Terrarum.HEIGHT.minus(imagesize).div(2).toFloat()
)
}
override fun keyPressed(key: Int, c: Char) {
if (c == ' ' && !generating) {
println("Generating noise, may take a while")
generating = true
generateNoiseImage()
}
}
class ThreadRunNoiseSampling(val startIndex: Int, val endIndex: Int, val joise: Joise) : Runnable {
/*override fun run() {
for (sy in startIndex..endIndex) {
for (sx in 0..imagesize - 1) {
val y = sy.toDouble() / imagesize
val x = sx.toDouble() / imagesize
val sampleOffset = sampleDensity
// 4-D toroidal sampling (looped H and V)
val sampleTheta1 = x * Math.PI * 2.0
val sampleTheta2 = y * Math.PI * 2.0
val sampleX = Math.sin(sampleTheta1) * sampleDensity + sampleDensity
val sampleY = Math.cos(sampleTheta1) * sampleDensity + sampleDensity
val sampleZ = Math.sin(sampleTheta2) * sampleDensity + sampleDensity
val sampleW = Math.cos(sampleTheta2) * sampleDensity + sampleDensity
val noise = joise.get(
sampleX, sampleY, sampleZ, sampleW
) // autocorrection REQUIRED!
val noiseCol = noise.times(255f).toInt()
noiseImageBuffer.setRGBA(sx, sy, noiseCol, noiseCol, noiseCol, 255)
}
}
}*/
override fun run() {
for (sy in startIndex..endIndex) {
for (sx in 0..imagesize - 1) {
val y = sy.toDouble() / imagesize * 1.5 -.6
val x = sx.toDouble() / imagesize
val sampleOffset = sampleDensity
// 4-D toroidal sampling (looped H and V)
val sampleTheta1 = x * Math.PI * 2.0
val sampleX = Math.sin(sampleTheta1) * sampleDensity + sampleDensity
val sampleZ = Math.cos(sampleTheta1) * sampleDensity + sampleDensity
val sampleY = y
val noise = joise.get(
sampleX, sampleY, sampleZ
) // autocorrection REQUIRED!
val noiseCol = noise.times(255f).toInt()
noiseImageBuffer.setRGBA(sx, sy, noiseCol, noiseCol, noiseCol, 255)
}
}
}
}
}

View File

@@ -133,6 +133,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
//addState(StateNoiseTexGen())
//addState(StateBlurTest())
//addState(StateShaderTest())
//addState(StateNoiseTester())
ingame = StateInGame()
addState(ingame)

View File

@@ -5,6 +5,23 @@ import net.torvald.terrarum.ui.ConsoleWindow
import org.apache.commons.codec.digest.DigestUtils
/**
*
* Password setting rules:
*
* For each releases new password should be set. The new password must:
* - start with next alphabet of previous password
* if previous password started with Z, the new password must start with A
* - be a name appear in the Legend of Zelda series which officially released by Nintendo
* - be lowercase
* - BE CRACKABLE (crackstation.net)
*
* Example passwords would be:
* aryll -> biggoron -> ciela -> ... -> linebeck -> midna -> navi -> ...
*
* Notes:
* do NOT put plaintext anywhere in the code (except for comments maybe)
* must use SHA-256
*
* Created by minjaesong on 16-02-19.
*/
internal object Authenticator : ConsoleCommand {

View File

@@ -39,7 +39,7 @@ abstract class Actor(val renderOrder: ActorOrder) : Comparable<Actor>, Runnable
* override var referenceID: Int = generateUniqueReferenceID()
*/
fun generateUniqueReferenceID(): Int {
fun itIsNotValid(value: Int) =
fun checkForCollision(value: Int) =
Terrarum.ingame.theGameHasActor(value) ||
value < ItemCodex.ITEM_COUNT_MAX ||
value < when (renderOrder) {
@@ -58,7 +58,7 @@ abstract class Actor(val renderOrder: ActorOrder) : Comparable<Actor>, Runnable
var ret: Int
do {
ret = HQRNG().nextInt().and(0x7FFFFFFF) // set new ID
} while (itIsNotValid(ret)) // check for collision
} while (checkForCollision(ret)) // check for collision
return ret
}

View File

@@ -65,39 +65,31 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
)
/**
* Elevators/Movingwalks/etc.: edit hitbox manually!
*
* Velocity vector for newtonian sim.
* Acceleration: used in code like:
* veloY += 3.0
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
*/
internal val velocity = Vector2(0.0, 0.0)
var veloX: Double
get() = velocity.x
protected set(value) {
velocity.x = value
}
var veloY: Double
get() = velocity.y
protected set(value) {
velocity.y = value
}
internal val externalForce = Vector2(0.0, 0.0)
val moveDelta = Vector2(0.0, 0.0)
val moveDelta = Vector2(0.0, 0.0) // moveDelta = velocity + controllerMoveDelta
@Transient private val VELO_HARD_LIMIT = 100.0
/**
* for "Controllable" actors
*/
var controllerVel: Vector2? = if (this is Controllable) Vector2() else null
var controllerMoveDelta: Vector2? = if (this is Controllable) Vector2() else null
var walkX: Double
get() = controllerVel!!.x
get() = controllerMoveDelta!!.x
protected set(value) {
controllerVel!!.x = value
controllerMoveDelta!!.x = value
}
var walkY: Double
get() = controllerVel!!.y
get() = controllerMoveDelta!!.y
protected set(value) {
controllerVel!!.y = value
controllerMoveDelta!!.y = value
}
/**
@@ -155,8 +147,6 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
}
get() = 1.0 - elasticity
@Transient private val CEILING_HIT_ELASTICITY = 0.3
var density = 1000.0
set(value) {
if (value < 0)
@@ -342,7 +332,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
* @param acc : Acceleration in Vector2
*/
fun applyForce(acc: Vector2) {
velocity += acc.times(speedMultByTile)
externalForce += acc * speedMultByTile
}
private val bounceDampenVelThreshold = 0.5
@@ -375,8 +365,8 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
}
// hard limit velocity
veloX = veloX.bipolarClamp(VELO_HARD_LIMIT)
veloY = veloY.bipolarClamp(VELO_HARD_LIMIT)
externalForce.x = externalForce.x.bipolarClamp(VELO_HARD_LIMIT)
externalForce.y = externalForce.y.bipolarClamp(VELO_HARD_LIMIT)
// Set 'next' position (hitbox) from canonical and walking velocity
setNewNextHitbox()
@@ -391,8 +381,12 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
applyNormalForce()
}
setHorizontalFriction()
if (immobileBody || isPlayerNoClip) { // TODO also hanging on the rope, etc.
if (!immobileBody) { // TODO test no friction on immobileBody
setHorizontalFriction()
}
//if (immobileBody || isPlayerNoClip) { // TODO also hanging on the rope, etc.
// TODO test no friction on immobileBody
if (isPlayerNoClip) { // TODO also hanging on the rope, etc.
setVerticalFriction()
}
@@ -429,28 +423,28 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
if (!(isCollidingSide(hitbox, COLLIDING_LEFT) && walkX < 0)
|| !(isCollidingSide(hitbox, COLLIDING_RIGHT) && walkX > 0)
) {
moveDelta.x = veloX + walkX
moveDelta.x = externalForce.x + walkX
}
// decide whether to ignore walkY
if (!(isCollidingSide(hitbox, COLLIDING_TOP) && walkY < 0)
|| !(isCollidingSide(hitbox, COLLIDING_BOTTOM) && walkY > 0)
) {
moveDelta.y = veloY + walkY
moveDelta.y = externalForce.y + walkY
}
}
else {
if (!isCollidingSide(hitbox, COLLIDING_LEFT)
|| !isCollidingSide(hitbox, COLLIDING_RIGHT)
) {
moveDelta.x = veloX
moveDelta.x = externalForce.x
}
// decide whether to ignore walkY
if (!isCollidingSide(hitbox, COLLIDING_TOP)
|| !isCollidingSide(hitbox, COLLIDING_BOTTOM)
) {
moveDelta.y = veloY
moveDelta.y = externalForce.y
}
}
}
@@ -466,18 +460,18 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
* weight; gravitational force in action
* W = mass * G (9.8 [m/s^2])
*/
val W: Vector2 = gravitation * mass
val W: Vector2 = gravitation * Terrarum.TARGET_FPS.toDouble()
/**
* Area
*/
val A: Double = scale * scale
val A: Double = (scale * baseHitboxW / METER) * (scale * baseHitboxW / METER)
/**
* Drag of atmosphere
* D = Cd (drag coefficient) * 0.5 * rho (density) * V^2 (velocity sqr) * A (area)
*/
val D: Vector2 = Vector2(veloX.magnSqr(), veloY.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble()
val D: Vector2 = Vector2(moveDelta.x.magnSqr(), moveDelta.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble()
val V: Vector2 = (W - D) / mass * SI_TO_GAME_ACC
val V: Vector2 = (W - D) / Terrarum.TARGET_FPS.toDouble() * SI_TO_GAME_ACC
applyForce(V)
}
@@ -488,7 +482,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
// axis Y. Using operand >= and hitting the ceiling will lock the player to the position
if (moveDelta.y > 0.0) { // was moving downward?
if (isColliding(nextHitbox, COLLIDING_TOP)) { // hit the ceiling
hitAndForciblyReflectY()
hitAndReflectY() //hitAndForciblyReflectY()
grounded = false
}
else if (isColliding(nextHitbox)) {
@@ -512,9 +506,12 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
}
}
// axis X
if (isTouchingSide(nextHitbox, COLLIDING_LEFT) || isTouchingSide(nextHitbox, COLLIDING_RIGHT)
&& moveDelta.x != 0.0) { // check right and left
if (isTouchingSide(nextHitbox, COLLIDING_LEFT) || isTouchingSide(nextHitbox, COLLIDING_RIGHT)) { // check right and left
// the actor is hitting the wall
// FIXME balls are stuck in this
if (referenceID != 321321321)
println("$this trying to reflectX")
hitAndReflectX()
}
}
@@ -534,7 +531,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
val ccdDelta = (nextHitbox.toVector() - hitbox.toVector())
if (ccdDelta.x != 0.0 || ccdDelta.y != 0.0) {
//ccdDelta.set(ccdDelta.setMagnitude(CCD_TICK)) // fixed tick
val displacement = Math.min(1.0.div(velocity.magnitude * 2), 0.5) // adaptive tick
val displacement = Math.min(1.0.div(moveDelta.magnitude * 2), 0.5) // adaptive tick
ccdDelta.set(ccdDelta.setMagnitude(displacement))
}
@@ -551,35 +548,44 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
}
private fun hitAndReflectX() {
if ((veloX * elasticity).abs() > Epsilon.E) {
veloX *= -elasticity
if ((externalForce.x * elasticity).abs() >= MINIMUM_BOUNCE_THRESHOLD) { // > Epsilon.E) {
externalForce.x *= -elasticity
if (this is Controllable) walkX *= -elasticity
}
else {
veloX = 0.0
externalForce.x = 0.0
if (this is Controllable) walkX = 0.0
}
}
private fun hitAndReflectY() {
if ((veloY * elasticity).abs() > Epsilon.E) {
veloY *= -elasticity
if (externalForce.y.abs() >= MINIMUM_BOUNCE_THRESHOLD) { //> Epsilon.E) {
externalForce.y *= -elasticity
if (this is Controllable) walkY *= -elasticity
}
else {
veloY = 0.0
externalForce.y = 0.0
if (this is Controllable) walkY *= 0.0
}
}
@Transient private val CEILING_HIT_ELASTICITY = 0.3
@Transient private val MINIMUM_BOUNCE_THRESHOLD = 0.1
/**
* prevents sticking to the ceiling
*/
private fun hitAndForciblyReflectY() {
if (veloY.abs() * CEILING_HIT_ELASTICITY > A_PIXEL)
veloY = -veloY * CEILING_HIT_ELASTICITY
else
veloY = veloY.sign() * -A_PIXEL
// TODO HARK! I have changed veloX/Y to moveDelta.x/y
if (moveDelta.y < 0) {
if (moveDelta.y.abs() * CEILING_HIT_ELASTICITY > A_PIXEL)
moveDelta.y = -moveDelta.y * CEILING_HIT_ELASTICITY
else
moveDelta.y = moveDelta.y.sign() * -A_PIXEL
}
else {
throw Error("Check this out bitch (moveDelta.y = ${moveDelta.y})")
}
}
private fun isColliding(hitbox: Hitbox) = isColliding(hitbox, 0)
@@ -792,13 +798,13 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
BASE_FRICTION * if (grounded) feetFriction else bodyFriction
}
if (veloX < 0) {
veloX += friction
if (veloX > 0) veloX = 0.0 // compensate overshoot
if (externalForce.x < 0) {
externalForce.x += friction
if (externalForce.x > 0) externalForce.x = 0.0 // compensate overshoot
}
else if (veloX > 0) {
veloX -= friction
if (veloX < 0) veloX = 0.0 // compensate overshoot
else if (externalForce.x > 0) {
externalForce.x -= friction
if (externalForce.x < 0) externalForce.x = 0.0 // compensate overshoot
}
if (this is Controllable) {
@@ -819,13 +825,13 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
else
BASE_FRICTION * bodyFriction
if (veloY < 0) {
veloY += friction
if (veloY > 0) veloX = 0.0 // compensate overshoot
if (externalForce.y < 0) {
externalForce.y += friction
if (externalForce.y > 0) externalForce.y = 0.0 // compensate overshoot
}
else if (veloY > 0) {
veloY -= friction
if (veloY < 0) veloY = 0.0 // compensate overshoot
else if (externalForce.y > 0) {
externalForce.y -= friction
if (externalForce.y < 0) externalForce.y = 0.0 // compensate overshoot
}
if (this is Controllable) {

View File

@@ -56,7 +56,7 @@ object PlayerBuilderSigrid {
p.actorValue[AVKey.INTELLIGENT] = true
//p.actorValue[AVKey.LUMINOSITY] = Color(0x434aff).to10bit()
p.actorValue[AVKey.LUMINOSITY] = Color(0x434aff).to10bit()
p.actorValue[AVKey.BASEDEFENCE] = 141

View File

@@ -53,7 +53,7 @@ open class ProjectileSimple(
posPre = Point2d(fromPoint.x, fromPoint.y)
// lightbox sized 8x8 centered to the bullet
lightBoxList.add(Hitbox(-4.0, -4.0, 8.0, 8.0))
this.velocity.set(velocity)
//this.externalForce.set(velocity)
damage = bulletDatabase[type][OFFSET_DAMAGE] as Int
displayColour = bulletDatabase[type][OFFSET_COL] as Color
@@ -63,7 +63,7 @@ open class ProjectileSimple(
setHitboxDimension(2, 2, 0, 0) // should be following sprite's properties if there IS one
velocity.set((fromPoint to toPoint).setMagnitude(speed.toDouble()))
externalForce.set((fromPoint to toPoint).setMagnitude(speed.toDouble()))

View File

@@ -60,8 +60,8 @@ internal class AILuaAPI(g: Globals, actor: ActorWithSprite) {
t["posX"] = actor.hitbox.centeredX.toLua()
t["posY"] = actor.hitbox.centeredY.toLua()
t["veloX"] = actor.veloX.toLua()
t["veloY"] = actor.veloY.toLua()
t["veloX"] = actor.moveDelta.x.toLua()
t["veloY"] = actor.moveDelta.y.toLua()
t["width"] = actor.hitbox.width.toLua()
t["height"] = actor.hitbox.height.toLua()

View File

@@ -150,10 +150,10 @@ object CollisionSolver {
// if they actually makes collision (e.g. player vs ball), solve it
if (a makesCollisionWith b) {
val ux_1 = a.veloX
val ux_2 = b.veloX
val uy_1 = a.veloY
val uy_2 = b.veloY
val ux_1 = a.moveDelta.x
val ux_2 = b.moveDelta.x
val uy_1 = a.moveDelta.y
val uy_2 = b.moveDelta.y
val m1 = a.mass
val m2 = b.mass

View File

@@ -24,8 +24,8 @@ class ThreadProcessNoiseLayers(val startIndex: Int, val endIndex: Int,
val sampleTheta = (x.toDouble() / WorldGenerator.WIDTH) * WorldGenerator.TWO_PI
val sampleOffset = (WorldGenerator.WIDTH / sampleDensity) / 8.0
val sampleX = Math.sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only
val sampleY = Math.cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled
val sampleZ = y / sampleDensity
val sampleZ = Math.cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled
val sampleY = y / sampleDensity
val noise: Double = record.noiseModule.get(sampleX, sampleY, sampleZ)
val fromTerr = record.replaceFromTerrain

View File

@@ -38,9 +38,7 @@ object WorldGenerator {
private val NOISE_SIMPLEX_ORE_START = 1.42
private val NOISE_SIMPLEX_ORE_END = 1.28
private val HILL_WIDTH = 256 // power of two!
//private val MAX_HILL_HEIGHT = 100
private val TERRAIN_UNDULATION = 250
private val TERRAIN_UNDULATION = 200
private val SIMPLEXGEN_LARGEST_FEATURE = 200
@@ -51,8 +49,8 @@ object WorldGenerator {
private var GLACIER_MOUNTAIN_WIDTH = 900
private val GLACIER_MOUNTAIN_HEIGHT = 300
private val CAVEGEN_THRE_START = 0.95
private val CAVEGEN_THRE_END = 0.67
private val CAVEGEN_THRE_START = 0.4
private val CAVEGEN_THRE_END = 0.1
private var worldOceanPosition: Int = -1
@@ -109,12 +107,18 @@ object WorldGenerator {
* Todo: Lakes! Aquifers! Lava chambers!
* Todo: deserts (variants: SAND_DESERT, SAND_RED)
* Todo: volcano(es?)
* Done: variants of beach (SAND, SAND_BEACH, SAND_BLACK, SAND_GREEN)
* TODO: variants of beach (SAND, SAND_BEACH, SAND_BLACK, SAND_GREEN)
*
*
* Hark! We use cylindrical sampling
*
* x, z: X-axis sampling
* y: Y-axis sampling
*/
val noiseArray = arrayOf(
TaggedJoise("Carving caves", noiseRidged(1.7, 1.4), 1.0, TILE_MACRO_ALL, TILE_MACRO_ALL, Tile.AIR, NoiseFilterSqrt, CAVEGEN_THRE_START, CAVEGEN_THRE_END)
, TaggedJoise("Collapsing caves", noiseBlobs(0.5), 0.3, Tile.AIR, Tile.STONE, Tile.STONE, NoiseFilterUniform)
// TODO cave one featured in http://accidentalnoise.sourceforge.net/minecraftworlds.html
TaggedJoise("Carving caves", noiseCave(), 1.0, TILE_MACRO_ALL, TILE_MACRO_ALL, Tile.AIR, NoiseFilterSqrt, CAVEGEN_THRE_START, CAVEGEN_THRE_END)
// , TaggedJoise("Collapsing caves", noiseBlobs(0.5), 0.3, Tile.AIR, Tile.STONE, Tile.STONE, NoiseFilterUniform)
//
//, TaggedJoise("Putting stone patches on the ground", noiseBlobs(0.8), 1.02f, intArrayOf(Tile.DIRT, Tile.GRASS), Tile.DIRT, Tile.STONE, NoiseFilterQuadratic, NOISE_GRAD_END, NOISE_GRAD_START)
//, TaggedJoise("Placing dirt spots in the cave", noiseBlobs(0.5), 0.98f, Tile.STONE, Tile.STONE, Tile.DIRT, NoiseFilterQuadratic, NOISE_GRAD_END, NOISE_GRAD_START)
@@ -179,19 +183,69 @@ object WorldGenerator {
val ridged_scale = ModuleScaleDomain()
ridged_scale.setScaleX(xStretch.toDouble())
ridged_scale.setScaleY(yStretch.toDouble())
ridged_scale.setScaleY(xStretch.toDouble())
ridged_scale.setScaleZ(yStretch.toDouble())
ridged_scale.setSource(ridged_autocorrect)
return Joise(ridged_scale)
}
private fun noiseCave(): Joise {
val caveMagic: Long = 0x00215741CDF // Urist McDF
val cavePerturbMagic: Long = 0xA2410C // Armok
val arbitraryScale = 4.0
val cave_shape = ModuleFractal()
cave_shape.setType(ModuleFractal.FractalType.RIDGEMULTI)
cave_shape.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
cave_shape.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
cave_shape.setNumOctaves(1)
cave_shape.setFrequency(4.0)
cave_shape.seed = SEED xor caveMagic
val cave_select = ModuleSelect()
cave_select.setLowSource(1.0)
cave_select.setHighSource(0.0)
cave_select.setControlSource(cave_shape)
cave_select.setThreshold(0.8)
cave_select.setFalloff(0.0)
val cave_perturb_fractal = ModuleFractal()
cave_perturb_fractal.setType(ModuleFractal.FractalType.FBM)
cave_perturb_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
cave_perturb_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
cave_perturb_fractal.setNumOctaves(6)
cave_perturb_fractal.setFrequency(3.0)
cave_perturb_fractal.seed = SEED xor cavePerturbMagic
val cave_perturb_scale = ModuleScaleOffset()
cave_perturb_scale.setSource(cave_perturb_fractal)
cave_perturb_scale.setScale(0.5)
cave_perturb_scale.setOffset(0.0)
val cave_perturb = ModuleTranslateDomain()
cave_perturb.setSource(cave_perturb_fractal)
cave_perturb.setAxisXSource(cave_perturb_scale)
val cave_scale = ModuleScaleDomain()
cave_scale.setScaleX(1.0 / arbitraryScale)
cave_scale.setScaleZ(1.0 / arbitraryScale)
cave_scale.setScaleY(1.0 / arbitraryScale)
cave_scale.setSource(cave_perturb)
return Joise(cave_scale)
}
private fun noiseBlobs(frequency: Double): Joise {
val ridgedMagic: Long = 0x4114EC2AF7 // minecraft
val ridged = ModuleFractal()
ridged.setType(ModuleFractal.FractalType.FBM)
ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
ridged.setNumOctaves(2)
ridged.setFrequency(frequency)
ridged.seed = Random().nextLong()
ridged.seed = SEED xor ridgedMagic
val brownian_select = ModuleSelect()
brownian_select.setControlSource(ridged)
@@ -269,8 +323,15 @@ object WorldGenerator {
val noiseMap = Array(HEIGHT, { BitSet(WIDTH) })
// Height = Terrain undulation times 2.
val SCALE_X: Double = (TERRAIN_UNDULATION * 0.5).toDouble()
val SCALE_Y: Double = (TERRAIN_UNDULATION * 0.25).toDouble()
val SCALE_X: Double = TERRAIN_UNDULATION * 1.33
val SCALE_Y: Double = TERRAIN_UNDULATION * 1.0
/* Init */
val lowlandMagic: Long = 0x41A21A114DBE56 // Maria Lindberg
val highlandMagic: Long = 0x0114E091 // Olive Oyl
val mountainMagic: Long = 0x115AA4DE2504 // Lisa Anderson
val selectionMagic: Long = 0x41E10D9B100 // Melody Blue
val ground_gradient = ModuleGradient()
ground_gradient.setGradient(0.0, 0.0, 0.0, 1.0)
@@ -281,19 +342,19 @@ object WorldGenerator {
lowland_shape_fractal.setType(ModuleFractal.FractalType.FBM)
lowland_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
lowland_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
lowland_shape_fractal.setNumOctaves(4)
lowland_shape_fractal.setFrequency(0.6)
lowland_shape_fractal.seed = SEED xor random.nextLong()
//println(lowland_shape_fractal.seed)
lowland_shape_fractal.setNumOctaves(2)
lowland_shape_fractal.setFrequency(1.0)
lowland_shape_fractal.seed = SEED xor lowlandMagic
val lowland_autocorrect = ModuleAutoCorrect()
lowland_autocorrect.setRange(0.0, 1.0)
lowland_autocorrect.setSource(lowland_shape_fractal)
lowland_autocorrect.setLow(0.0)
lowland_autocorrect.setHigh(1.0)
val lowland_scale = ModuleScaleOffset()
lowland_scale.setSource(lowland_autocorrect)
lowland_scale.setScale(0.8)
lowland_scale.setOffset(-2.75)
lowland_scale.setScale(0.2)
lowland_scale.setOffset(-0.25)
val lowland_y_scale = ModuleScaleDomain()
lowland_y_scale.setSource(lowland_scale)
@@ -303,25 +364,26 @@ object WorldGenerator {
lowland_terrain.setSource(ground_gradient)
lowland_terrain.setAxisYSource(lowland_y_scale)
/* highlands */
val highland_shape_fractal = ModuleFractal()
highland_shape_fractal.setType(ModuleFractal.FractalType.RIDGEMULTI)
highland_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
highland_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
highland_shape_fractal.setNumOctaves(4)
highland_shape_fractal.setFrequency(0.5) // horizontal size. Higher == narrower
highland_shape_fractal.seed = SEED xor random.nextLong()
//println(highland_shape_fractal.seed)
highland_shape_fractal.setNumOctaves(2)
highland_shape_fractal.setFrequency(2.0)
highland_shape_fractal.seed = SEED xor highlandMagic
val highland_autocorrect = ModuleAutoCorrect()
highland_autocorrect.setSource(highland_shape_fractal)
highland_autocorrect.setRange(0.0, 1.0)
highland_autocorrect.setLow(0.0)
highland_autocorrect.setHigh(1.0)
val highland_scale = ModuleScaleOffset()
highland_scale.setSource(highland_autocorrect)
highland_scale.setScale(1.4) // vertical size. Higher == taller
highland_scale.setOffset(-2.25)
highland_scale.setScale(0.45)
highland_scale.setOffset(0.0)
val highland_y_scale = ModuleScaleDomain()
highland_y_scale.setSource(highland_scale)
@@ -331,55 +393,53 @@ object WorldGenerator {
highland_terrain.setSource(ground_gradient)
highland_terrain.setAxisYSource(highland_y_scale)
/* mountains */
val mountain_shape_fractal = ModuleFractal()
mountain_shape_fractal.setType(ModuleFractal.FractalType.BILLOW)
mountain_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
mountain_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
mountain_shape_fractal.setNumOctaves(6)
mountain_shape_fractal.setFrequency(0.55)
mountain_shape_fractal.seed = SEED xor random.nextLong()
//println(mountain_shape_fractal.seed)
mountain_shape_fractal.setNumOctaves(4)
mountain_shape_fractal.setFrequency(1.0)
mountain_shape_fractal.seed = SEED xor mountainMagic
val mountain_autocorrect = ModuleAutoCorrect()
mountain_autocorrect.setSource(mountain_shape_fractal)
mountain_autocorrect.setRange(0.0, 1.0)
mountain_autocorrect.setLow(0.0)
mountain_autocorrect.setHigh(1.0)
val mountain_scale = ModuleScaleOffset()
mountain_scale.setSource(mountain_autocorrect)
mountain_scale.setScale(1.66)
mountain_scale.setOffset(-1.25)
mountain_scale.setScale(0.75)
mountain_scale.setOffset(0.25)
val mountain_y_scale = ModuleScaleDomain()
mountain_y_scale.setSource(mountain_scale)
mountain_y_scale.setScaleY(0.1)
mountain_y_scale.setScaleY(0.1) // controls "quirkiness" of the mountain
val mountain_terrain = ModuleTranslateDomain()
mountain_terrain.setSource(ground_gradient)
mountain_terrain.setAxisYSource(mountain_y_scale)
/* selection */
val terrain_type_fractal = ModuleFractal()
terrain_type_fractal.setType(ModuleFractal.FractalType.MULTI)
terrain_type_fractal.setType(ModuleFractal.FractalType.FBM)
terrain_type_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
terrain_type_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
terrain_type_fractal.setNumOctaves(5)
terrain_type_fractal.setFrequency(0.4) // <= 0.33
terrain_type_fractal.seed = SEED xor random.nextLong()
//println(terrain_type_fractal.seed)
terrain_type_fractal.setNumOctaves(3)
terrain_type_fractal.setFrequency(0.5)
terrain_type_fractal.seed = SEED xor selectionMagic
val terrain_autocorrect = ModuleAutoCorrect()
terrain_autocorrect.setSource(terrain_type_fractal)
terrain_autocorrect.setRange(0.0, 1.0)
val terrain_type_scale = ModuleScaleDomain()
terrain_type_scale.setScaleY(0.33)
terrain_type_scale.setSource(terrain_autocorrect)
terrain_autocorrect.setLow(0.0)
terrain_autocorrect.setHigh(1.0)
val terrain_type_cache = ModuleCache()
terrain_type_cache.setSource(terrain_type_scale)
terrain_type_cache.setSource(terrain_autocorrect)
val highland_mountain_select = ModuleSelect()
highland_mountain_select.setLowSource(highland_terrain)
@@ -395,13 +455,13 @@ object WorldGenerator {
highland_lowland_select.setThreshold(0.25)
highland_lowland_select.setFalloff(0.15)
val ground_select = ModuleSelect()
ground_select.setLowSource(0.0)
ground_select.setHighSource(1.0)
ground_select.setThreshold(0.5)
ground_select.setControlSource(highland_lowland_select)
val joise = Joise(ground_select)
// fill the area as Joise map
@@ -414,17 +474,17 @@ object WorldGenerator {
x / SCALE_X,
y / SCALE_Y
) == 1.0)*/
// circular sampling
// cylindrical sampling
// Mapping function:
// World(x, y) -> Joise(sin x, y, cos x)
val sampleTheta = (x.toDouble() / WIDTH) * TWO_PI
val sampleOffset = (WIDTH / SCALE_X) / 4.0
val sampleX = Math.sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only
val sampleZ = Math.cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled
val sampleY = y / SCALE_Y
val map: Boolean = (
joise.get(sampleX, sampleY, sampleZ) == 1.0
)
val sampleY = y / SCALE_Y * 1.5 - 0.6
val map: Boolean = joise.get(sampleX, sampleY, sampleZ) == 1.0
// FIXME joise.get(sampleX, sampleY, sampleZ) returns all zero
noiseMap[y + TERRAIN_AVERAGE_HEIGHT - (TERRAIN_UNDULATION / 2)].set(x, map)
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB