算法。地形生成 - 蒸发计算问题

Algo. terrain generation - evaporation calculation issue

创建程序地形我无法获得蒸发矩阵并找到我的算法错误的原因。我的程序如何工作:

块创建步骤:

生成地形时我使用以下常量:

private const chunkHeights = array( 'max' => 64, 'min' => -64 ); // min and max height
private const chunkSize = 129; // width = height for 1 chunk
private const chunkVariation = 1; // max variation from a position to its neighbor

Heightfield 脚本和我的 Rivers 脚本都按预期工作。我尝试更新给定块的蒸发文件:

    private static function updateEvaporation( $pChunkX, $pChunkY ) {
        $chunks = array();
        $seaOrRiver = 0;
        
        for( $y = ( $pChunkY - 1 ); $y <= ( $pChunkY + 1 ); $y++ ) {
            for( $x = ( $pChunkX - 1 ); $x <= ( $pChunkX + 1 ); $x++ ) {
                $chunkFolder = 'terrain/chunk'.$x.'x'.$y.'/';
                $tmpChunkFolder = 'terrain/tmp_chunk'.$x.'x'.$y.'/';
                
                $chunkHf = null;
                $chunkRivers = null;
                $chunkEvaporation = null;
                
                if( file_exists( $chunkFolder ) ) {
                    $chunkHf = new HeightField();
                    $chunkHfData = file_get_contents( $chunkFolder.'heightfield.json' );
                    $chunkHf->fromString( $chunkHfData );
                    
                    $chunkRivers = json_decode( file_get_contents( $chunkFolder.'rivers.json' ), true );
                    
                    $chunkEvaporation = json_decode( file_get_contents( $chunkFolder.'evaporation.json' ), true );
                } elseif( file_exists( $tmpChunkFolder ) ) {
                    $chunkHf = new HeightField();
                    $chunkHfData = file_get_contents( $tmpChunkFolder.'heightfield.json' );
                    $chunkHf->fromString( $chunkHfData );
                    
                    $chunkRivers = json_decode( file_get_contents( $tmpChunkFolder.'rivers.json' ), true );
                    
                    $chunkEvaporation = json_decode( file_get_contents( $tmpChunkFolder.'evaporation.json' ), true );
                }
                
                if( ( $chunkHf != null ) && ( $chunkRivers != null ) && ( $chunkEvaporation != null ) ) {
                    for( $chunkY = 0; $chunkY < self::chunkSize; $chunkY++ ) {
                        for( $chunkX = 0; $chunkX < self::chunkSize; $chunkX++ ) {
                            if( ( $chunkHf->getHeight( $chunkX, $chunkY ) <= 0 ) || ( $chunkRivers[$chunkY][$chunkX] == 1 ) ) {
                                $chunkEvaporation[$chunkY][$chunkX] = 0;
                                $seaOrRiver++;
                            } else {
                                $chunkEvaporation[$chunkY][$chunkX] = null;
                            }
                        }
                    }
                    
                    $chunks[$x.'x'.$y] = array(
                        'hf' => $chunkHf,
                        'rivers' => $chunkRivers,
                        'evaporation' => $chunkEvaporation
                    );
                }
            }
        }
        
        echo '<br>0 => ['.$seaOrRiver.']<br>';
        
        $eLevel = 0;
        
        while( $eLevel <= max( 0, self::chunkHeights['max'] ) ) {
            $byLevel = 0;
            
            for( $y = 0; $y < ( 3 * self::chunkSize ); $y++ ) {
                for( $x = 0; $x < ( 3 * self::chunkSize ); $x++ ) {
                    $chunkX = floor( $x / self::chunkSize ) + $pChunkX - 1;
                    $chunkY = floor( $y / self::chunkSize ) + $pChunkY - 1;
                    $chunkXx = $x % self::chunkSize;
                    $chunkYy = $y % self::chunkSize;
                    
                    if( isset( $chunks[$chunkX.'x'.$chunkY] ) ) {
                        if( $chunks[$chunkX.'x'.$chunkY]['evaporation'][$chunkYy][$chunkXx] == $eLevel ) {
                            for( $yy = ( $y - 1 ); $yy <= ( $y + 1 ); $yy++ ) {
                                for( $xx = ( $x - 1 ); $xx <= ( $x + 1 ); $xx++ ) {
                                    $chunkXX = floor( $xx / self::chunkSize ) + $pChunkX - 1;
                                    $chunkYY = floor( $yy / self::chunkSize ) + $pChunkY - 1;
                                    $chunkXXx = $xx % self::chunkSize;
                                    $chunkYYy = $yy % self::chunkSize;
                                    
                                    if( isset( $chunks[$chunkXX.'x'.$chunkYY]['evaporation'][$chunkYYy][$chunkXXx] ) ) {
                                        if( $chunks[$chunkXX.'x'.$chunkYY]['evaporation'][$chunkYYy][$chunkXXx] == null ) {
                                            $chunks[$chunkXX.'x'.$chunkYY]['evaporation'][$chunkYYy][$chunkXXx] = ( $eLevel + 1 );
                                            
                                            $byLevel++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            
            echo ( $eLevel + 1 ).' => ['.$byLevel.']<br>';
            $eLevel++;
        }
        
        if( file_exists( 'terrain/chunk'.$pChunkX.'x'.$pChunkY ) ) {
            file_put_contents( 'terrain/chunk'.$pChunkX.'x'.$pChunkY.'/evaporation.json', json_encode( $chunks[$pChunkX.'x'.$pChunkY]['evaporation'] ) );
        } else {
            file_put_contents( 'terrain/tmp_chunk'.$pChunkX.'x'.$pChunkY.'/evaporation.json', json_encode( $chunks[$pChunkX.'x'.$pChunkY]['evaporation'] ) );
        }
        
        return $chunks[$pChunkX.'x'.$pChunkY]['evaporation'];
    }

这里有一些解释:

这是第一个主循环。在此之后,我有一个 $chunks 列表,其中包含所有块的高度场、河流矩阵和不完整的蒸发矩阵(其中蒸发值为 0 或 null)。

我的第二个主循环:

加载 1 个块后的结果:

这里的白色部分是$pEvaporation[$y][$x] == null的位置,其余部分是从(rgb( 0, 0, 0 )rgb( 255, 0, 0 ))的蒸发率。仅生成海洋(和河流)(由于我生成和获取数据的顺序,河流不可见)。打印的文字对应<level I'm checking> => [<number of null neighbors found>].

其他矩阵预览:

你知道我的脚本出了什么问题吗?

我发现了我的错误:

PHP 考虑 0 == null0 !== null,我在我的脚本中更正了这个(用于蒸发测试)。