From 007a9f7989c1116f3b7308943446cbb82fa73edc Mon Sep 17 00:00:00 2001 From: tim Date: Mon, 5 Jun 2023 02:54:54 +0200 Subject: [PATCH] Experiment with biomes --- src/MapGenerator.php | 6 ++--- src/Noise.php | 54 ++++++++++++++++++++++++++++++++------------ src/PerlinNoise.php | 4 ++-- src/dto/Color.php | 23 +++++++++++++++---- src/index.php | 2 ++ 5 files changed, 65 insertions(+), 24 deletions(-) diff --git a/src/MapGenerator.php b/src/MapGenerator.php index e67f97f..70a43ce 100644 --- a/src/MapGenerator.php +++ b/src/MapGenerator.php @@ -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 diff --git a/src/Noise.php b/src/Noise.php index c391314..d55e9cc 100644 --- a/src/Noise.php +++ b/src/Noise.php @@ -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; + } } \ No newline at end of file diff --git a/src/PerlinNoise.php b/src/PerlinNoise.php index 1e3fd06..5681f2b 100644 --- a/src/PerlinNoise.php +++ b/src/PerlinNoise.php @@ -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 diff --git a/src/dto/Color.php b/src/dto/Color.php index 6fb721f..87c0d61 100644 --- a/src/dto/Color.php +++ b/src/dto/Color.php @@ -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)); + } } \ No newline at end of file diff --git a/src/index.php b/src/index.php index 205d7b0..71cc3d7 100644 --- a/src/index.php +++ b/src/index.php @@ -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;