Experiment with biomes
This commit is contained in:
parent
cccd74f1a5
commit
007a9f7989
@ -18,15 +18,13 @@ class MapGenerator
|
|||||||
$this->noise = new Noise($seed);
|
$this->noise = new Noise($seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPixels(): array
|
public function getPixels(): iterable
|
||||||
{
|
{
|
||||||
$pixels = [];
|
|
||||||
for ($x = 0; $x < $this->width; $x++) {
|
for ($x = 0; $x < $this->width; $x++) {
|
||||||
for ($y = 0; $y < $this->height; $y++) {
|
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
|
private function drawPixel(int $x, int $y, Color $color): string
|
||||||
|
@ -6,18 +6,20 @@ use Ardent\Game\dto\Color;
|
|||||||
|
|
||||||
class Noise
|
class Noise
|
||||||
{
|
{
|
||||||
private readonly PerlinNoise $noise;
|
private readonly PerlinNoise $height;
|
||||||
|
private readonly PerlinNoise $biome;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
?int $seed = null,
|
?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);
|
$water = new Color(0, 156, 244);
|
||||||
$sand = new Color(238, 226, 104);
|
$sand = new Color(238, 226, 104);
|
||||||
$grass = new Color(25, 171, 64);
|
$grass = new Color(25, 171, 64);
|
||||||
@ -26,7 +28,7 @@ class Noise
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
[-1.0, $deepwater],
|
[-1.0, $deepwater],
|
||||||
[-0.9, $water],
|
[-0.997, $water],
|
||||||
[0.0, $sand],
|
[0.0, $sand],
|
||||||
[0.8, $grass],
|
[0.8, $grass],
|
||||||
[0.997, $mountain],
|
[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
|
public function generate(int $x, int $y): Color
|
||||||
{
|
{
|
||||||
$rand = $this->noise->random2D($x, $y, 150);
|
$height = $this->height->random2D($x, $y, 150);
|
||||||
$transitions = $this->getTransitions();
|
|
||||||
|
|
||||||
for ($i = 0; $i < count($transitions) - 1; $i++) {
|
// $biomes = [
|
||||||
$transition = $transitions[$i];
|
// [-1.0, $this->transitionTerrain($this->getGrassland(), $height)],
|
||||||
$nextTransition = $transitions[$i + 1];
|
// [1.01, $this->transitionTerrain($this->getDesert(), $height)],
|
||||||
if ($rand >= $transition[0] && $rand < $nextTransition[0]) {
|
// ];
|
||||||
return $this->lerpTerrain($transition[1], $nextTransition[1], $transition[0], $nextTransition[0], $rand);
|
// $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
|
public function lerpTerrain(Color $color1, Color $color2, float $begin, float $end, float $value): Color
|
||||||
{
|
{
|
||||||
return $color1->lerp($color2, ($value - $begin) * (1.0 / ($end - $begin)));
|
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;
|
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) {
|
if ($size === NULL) {
|
||||||
$size = $this->_default_size;
|
$size = $this->_default_size;
|
||||||
@ -167,7 +167,7 @@ class PerlinNoise
|
|||||||
|
|
||||||
// $value /= 2.0;
|
// $value /= 2.0;
|
||||||
|
|
||||||
return $this->sigmoid($value);
|
return $this->sigmoid($value * $multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sigmoid(float $t): float
|
private function sigmoid(float $t): float
|
||||||
|
@ -5,14 +5,14 @@ namespace Ardent\Game\dto;
|
|||||||
class Color
|
class Color
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private int|string $red,
|
private int|string $red,
|
||||||
private int $green = 0,
|
private int $green = 0,
|
||||||
private int $blue = 0,
|
private int $blue = 0,
|
||||||
private readonly int $alpha = 255
|
private readonly int $alpha = 255
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (is_string($red)) {
|
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,
|
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();
|
$renderer = new Renderer();
|
||||||
$map = new MapGenerator($renderer, $_GET['seed'], (int)$_GET['width'], (int)$_GET['height']);
|
$map = new MapGenerator($renderer, $_GET['seed'], (int)$_GET['width'], (int)$_GET['height']);
|
||||||
|
|
||||||
|
$start = microtime(true);
|
||||||
echo $renderer->render('map.html.twig', [
|
echo $renderer->render('map.html.twig', [
|
||||||
'map' => $map,
|
'map' => $map,
|
||||||
]);
|
]);
|
||||||
|
echo 'time: ' . microtime(true) - $start;
|
||||||
|
Loading…
Reference in New Issue
Block a user