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. * Works like Ampere in electronics.
- Health: Regen per time - Health: Regen per time
- Magic: Out power 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 ### ### Looms for custom pattern ###
- Players can create their own décors (hang on wall), dresses. - 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 ### ### Music making ###
@@ -25,13 +26,13 @@ Connect two or more tracker head to play the array of trackers play simultaneous
<actorid>.json <actorid>.json
{ {
notes = [arr<int>, fixed size of 48], notes = [arr<key: Int>(64)], // 64 notes per track
speed = 120 speed = 120
} }
*int: (0-63) number of the note pitch that is struck. 32: Middle C (C3). - key: C1-D6 (63 keys)
'A' just above of Middle C (A3) has base pitch of 440 Hz. - speed: in BPM
*speed: in BPM - tuning: A440
## Aimhack ## ## Aimhack ##

View File

@@ -194,7 +194,7 @@ constructor() : BasicGameState() {
/////////////////////////// ///////////////////////////
TilePropUtil.dynamicLumFuncTickClock() TilePropUtil.dynamicLumFuncTickClock()
world.updateWorldTime(delta) world.updateWorldTime(delta)
WorldSimulator(player, delta) //WorldSimulator(player, delta)
WeatherMixer.update(gc, delta) WeatherMixer.update(gc, delta)
TileStats.update() TileStats.update()
if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride) if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride)
@@ -300,8 +300,8 @@ constructor() : BasicGameState() {
private fun setAppTitle() { private fun setAppTitle() {
Terrarum.appgc.setTitle( Terrarum.appgc.setTitle(
Terrarum.NAME + Terrarum.NAME +
" — F: ${Terrarum.appgc.fps} (${Terrarum.TARGET_INTERNAL_FPS})" + " — F: ${Terrarum.appgc.fps} (${Terrarum.TARGET_INTERNAL_FPS})")
" — M: ${Terrarum.memInUse}M / ${Terrarum.memTotal}M / ${Terrarum.memXmx}M") //" — M: ${Terrarum.memInUse}M / ${Terrarum.memTotal}M / ${Terrarum.memXmx}M")
} }
override fun render(gc: GameContainer, sbg: StateBasedGame, gwin: Graphics) { override fun render(gc: GameContainer, sbg: StateBasedGame, gwin: Graphics) {
@@ -405,12 +405,12 @@ constructor() : BasicGameState() {
// velocity // velocity
worldG.color = GameFontBase.codeToCol["g"] worldG.color = GameFontBase.codeToCol["g"]
worldG.drawString( 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.posX.toFloat(),
actor.hitbox.pointedY.toFloat() + 4 + 8 actor.hitbox.pointedY.toFloat() + 4 + 8
) )
worldG.drawString( worldG.drawString(
"${0x7F.toChar()}Y ${actor.velocity.y}", "${0x7F.toChar()}Y ${actor.moveDelta.y}",
actor.hitbox.posX.toFloat(), actor.hitbox.posX.toFloat(),
actor.hitbox.pointedY.toFloat() + 4 + 8 * 2 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(StateNoiseTexGen())
//addState(StateBlurTest()) //addState(StateBlurTest())
//addState(StateShaderTest()) //addState(StateShaderTest())
//addState(StateNoiseTester())
ingame = StateInGame() ingame = StateInGame()
addState(ingame) addState(ingame)

View File

@@ -5,6 +5,23 @@ import net.torvald.terrarum.ui.ConsoleWindow
import org.apache.commons.codec.digest.DigestUtils 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. * Created by minjaesong on 16-02-19.
*/ */
internal object Authenticator : ConsoleCommand { internal object Authenticator : ConsoleCommand {

View File

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

View File

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

View File

@@ -53,7 +53,7 @@ open class ProjectileSimple(
posPre = Point2d(fromPoint.x, fromPoint.y) posPre = Point2d(fromPoint.x, fromPoint.y)
// lightbox sized 8x8 centered to the bullet // lightbox sized 8x8 centered to the bullet
lightBoxList.add(Hitbox(-4.0, -4.0, 8.0, 8.0)) 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 damage = bulletDatabase[type][OFFSET_DAMAGE] as Int
displayColour = bulletDatabase[type][OFFSET_COL] as Color 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 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["posX"] = actor.hitbox.centeredX.toLua()
t["posY"] = actor.hitbox.centeredY.toLua() t["posY"] = actor.hitbox.centeredY.toLua()
t["veloX"] = actor.veloX.toLua() t["veloX"] = actor.moveDelta.x.toLua()
t["veloY"] = actor.veloY.toLua() t["veloY"] = actor.moveDelta.y.toLua()
t["width"] = actor.hitbox.width.toLua() t["width"] = actor.hitbox.width.toLua()
t["height"] = actor.hitbox.height.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 they actually makes collision (e.g. player vs ball), solve it
if (a makesCollisionWith b) { if (a makesCollisionWith b) {
val ux_1 = a.veloX val ux_1 = a.moveDelta.x
val ux_2 = b.veloX val ux_2 = b.moveDelta.x
val uy_1 = a.veloY val uy_1 = a.moveDelta.y
val uy_2 = b.veloY val uy_2 = b.moveDelta.y
val m1 = a.mass val m1 = a.mass
val m2 = b.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 sampleTheta = (x.toDouble() / WorldGenerator.WIDTH) * WorldGenerator.TWO_PI
val sampleOffset = (WorldGenerator.WIDTH / sampleDensity) / 8.0 val sampleOffset = (WorldGenerator.WIDTH / sampleDensity) / 8.0
val sampleX = Math.sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only 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 = Math.cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled
val sampleZ = y / sampleDensity val sampleY = y / sampleDensity
val noise: Double = record.noiseModule.get(sampleX, sampleY, sampleZ) val noise: Double = record.noiseModule.get(sampleX, sampleY, sampleZ)
val fromTerr = record.replaceFromTerrain 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_START = 1.42
private val NOISE_SIMPLEX_ORE_END = 1.28 private val NOISE_SIMPLEX_ORE_END = 1.28
private val HILL_WIDTH = 256 // power of two! private val TERRAIN_UNDULATION = 200
//private val MAX_HILL_HEIGHT = 100
private val TERRAIN_UNDULATION = 250
private val SIMPLEXGEN_LARGEST_FEATURE = 200 private val SIMPLEXGEN_LARGEST_FEATURE = 200
@@ -51,8 +49,8 @@ object WorldGenerator {
private var GLACIER_MOUNTAIN_WIDTH = 900 private var GLACIER_MOUNTAIN_WIDTH = 900
private val GLACIER_MOUNTAIN_HEIGHT = 300 private val GLACIER_MOUNTAIN_HEIGHT = 300
private val CAVEGEN_THRE_START = 0.95 private val CAVEGEN_THRE_START = 0.4
private val CAVEGEN_THRE_END = 0.67 private val CAVEGEN_THRE_END = 0.1
private var worldOceanPosition: Int = -1 private var worldOceanPosition: Int = -1
@@ -109,12 +107,18 @@ object WorldGenerator {
* Todo: Lakes! Aquifers! Lava chambers! * Todo: Lakes! Aquifers! Lava chambers!
* Todo: deserts (variants: SAND_DESERT, SAND_RED) * Todo: deserts (variants: SAND_DESERT, SAND_RED)
* Todo: volcano(es?) * 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( 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) // TODO cave one featured in http://accidentalnoise.sourceforge.net/minecraftworlds.html
, TaggedJoise("Collapsing caves", noiseBlobs(0.5), 0.3, Tile.AIR, Tile.STONE, Tile.STONE, NoiseFilterUniform) 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("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) //, 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() val ridged_scale = ModuleScaleDomain()
ridged_scale.setScaleX(xStretch.toDouble()) 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) ridged_scale.setSource(ridged_autocorrect)
return Joise(ridged_scale) 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 { private fun noiseBlobs(frequency: Double): Joise {
val ridgedMagic: Long = 0x4114EC2AF7 // minecraft
val ridged = ModuleFractal() val ridged = ModuleFractal()
ridged.setType(ModuleFractal.FractalType.FBM) ridged.setType(ModuleFractal.FractalType.FBM)
ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
ridged.setNumOctaves(2) ridged.setNumOctaves(2)
ridged.setFrequency(frequency) ridged.setFrequency(frequency)
ridged.seed = Random().nextLong() ridged.seed = SEED xor ridgedMagic
val brownian_select = ModuleSelect() val brownian_select = ModuleSelect()
brownian_select.setControlSource(ridged) brownian_select.setControlSource(ridged)
@@ -269,8 +323,15 @@ object WorldGenerator {
val noiseMap = Array(HEIGHT, { BitSet(WIDTH) }) val noiseMap = Array(HEIGHT, { BitSet(WIDTH) })
// Height = Terrain undulation times 2. // Height = Terrain undulation times 2.
val SCALE_X: Double = (TERRAIN_UNDULATION * 0.5).toDouble() val SCALE_X: Double = TERRAIN_UNDULATION * 1.33
val SCALE_Y: Double = (TERRAIN_UNDULATION * 0.25).toDouble() 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() val ground_gradient = ModuleGradient()
ground_gradient.setGradient(0.0, 0.0, 0.0, 1.0) 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.setType(ModuleFractal.FractalType.FBM)
lowland_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT) lowland_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
lowland_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) lowland_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
lowland_shape_fractal.setNumOctaves(4) lowland_shape_fractal.setNumOctaves(2)
lowland_shape_fractal.setFrequency(0.6) lowland_shape_fractal.setFrequency(1.0)
lowland_shape_fractal.seed = SEED xor random.nextLong() lowland_shape_fractal.seed = SEED xor lowlandMagic
//println(lowland_shape_fractal.seed)
val lowland_autocorrect = ModuleAutoCorrect() val lowland_autocorrect = ModuleAutoCorrect()
lowland_autocorrect.setRange(0.0, 1.0)
lowland_autocorrect.setSource(lowland_shape_fractal) lowland_autocorrect.setSource(lowland_shape_fractal)
lowland_autocorrect.setLow(0.0)
lowland_autocorrect.setHigh(1.0)
val lowland_scale = ModuleScaleOffset() val lowland_scale = ModuleScaleOffset()
lowland_scale.setSource(lowland_autocorrect) lowland_scale.setSource(lowland_autocorrect)
lowland_scale.setScale(0.8) lowland_scale.setScale(0.2)
lowland_scale.setOffset(-2.75) lowland_scale.setOffset(-0.25)
val lowland_y_scale = ModuleScaleDomain() val lowland_y_scale = ModuleScaleDomain()
lowland_y_scale.setSource(lowland_scale) lowland_y_scale.setSource(lowland_scale)
@@ -303,25 +364,26 @@ object WorldGenerator {
lowland_terrain.setSource(ground_gradient) lowland_terrain.setSource(ground_gradient)
lowland_terrain.setAxisYSource(lowland_y_scale) lowland_terrain.setAxisYSource(lowland_y_scale)
/* highlands */ /* highlands */
val highland_shape_fractal = ModuleFractal() val highland_shape_fractal = ModuleFractal()
highland_shape_fractal.setType(ModuleFractal.FractalType.RIDGEMULTI) highland_shape_fractal.setType(ModuleFractal.FractalType.RIDGEMULTI)
highland_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT) highland_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
highland_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) highland_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
highland_shape_fractal.setNumOctaves(4) highland_shape_fractal.setNumOctaves(2)
highland_shape_fractal.setFrequency(0.5) // horizontal size. Higher == narrower highland_shape_fractal.setFrequency(2.0)
highland_shape_fractal.seed = SEED xor random.nextLong() highland_shape_fractal.seed = SEED xor highlandMagic
//println(highland_shape_fractal.seed)
val highland_autocorrect = ModuleAutoCorrect() val highland_autocorrect = ModuleAutoCorrect()
highland_autocorrect.setSource(highland_shape_fractal) 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() val highland_scale = ModuleScaleOffset()
highland_scale.setSource(highland_autocorrect) highland_scale.setSource(highland_autocorrect)
highland_scale.setScale(1.4) // vertical size. Higher == taller highland_scale.setScale(0.45)
highland_scale.setOffset(-2.25) highland_scale.setOffset(0.0)
val highland_y_scale = ModuleScaleDomain() val highland_y_scale = ModuleScaleDomain()
highland_y_scale.setSource(highland_scale) highland_y_scale.setSource(highland_scale)
@@ -331,55 +393,53 @@ object WorldGenerator {
highland_terrain.setSource(ground_gradient) highland_terrain.setSource(ground_gradient)
highland_terrain.setAxisYSource(highland_y_scale) highland_terrain.setAxisYSource(highland_y_scale)
/* mountains */ /* mountains */
val mountain_shape_fractal = ModuleFractal() val mountain_shape_fractal = ModuleFractal()
mountain_shape_fractal.setType(ModuleFractal.FractalType.BILLOW) mountain_shape_fractal.setType(ModuleFractal.FractalType.BILLOW)
mountain_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT) mountain_shape_fractal.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
mountain_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) mountain_shape_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
mountain_shape_fractal.setNumOctaves(6) mountain_shape_fractal.setNumOctaves(4)
mountain_shape_fractal.setFrequency(0.55) mountain_shape_fractal.setFrequency(1.0)
mountain_shape_fractal.seed = SEED xor random.nextLong() mountain_shape_fractal.seed = SEED xor mountainMagic
//println(mountain_shape_fractal.seed)
val mountain_autocorrect = ModuleAutoCorrect() val mountain_autocorrect = ModuleAutoCorrect()
mountain_autocorrect.setSource(mountain_shape_fractal) 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() val mountain_scale = ModuleScaleOffset()
mountain_scale.setSource(mountain_autocorrect) mountain_scale.setSource(mountain_autocorrect)
mountain_scale.setScale(1.66) mountain_scale.setScale(0.75)
mountain_scale.setOffset(-1.25) mountain_scale.setOffset(0.25)
val mountain_y_scale = ModuleScaleDomain() val mountain_y_scale = ModuleScaleDomain()
mountain_y_scale.setSource(mountain_scale) 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() val mountain_terrain = ModuleTranslateDomain()
mountain_terrain.setSource(ground_gradient) mountain_terrain.setSource(ground_gradient)
mountain_terrain.setAxisYSource(mountain_y_scale) mountain_terrain.setAxisYSource(mountain_y_scale)
/* selection */ /* selection */
val terrain_type_fractal = ModuleFractal() 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.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
terrain_type_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) terrain_type_fractal.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
terrain_type_fractal.setNumOctaves(5) terrain_type_fractal.setNumOctaves(3)
terrain_type_fractal.setFrequency(0.4) // <= 0.33 terrain_type_fractal.setFrequency(0.5)
terrain_type_fractal.seed = SEED xor random.nextLong() terrain_type_fractal.seed = SEED xor selectionMagic
//println(terrain_type_fractal.seed)
val terrain_autocorrect = ModuleAutoCorrect() val terrain_autocorrect = ModuleAutoCorrect()
terrain_autocorrect.setSource(terrain_type_fractal) terrain_autocorrect.setSource(terrain_type_fractal)
terrain_autocorrect.setRange(0.0, 1.0) terrain_autocorrect.setLow(0.0)
terrain_autocorrect.setHigh(1.0)
val terrain_type_scale = ModuleScaleDomain()
terrain_type_scale.setScaleY(0.33)
terrain_type_scale.setSource(terrain_autocorrect)
val terrain_type_cache = ModuleCache() val terrain_type_cache = ModuleCache()
terrain_type_cache.setSource(terrain_type_scale) terrain_type_cache.setSource(terrain_autocorrect)
val highland_mountain_select = ModuleSelect() val highland_mountain_select = ModuleSelect()
highland_mountain_select.setLowSource(highland_terrain) highland_mountain_select.setLowSource(highland_terrain)
@@ -395,13 +455,13 @@ object WorldGenerator {
highland_lowland_select.setThreshold(0.25) highland_lowland_select.setThreshold(0.25)
highland_lowland_select.setFalloff(0.15) highland_lowland_select.setFalloff(0.15)
val ground_select = ModuleSelect() val ground_select = ModuleSelect()
ground_select.setLowSource(0.0) ground_select.setLowSource(0.0)
ground_select.setHighSource(1.0) ground_select.setHighSource(1.0)
ground_select.setThreshold(0.5) ground_select.setThreshold(0.5)
ground_select.setControlSource(highland_lowland_select) ground_select.setControlSource(highland_lowland_select)
val joise = Joise(ground_select) val joise = Joise(ground_select)
// fill the area as Joise map // fill the area as Joise map
@@ -414,17 +474,17 @@ object WorldGenerator {
x / SCALE_X, x / SCALE_X,
y / SCALE_Y y / SCALE_Y
) == 1.0)*/ ) == 1.0)*/
// circular sampling // cylindrical sampling
// Mapping function: // Mapping function:
// World(x, y) -> Joise(sin x, y, cos x) // World(x, y) -> Joise(sin x, y, cos x)
val sampleTheta = (x.toDouble() / WIDTH) * TWO_PI val sampleTheta = (x.toDouble() / WIDTH) * TWO_PI
val sampleOffset = (WIDTH / SCALE_X) / 4.0 val sampleOffset = (WIDTH / SCALE_X) / 4.0
val sampleX = Math.sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only 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 sampleZ = Math.cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled
val sampleY = y / SCALE_Y val sampleY = y / SCALE_Y * 1.5 - 0.6
val map: Boolean = ( val map: Boolean = joise.get(sampleX, sampleY, sampleZ) == 1.0
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) 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