Experiment with biomes
This commit is contained in:
parent
cccd74f1a5
commit
007a9f7989
@ -18,15 +18,13 @@ class MapGenerator
|
||||
$this->noise = new Noise($seed);
|
||||
}
|
||||
|
||||
public function getPixels(): array
|
||||
public function getPixels(): iterable
|
||||
{
|
||||
$pixels = [];
|
||||
for ($x = 0; $x < $this->width; $x++) {
|
||||
for ($y = 0; $y < $this->height; $y++) {
|
||||
$pixels[] = $this->drawPixel($x, $y, $this->noise->generate($x, $y));
|
||||
yield $this->drawPixel($x, $y, $this->noise->generate($x, $y));
|
||||
}
|
||||
}
|
||||
return $pixels;
|
||||
}
|
||||
|
||||
private function drawPixel(int $x, int $y, Color $color): string
|
||||
|
@ -6,18 +6,20 @@ use Ardent\Game\dto\Color;
|
||||
|
||||
class Noise
|
||||
{
|
||||
private readonly PerlinNoise $noise;
|
||||
private readonly PerlinNoise $height;
|
||||
private readonly PerlinNoise $biome;
|
||||
|
||||
public function __construct(
|
||||
?int $seed = null,
|
||||
)
|
||||
{
|
||||
$this->noise = new PerlinNoise($seed);
|
||||
$this->height = new PerlinNoise($seed);
|
||||
$this->biome = new PerlinNoise($seed + 1);
|
||||
}
|
||||
|
||||
private function getTransitions(): array
|
||||
private function getGrassland(): array
|
||||
{
|
||||
$deepwater = new Color('#006eb4');
|
||||
$deepwater = new Color(0, 110, 180);
|
||||
$water = new Color(0, 156, 244);
|
||||
$sand = new Color(238, 226, 104);
|
||||
$grass = new Color(25, 171, 64);
|
||||
@ -26,7 +28,7 @@ class Noise
|
||||
|
||||
return [
|
||||
[-1.0, $deepwater],
|
||||
[-0.9, $water],
|
||||
[-0.997, $water],
|
||||
[0.0, $sand],
|
||||
[0.8, $grass],
|
||||
[0.997, $mountain],
|
||||
@ -34,22 +36,46 @@ class Noise
|
||||
];
|
||||
}
|
||||
|
||||
private function getDesert(): array
|
||||
{
|
||||
$lightSand = new Color(248, 255, 111);
|
||||
$sand = new Color(238, 226, 104);
|
||||
$darkSand = new Color(161, 153, 70);
|
||||
|
||||
return [
|
||||
[-1.0, $sand],
|
||||
[1.0, $darkSand],
|
||||
];
|
||||
}
|
||||
|
||||
public function generate(int $x, int $y): Color
|
||||
{
|
||||
$rand = $this->noise->random2D($x, $y, 150);
|
||||
$transitions = $this->getTransitions();
|
||||
$height = $this->height->random2D($x, $y, 150);
|
||||
|
||||
for ($i = 0; $i < count($transitions) - 1; $i++) {
|
||||
$transition = $transitions[$i];
|
||||
$nextTransition = $transitions[$i + 1];
|
||||
if ($rand >= $transition[0] && $rand < $nextTransition[0]) {
|
||||
return $this->lerpTerrain($transition[1], $nextTransition[1], $transition[0], $nextTransition[0], $rand);
|
||||
}
|
||||
}
|
||||
// $biomes = [
|
||||
// [-1.0, $this->transitionTerrain($this->getGrassland(), $height)],
|
||||
// [1.01, $this->transitionTerrain($this->getDesert(), $height)],
|
||||
// ];
|
||||
// $biome = $this->biome->random2D($x, $y, 200, 5);
|
||||
|
||||
return $this->transitionTerrain($this->getGrassland(), $height);
|
||||
}
|
||||
|
||||
public function lerpTerrain(Color $color1, Color $color2, float $begin, float $end, float $value): Color
|
||||
{
|
||||
return $color1->lerp($color2, ($value - $begin) * (1.0 / ($end - $begin)));
|
||||
}
|
||||
|
||||
public function transitionTerrain(array $transitions, float $height): Color
|
||||
{
|
||||
$color = new Color('#000000');
|
||||
for ($i = 0; $i < count($transitions) - 1; $i++) {
|
||||
$transition = $transitions[$i];
|
||||
$nextTransition = $transitions[$i + 1];
|
||||
if ($height >= $transition[0] && $height < $nextTransition[0]) {
|
||||
$color = $this->lerpTerrain($transition[1], $nextTransition[1], $transition[0], $nextTransition[0], $height);
|
||||
}
|
||||
}
|
||||
return $color;
|
||||
}
|
||||
}
|
@ -148,7 +148,7 @@ class PerlinNoise
|
||||
return $value;
|
||||
}
|
||||
|
||||
function random2D(float $x, float $y, ?int $size = NULL): float
|
||||
function random2D(float $x, float $y, ?int $size = null, float $multiplier = 1.0): float
|
||||
{
|
||||
if ($size === NULL) {
|
||||
$size = $this->_default_size;
|
||||
@ -167,7 +167,7 @@ class PerlinNoise
|
||||
|
||||
// $value /= 2.0;
|
||||
|
||||
return $this->sigmoid($value);
|
||||
return $this->sigmoid($value * $multiplier);
|
||||
}
|
||||
|
||||
private function sigmoid(float $t): float
|
||||
|
@ -5,14 +5,14 @@ namespace Ardent\Game\dto;
|
||||
class Color
|
||||
{
|
||||
public function __construct(
|
||||
private int|string $red,
|
||||
private int $green = 0,
|
||||
private int $blue = 0,
|
||||
private int|string $red,
|
||||
private int $green = 0,
|
||||
private int $blue = 0,
|
||||
private readonly int $alpha = 255
|
||||
)
|
||||
{
|
||||
if (is_string($red)) {
|
||||
list($this->red, $this->green, $this->blue) = sscanf($this->red, "#%02x%02x%02x");
|
||||
[$this->red, $this->green, $this->blue] = sscanf($this->red, "#%02x%02x%02x");
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,4 +31,19 @@ class Color
|
||||
alpha: $this->alpha + ($color->alpha - $this->alpha) * $range,
|
||||
);
|
||||
}
|
||||
|
||||
public function brighten(float $amount): Color
|
||||
{
|
||||
return new Color(
|
||||
red: $this->clamp($this->red + $amount, 0, 255),
|
||||
green: $this->clamp($this->green + $amount, 0, 255),
|
||||
blue: $this->clamp($this->blue + $amount, 0, 255),
|
||||
alpha: $this->alpha,
|
||||
);
|
||||
}
|
||||
|
||||
private function clamp(int $current, int $min, int $max): int
|
||||
{
|
||||
return max($min, min($max, $current));
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ include "MapGenerator.php";
|
||||
$renderer = new Renderer();
|
||||
$map = new MapGenerator($renderer, $_GET['seed'], (int)$_GET['width'], (int)$_GET['height']);
|
||||
|
||||
$start = microtime(true);
|
||||
echo $renderer->render('map.html.twig', [
|
||||
'map' => $map,
|
||||
]);
|
||||
echo 'time: ' . microtime(true) - $start;
|
||||
|
Loading…
Reference in New Issue
Block a user