mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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 ##
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
281
src/net/torvald/terrarum/StateNoiseTester.kt
Normal file
281
src/net/torvald/terrarum/StateNoiseTester.kt
Normal 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)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
||||
//addState(StateNoiseTexGen())
|
||||
//addState(StateBlurTest())
|
||||
//addState(StateShaderTest())
|
||||
//addState(StateNoiseTester())
|
||||
|
||||
ingame = StateInGame()
|
||||
addState(ingame)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
Reference in New Issue
Block a user