Experiment with biomes

This commit is contained in:
Tim 2023-06-05 02:54:54 +02:00
parent cccd74f1a5
commit 007a9f7989
5 changed files with 65 additions and 24 deletions

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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));
}
}

View File

@ -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;