рдЧреЛрд▓рдВрдЧ + рдлреЗрд╕рд░ 3 = MMORPG - рд╣рдо рджреБрдирд┐рдпрд╛ рдХреА рдЕрдВрддрд╣реАрди рдкреАрдврд╝реА рдХреЗ рд▓рд┐рдП рдЖрдзрд╛рд░ рдмрдирд╛рддреЗ рд╣реИрдВ

рдЫрд╡рд┐

рд░реВрд╕реА-рднрд╛рд╖рд╛ рдХреЗ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдкрд░ рд╕рд╣реА рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдХрдард┐рди рд╣реИ, рд╢рд╛рдпрдж рдпрд╣ рд╕рд╛рдордЧреНрд░реА рдЖрдкрдХреЛ рдорд▓реНрдЯреА-рдкреНрд▓реЗрдпрд░ рдЧреЗрдо рдФрд░ рдЕрдзрд┐рдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдореВрд▓ рдмрд╛рддреЗрдВ рд╕рдордЭрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧреАред рдореИрдВ 2.5D MMORPG рдмрдирд╛рдиреЗ рдкрд░ рд▓реЗрдЦреЛрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдмрдирд╛рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВ, рдЕрд░реНрдерд╛рддреН, рдЗрд╕реЛрдореЗрдЯреНрд░реА рдореЗрдВ, рд╣рдорд╛рд░реА рджреБрдирд┐рдпрд╛ рдХреЛ рдкреНрд░рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдЪрдХреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╕рд░реНрд╡рд░ рдХреЛ рдЧреЛрд▓рдВрдЧ рднрд╛рд╖рд╛ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдореБрдЭреЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреВрд░реА рддрд░рд╣ рдЙрдкрдпреБрдХреНрдд рд▓рдЧрддрд╛ рд╣реИ, рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдлреНрд░реЗрдорд╡рд░реНрдХ рдореЗрдВ рдлреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛ - Phaser.js

рдПрдХ рд╡рд┐рд╢реНрд╡ рдкреАрдврд╝реА рдмрдирд╛рдПрдБ


рдФрд░ рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╣рдо рдЧреЛрд▓рдВрдЧ рдкрд░ IMO рдХреЗ рд▓рд┐рдП рдПрдХ рдЪрдВрдХ рдЬреЗрдирд░реЗрдЯрд░ рд▓рд┐рдЦреЗрдВрдЧреЗ, рдЕрдм рд╣рдо рдлреЗрдЬрд░ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рдкреНрд░рдХреНрд░рд┐рдпрд╛рддреНрдордХ рдкреАрдврд╝реА рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рд╢реЛрд░ рд╕рдорд╛рд░реЛрд╣ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд╣рдо рдкреЗрд░рд▓рд┐рди рд╢реЛрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ , рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдкрдврд╝реЗрдВ рдФрд░ рдЧреЛ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗрдВ рдпрд╛ рдореЗрд░рд╛ рд╕рдВрд╕реНрдХрд░рдг рд▓реЗрдВред

Perlin.go
package PerlinNoise

import (
	"math"
	"math/rand"
)

func Noise(x, y float32) float32 {
	//Coordinate left and top vertex square
	left := float32(math.Floor(float64(x)))
	top := float32(math.Floor(float64(y)))

	//Local coordinate
	localPoinX := x - left
	localPoiny := y - top

	topLeft := getRandomVector(left, top)
	topRight := getRandomVector(left+1, top)
	bottomLeft := getRandomVector(left, top+1)
	bottomRight := getRandomVector(left+1, top+1)
	//      
	DtopLeft := []float32{localPoinX, localPoiny}
	DtopRight := []float32{localPoinX - 1, localPoiny}
	DbottomLeft := []float32{localPoinX, localPoiny - 1}
	DbottomRight := []float32{localPoinX - 1, localPoiny - 1}

	// 
	tx1 := dot(DtopLeft, topLeft)
	tx2 := dot(DtopRight, topRight)
	bx1 := dot(DbottomLeft, bottomLeft)
	bx2 := dot(DbottomRight, bottomRight)

	//  
	pointX := curve(localPoinX)
	pointY := curve(localPoiny)

	//

	tx := lerp(tx1, tx2, pointX)
	bx := lerp(bx1, bx2, pointX)
	tb := lerp(tx, bx, pointY)
	return tb

}
func getRandomVector(x, y float32) []float32 {
	rand.Seed(int64(x * y))
	v := rand.Intn(3)

	switch v {

	case 0:
		return []float32{-1, 0}
	case 1:
		return []float32{1, 0}
	case 2:
		return []float32{0, 1}
	default:
		return []float32{0, -1}

	}
}
func dot(a []float32, b []float32) float32 {

	return (a[0]*b[0] + b[1]*a[1])
}
func lerp(a, b, c float32) float32 {

	return a*(1-c) + b*c

}
func curve(t float32) float32 {

	return (t * t * t * (t*(t*6-15) + 10))

}


рдЪрд▓реЛ рдПрдХ рдЫреЛрдЯреА рд╕реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдБ рд╣рдо рдЕрдкрдиреЗ рдХрд╛рд░реНрдп рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣рд╛рдБ рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рд╕рдВрд░рдЪрдирд╛ рд╣реИ:

рдЫрд╡рд┐

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛ рдореБрдЦреНрдп рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред

func main() {
	var a, b float32= 1330, 2500
	v:= PerlinNoise.Noise(a/2500, b/2500)
	fmt.Println(v)
}

рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рд╕реЗ рд╕рд╛рд╡рдзрд╛рди рд░рд╣реЗрдВ, рд╣рдореЗрд╢рд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкреНрд░рдХрд╛рд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ, рдпрд╣ рдЖрдкрдХреЛ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рд╕рдорд╕реНрдпрд╛рдУрдВ, рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рд╕реЗ рдмрдЪрд╛рдПрдЧрд╛:

-0.23416707

рдФрд░ рдЗрд╕рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдкрдиреА рджреБрдирд┐рдпрд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╢реЛрд░ рд╕рдорд╛рд░реЛрд╣ рд╣реИред рдЪрд▓рд┐рдП рдЪреБрдбрд┐рдпрд╛рдБ рдмрдирд╛рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рдореЗрдВ Chunk рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдФрд░ Chunk.go рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ рдФрд░ рдореБрдЦреНрдп рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЛ рддреБрд░рдВрдд рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:

var TILE_SIZE = 16
var CHUNK_SIZE = TILE_SIZE * TILE_SIZE
var PERLIN_SEED float32 = 150

TILE_SIZE рдкрд┐рдХреНрд╕реЗрд▓ рдореЗрдВ рд╣рдорд╛рд░реЗ рднрд╡рд┐рд╖реНрдп рдХреЗ рд╡рд┐рдЦрдВрдбреВ рдХрд╛ рд╕рдВрдХрд▓реНрдк рд╣реИ
CHUNK_SIZE, рдЪрдВрдХ рдХрд╛ рдЖрдХрд╛рд░ рд╣реИ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ 16 * 16
PERLIN_SEED - рдпрд╣рд╛рдВ рдЖрдк рдХреЛрдИ рднреА рд╕рдВрдЦреНрдпрд╛ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рддрдирд╛ рдЕрдзрд┐рдХ рд╣реЛрдЧрд╛, рдЙрддрдирд╛ рд╣реА рдЕрдзрд┐рдХ рд╢реЛрд░ рд╣реЛрдЧрд╛, рдЕрд░реНрдерд╛рддреНред рдпрджрд┐ рдЖрдк рдЫреЛрдЯреЗ рджреНрд╡реАрдк рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдХрдо рд░рдЦреЗрдВ, рдпрджрд┐ рд╡рд┐рд╢рд╛рд▓ рдорд╣рд╛рджреНрд╡реАрдк рдЕрдзрд┐рдХ рд╣реИрдВред

рдЕрдЧрд▓рд╛, рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдмрдирд╛рдПрдВ:

type Coordinate struct {
	X int 
	Y int 
}

рдпрд╣ рдкреНрд░рдХрд╛рд░ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛, рдФрд░ рдЕрдм рд╣рдо рдПрдХ рдФрд░ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрд╛рд░реНрдп рдмрдирд╛рдПрдВрдЧреЗ, рддрд╛рдХрд┐ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣рдо рдЕрдкрдиреЗ рдЖрдИрдбреА рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВрдЧреЗ:

func GetChunkID(x, y int) Coordinate {
	tileX := float64(float64(x) / float64(TILE_SIZE))
	tileY := float64(float64(y) / float64(TILE_SIZE))

	var ChunkID Coordinate
	if tileX < 0 {
		ChunkID.X = int(math.Floor(tileX / float64(TILE_SIZE)))
	} else {
		ChunkID.X = int(math.Ceil(tileX / float64(TILE_SIZE)))
	}
	if tileY < 0 {
		ChunkID.Y = int(math.Floor(tileY / float64(TILE_SIZE)))
	} else {
		ChunkID.Y = int(math.Ceil(tileY / float64(TILE_SIZE)))
	}
	if tileX == 0 {
		ChunkID.X = 1
	}
	if tileY == 0 {
		ChunkID.Y = 1
	}
	return ChunkID

}

рдЪрдВрдХ рдХреА рдЖрдИрдбреА рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ, рд╣рдо рд╕рд┐рд░реНрдл рдЯрд╛рдЗрд▓ рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдорд╛рдирдЪрд┐рддреНрд░ рдкрд░ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╣рдо рдкрд░рд┐рдгрд╛рдо рдХреЛ рд░рд╛рдЙрдВрдб рдХреЗ рд╕рд╛рде рдпрд╛ рдиреАрдЪреЗ рдЯрд╛рдЗрд▓ рдХреЗ рдЖрдХрд╛рд░ рд╕реЗ рдлрд┐рд░ рд╕реЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рдЪрдВрдХ рдХреА рдЖрдИрдбреА рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред рд╣рдорд╛рд░реА рджреБрдирд┐рдпрд╛ рдХрд┐рд╕реА рднреА рджрд┐рд╢рд╛ рдореЗрдВ рдЕрдВрддрд╣реАрди рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрдЧреАред

рдЕрдЧрд▓рд╛, рд╣рдорд╛рд░реЗ рдмрд┐рд▓реНрдбрд┐рдВрдЧ рдмреНрд▓реЙрдХ рдХреЛ рдЪрдВрдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛрдбрд╝реЗрдВ, рдпрд╣ рдЯрд╛рдЗрд▓ рдФрд░ рдЪрдВрдХ рд╣реИ:

type Chunk struct {
	ChunkID [2]int
	Map     map[Coordinate]Tile
}
type Tile struct {
	Key string
	X   int
	Y   int
}

рдЪрдВрдХ рдореЗрдВ рдПрдХ рдЯрд╛рдЗрд▓ рдХрд╛ рдирдХреНрд╢рд╛ рд╣реЛрддрд╛ рд╣реИред рдЯрд╛рдЗрд▓реЗрдВ рдЕрдкрдиреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдФрд░ рдХреБрдВрдЬреА рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреА рд╣реИрдВ (рдХреБрдВрдЬреА рдЖрдкрдХреЗ рд╢реАрд░реНрд╖рдХ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ: рднреВрдорд┐, рдкрд╛рдиреА, рдкрд░реНрд╡рдд, рдЖрджрд┐)

рдЕрдм рдЪрд▓реЛ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдЪрдВрдХ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рдХрд╛рд░реНрдп, рдореИрдВрдиреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕реЗ рдЕрдкрдирд╛ рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рд▓рд┐рдпрд╛ рдФрд░ рдЗрд╕реЗ рдЗрд╕ рд▓реЗрдЦ рд╕реЗ рдереЛрдбрд╝рд╛ рд╕рд╛ рднреБрдирд╛рдпрд╛:

рдлрдВрдХ рдиреНрдпреВрдХрдВрдХ ()
func NewChunk(idChunk Coordinate) Chunk {
	//    
	chunk := Chunk{ChunkID: [2]int{idChunk.X, idChunk.Y}}
	//   
	var chunkXMax, chunkYMax int
	//    
	var chunkMap map[Coordinate]Tile
	chunkMap = make(map[Coordinate]Tile)
	//     
	chunkXMax = idChunk.X * CHUNK_SIZE
	chunkYMax = idChunk.Y * CHUNK_SIZE
	switch {
	//      
	case chunkXMax < 0 && chunkYMax < 0:
		{
			for x := chunkXMax + CHUNK_SIZE; x > chunkXMax; x -= TILE_SIZE {
				for y := chunkYMax + CHUNK_SIZE; y > chunkYMax; y -= TILE_SIZE {
					//     
					posX := float32(x - (TILE_SIZE / 2))
					posY := float32(y + (TILE_SIZE / 2))
					tile := Tile{}

					tile.X = int(posX)
					tile.Y = int(posY)

					perlinValue := PerlinNoise.Noise(posX/PERLIN_SEED, posY/PERLIN_SEED)
					switch {
					case perlinValue < -0.01:
						tile.Key = "~" //
					case perlinValue >= -0.01 && perlinValue <= 0.5:
						tile.Key = "1" //

					case perlinValue > 0.5:
						tile.Key = "^" // 
					}
					chunkMap[Coordinate{X: tile.X, Y: tile.Y}] = tile

				}
			}
		}
		//  X 
	case chunkXMax < 0:
		{
			for x := chunkXMax + CHUNK_SIZE; x > chunkXMax; x -= TILE_SIZE {
				for y := chunkYMax - CHUNK_SIZE; y < chunkYMax; y += TILE_SIZE {
					posX := float32(x - (TILE_SIZE / 2))
					posY := float32(y + (TILE_SIZE / 2))

					tile := Tile{}

					tile.X = int(posX)
					tile.Y = int(posY)

					perlinValue := PerlinNoise.Noise(posX/PERLIN_SEED, posY/PERLIN_SEED)
					switch {
					case perlinValue < -0.12:
						tile.Key = "~"
					case perlinValue >= -0.12 && perlinValue <= 0.5:
						tile.Key = "1"

					case perlinValue > 0.5:
						tile.Key = "^"
					}

					chunkMap[Coordinate{X: tile.X, Y: tile.Y}] = tile

				}
			}
		}
		//  Y 
	case chunkYMax < 0:
		{
			for x := chunkXMax - CHUNK_SIZE; x < chunkXMax; x += TILE_SIZE {
				for y := chunkYMax + CHUNK_SIZE; y > chunkYMax; y -= TILE_SIZE {
					posX := float32(x + (TILE_SIZE / 2))
					posY := float32(y - (TILE_SIZE / 2))
					tile := Tile{}
					tile.X = int(posX)
					tile.Y = int(posY)
					perlinValue := PerlinNoise.Noise(posX/PERLIN_SEED, posY/PERLIN_SEED)
					switch {
					case perlinValue < -0.12:
						tile.Key = "~"
					case perlinValue >= -0.12 && perlinValue <= 0.5:
						tile.Key = "1"
					case perlinValue > 0.5:
						tile.Key = "^"
					}
					chunkMap[Coordinate{X: tile.X, Y: tile.Y}] = tile

				}
			}
		}
		//   
	default:
		{
			for x := chunkXMax - CHUNK_SIZE; x < chunkXMax; x += TILE_SIZE {
				for y := chunkYMax - CHUNK_SIZE; y < chunkYMax; y += TILE_SIZE {
					posX := float32(x + (TILE_SIZE / 2))
					posY := float32(y + (TILE_SIZE / 2))
					tile := Tile{}
					tile.X = int(posX)
					tile.Y = int(posY)
					perlinValue := PerlinNoise.Noise(posX/PERLIN_SEED, posY/PERLIN_SEED)
					switch {
					case perlinValue < -0.12:
						tile.Key = "~"
					case perlinValue >= -0.12 && perlinValue <= 0.5:
						tile.Key = "1"
					case perlinValue > 0.5:
						tile.Key = "^"
					}
					chunkMap[Coordinate{X: tile.X, Y: tile.Y}] = tile

				}
			}
		}

	}

	chunk.Map = chunkMap
	return chunk
}


рдФрд░ рдЗрд╕рд▓рд┐рдП, рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдпрд╛ рд╣рдорд╛рд░реЗ рдЪрдВрдХ рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рдЪрдВрдХ рдХреЗ рдЕрдзрд┐рдХрддрдо рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рд╣рдо рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдЖрдЧреЗ рдмрдврд╝реЗрдВрдЧреЗ, рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╕рд╛рде рдЯрд╛рдЗрд▓ рднрд░реЗрдВрдЧреЗред ChunkMax рдХреЛ рднреА рдХрд╛рдлреА рд╕рд░рд▓рддрд╛ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдЗрд╕рдХреЗ рдЖрдХрд╛рд░ (CHUNK_SIZE) рд╕реЗ рдЪрдВрдХ рдХреА рдЖрдИрдбреА рдХреЛ рдЧреБрдгрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рддреН ID {1; 1} рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░реЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ chunkXMax рдФрд░ chunkYaxax 256 рд╣реЛрдВрдЧреЗ

ред рдкреЙрдЬрд╝рдПрдХреНрд╕ / рдкреЙрдЬрд╝реА рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдЧреНрд░рд╛рдлрд┐рдХреНрд╕ рдХреЛ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:

					posX := float32(x + (TILE_SIZE / 2))
					posY := float32(y + (TILE_SIZE / 2))

рд╣рдо рдЕрдкрдиреЗ рдЪрдВрдХ рдХреА рдЖрдИрдбреА рдХреЗ рдореВрд▓реНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рддрд░реНрдХ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рд┐рдЪ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ (рд╕рдХрд╛рд░рд╛рддреНрдордХ рдФрд░ рдирдХрд╛рд░рд╛рддреНрдордХ рдорд╛рди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ)ред рдЯрд╛рдЗрд▓ рдХреА рдХреБрдВрдЬреА рдкреЗрд░реНрд▓рд┐рди рдХреЗ рд╢реЛрд░ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдЧреА, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдкрд░реНрд▓рд┐рди рдХрд╛ рд╢реЛрд░ 0 рд╕реЗ рдиреАрдЪреЗ рд╣реИ, рддреЛ рдпрд╣ рдкрд╛рдиреА рд╣реЛрдЧрд╛, рдКрдкрд░ рдпрд╣ рдЬрдореАрди рд╣реЛрдЧреАред рд╣рдо рдпрд╣ рдХрд░реЗрдВрдЧреЗ:

					case perlinValue < -0.12:
						tile.Key = "~" // 
					case perlinValue >= -0.12 && perlinValue <= 0.5:
						tile.Key = "1" // 
					case perlinValue > 0.5:
						tile.Key = "^" // 

рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╣рдорд╛рд░рд╛ рдлрд╝рдВрдХреНрд╢рди рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдХреЛрдб рдХреЛ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рд╕реЗ рдмрджрд▓реЗрдВ:

func main() {
	coord := Chunk.Coordinate{Y: 1, X: 1}
	chunk := Chunk.NewChunk(coord)
	m := chunk.Map
	out := os.Stdout
	for y := 8; y < 16*16; y += 16 {
		for x := 8; x < 16*16; x += 16 {
			c := Chunk.Coordinate{X: x, Y: y}
			out.Write([]byte(m[c].Key))

		}
		out.Write([]byte("\n"))
	}

}

рдирд┐рд╖реНрдХрд░реНрд╖:

11~~~11111111111
11~~~11111111111
11~~~~1111111111
11~~~~1111111111
11~~~~~111111111
11~~~~~~1111111~
11~~~~~~~~~11~~~
11~~~~~~~~~~~~~~
11~~~~~~~~~~~~~~
11~~~~~~~~~~~~~~
11~~~~~~~~~~~~~~
11~~~~~~~~~~~~~~
11~~~~~~~~~~~~~~
11~~~~~~~~~~~~~~
11~~~~~~~~~~1111
11~~~~~~~~~11111

рдпрд╣ рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИ, рдЖрдк рдЖрдЙрдЯрдкреБрдЯ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдЦреЗрд▓ рд╕рдХрддреЗ рд╣реИрдВ:

11111~~~~~~~~111111111111111111111111111111~~~~~~~11111111111111
11111~~~~~~~~111111111111111111111111111111~~~~~~~11111111111111
11111~~~~~~~~111111111111111111111111111111~~~~~~~11111111111111
11111~~~~~~~~111111111111111111111111111111~~~~~~~~1111111111111
11111~~~~~~~~11111111111111111111111111111~~~~~~~~~1111111111111
11111~~~~~~~~11111111111111111111111111111~~~~~~~~~1111111111111
11111~~~~~~~~~111111111111111111111111111~~~~~~~~~~~111111111111
11111~~~~~~~~~111111111111111111111111111~~~~~~~~~~~~11111111111
11111~~~~~~~~~~1111111111111111111111111~~~~~~~~~~~~~11111111111
11111~~~~~~~~~~~11111111111111111111111~~~~~~~~~~~~~~~1111111111
11111~~~~~~~~~~~1111111111111111111111~~~~~~~~~~~~~~~~~111111111
11111~~~~~~~~~~~~~11111111111111111111~~~~~~~~~~~~~~~~~111111111
11111~~~~~~~~~~~~~~111111111111111111~~~~~~~~~~~~~~~~~~~11111111
11111~~~~~~~~~~~~~~~~11111111111111~~~~~~~~~~~~~~~~~~~~~~1111111
11111~~~~~~~~~~~~~~~~~~11111111111~~~~~~~~~~~~~~~~~~~~~~~~111111
11111~~~~~~~~~~~~~~~~~~~~~111111~~~~~~~~~~~~~~~~~~~~~~~~~~~11111
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1111
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~111
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~11
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~~~1111111111~~~~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~~~111111111111111~~~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~~1111111111111111111~~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~~111111111111111111111~~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~~11111111111111111111111~~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~~1111111111111111111111111~~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~~111111111111111111111111111~~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~11111111111111111111111111111~~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~~111111111111111111111111111111~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~~1111111111111111111111111111111~~~~~~~~~~~
11111~~~~~~~~~~~~~~~~111111111111111111111111111111111~~~~~~~~~~
11111~~~~~~~~~~~~~~~~1111111111111111111111111111111111~~~~~~~~~
11111~~~~~~~~~~~~~~~~11111111111111111111111111111111111~~~~~~~~
11111~~~~~~~~~~~~~~~~11111111111111111111111111111111111~~~~~~~~
11111~~~~~~~~~~~~~~~~111111111111111111111111111111111111~~~~~~~
11111~~~~~~~~~~~~~~~~1111111111111111111111111111111111111~~~~~~
11111~~~~~~~~~~~~~~~~1111111111111111111111111111111111111~~~~~~
11111~~~~~~~~~~~~~~~~11111111111111111111111111111111111111~~~~~
11111~~~~~~~~~~~~~~~~11111111111111111111111111111111111111~~~~~
11111~~~~~~~~~~~~~~~~~11111111111111111111111111111111111111~~~~
11111~~~~~~~~~~~~~~~~~11111111111111111111111111111111111111~~~~
11111~~~~~~~~~~~~~~~~~~11111111111111111111111111111111111111~~~
1111~~~~~~~~~~~~~~~~~~~11111111111111111111111111111111111111~~~
1111~~~~~~~~~~~~~~~~~~~~1111111111111111111111111111111111111~~~
1111~~~~~~~~~~~~~~~~~~~~~111111111111111111111111111111111111~~~
1111~~~~~~~~~~~~~~~~~~~~~1111111111111111111111111111111111111~~
1111~~~~~~~~~~~~~~~~~~~~~~111111111111111111111111111111111111~~
1111~~~~~~~~~~~~~~~~~~~~~~~11111111111111111111111111111111111~~
1111~~~~~~~~~~~~~~~~~~~~~~~~1111111111111111111111111111111111~~
1111~~~~~~~~~~~~~~~~~~~~~~~~1111111111111111111111111111111111~~
1111~~~~~~~~~~~~~~~~~~~~~~~~~111111111111111111111111111111111~~

рдХреЛрдб:

Chunk.go
package Chunk

import (
	"PerlinNoise"
	"math"
)

var TILE_SIZE = 16
var CHUNK_SIZE = 32 * 32
var PERLIN_SEED float32 = 600

type Coordinate struct {
	X int `json:"x"`
	Y int `json:"y"`
}
type Chunk struct {
	ChunkID [2]int
	Map     map[Coordinate]Tile
}
type Tile struct {
	Key string
	X   int
	Y   int
}

func GetChunkID(x, y int) Coordinate {
	tileX := float64(x)
	tileY := float64(y)

	var ChunkID Coordinate
	if tileX < 0 {
		ChunkID.X = int(math.Floor(tileX / float64(TILE_SIZE)))
	} else {
		ChunkID.X = int(math.Ceil(tileX / float64(TILE_SIZE)))
	}
	if tileY < 0 {
		ChunkID.Y = int(math.Floor(tileY / float64(TILE_SIZE)))
	} else {
		ChunkID.Y = int(math.Ceil(tileY / float64(TILE_SIZE)))
	}
	if tileX == 0 {
		ChunkID.X = 1
	}
	if tileY == 0 {
		ChunkID.Y = 1
	}
	return ChunkID

}
func NewChunk(idChunk Coordinate) Chunk {
	//    
	chunk := Chunk{ChunkID: [2]int{idChunk.X, idChunk.Y}}
	//   
	var chunkXMax, chunkYMax int
	//    
	var chunkMap map[Coordinate]Tile
	chunkMap = make(map[Coordinate]Tile)
	//     
	chunkXMax = idChunk.X * CHUNK_SIZE
	chunkYMax = idChunk.Y * CHUNK_SIZE
	switch {
	//      
	case chunkXMax < 0 && chunkYMax < 0:
		{
			for x := chunkXMax + CHUNK_SIZE; x > chunkXMax; x -= TILE_SIZE {
				for y := chunkYMax + CHUNK_SIZE; y > chunkYMax; y -= TILE_SIZE {
					//     
					posX := float32(x - (TILE_SIZE / 2))
					posY := float32(y + (TILE_SIZE / 2))
					tile := Tile{}

					tile.X = int(posX)
					tile.Y = int(posY)

					perlinValue := PerlinNoise.Noise(posX/PERLIN_SEED, posY/PERLIN_SEED)
					switch {
					case perlinValue < -0.01:
						tile.Key = "~" //
					case perlinValue >= -0.01 && perlinValue <= 0.5:
						tile.Key = "1" //

					case perlinValue > 0.5:
						tile.Key = "^" // 
					}
					chunkMap[Coordinate{X: tile.X, Y: tile.Y}] = tile

				}
			}
		}
		//  X 
	case chunkXMax < 0:
		{
			for x := chunkXMax + CHUNK_SIZE; x > chunkXMax; x -= TILE_SIZE {
				for y := chunkYMax - CHUNK_SIZE; y < chunkYMax; y += TILE_SIZE {
					posX := float32(x - (TILE_SIZE / 2))
					posY := float32(y + (TILE_SIZE / 2))

					tile := Tile{}

					tile.X = int(posX)
					tile.Y = int(posY)

					perlinValue := PerlinNoise.Noise(posX/PERLIN_SEED, posY/PERLIN_SEED)
					switch {
					case perlinValue < -0.12:
						tile.Key = "~"
					case perlinValue >= -0.12 && perlinValue <= 0.5:
						tile.Key = "1"

					case perlinValue > 0.5:
						tile.Key = "^"
					}

					chunkMap[Coordinate{X: tile.X, Y: tile.Y}] = tile

				}
			}
		}
		//  Y 
	case chunkYMax < 0:
		{
			for x := chunkXMax - CHUNK_SIZE; x < chunkXMax; x += TILE_SIZE {
				for y := chunkYMax + CHUNK_SIZE; y > chunkYMax; y -= TILE_SIZE {
					posX := float32(x + (TILE_SIZE / 2))
					posY := float32(y - (TILE_SIZE / 2))
					tile := Tile{}
					tile.X = int(posX)
					tile.Y = int(posY)
					perlinValue := PerlinNoise.Noise(posX/PERLIN_SEED, posY/PERLIN_SEED)
					switch {
					case perlinValue < -0.12:
						tile.Key = "~"
					case perlinValue >= -0.12 && perlinValue <= 0.5:
						tile.Key = "1"
					case perlinValue > 0.5:
						tile.Key = "^"
					}
					chunkMap[Coordinate{X: tile.X, Y: tile.Y}] = tile

				}
			}
		}
		//   
	default:
		{
			for x := chunkXMax - CHUNK_SIZE; x < chunkXMax; x += TILE_SIZE {
				for y := chunkYMax - CHUNK_SIZE; y < chunkYMax; y += TILE_SIZE {
					posX := float32(x + (TILE_SIZE / 2))
					posY := float32(y + (TILE_SIZE / 2))
					tile := Tile{}
					tile.X = int(posX)
					tile.Y = int(posY)
					perlinValue := PerlinNoise.Noise(posX/PERLIN_SEED, posY/PERLIN_SEED)
					switch {
					case perlinValue < -0.12:
						tile.Key = "~"
					case perlinValue >= -0.12 && perlinValue <= 0.5:
						tile.Key = "1"
					case perlinValue > 0.5:
						tile.Key = "^"
					}
					chunkMap[Coordinate{X: tile.X, Y: tile.Y}] = tile

				}
			}
		}

	}

	chunk.Map = chunkMap
	return chunk
}


Perlin.go
package PerlinNoise

import (
	"math"
	"math/rand"
)

func Noise(x, y float32) float32 {
	//Coordinate left and top vertex square
	left := float32(math.Floor(float64(x)))
	top := float32(math.Floor(float64(y)))

	//Local coordinate
	localPoinX := x - left
	localPoiny := y - top

	topLeft := getRandomVector(left, top)
	topRight := getRandomVector(left+1, top)
	bottomLeft := getRandomVector(left, top+1)
	bottomRight := getRandomVector(left+1, top+1)
	//      
	DtopLeft := []float32{localPoinX, localPoiny}
	DtopRight := []float32{localPoinX - 1, localPoiny}
	DbottomLeft := []float32{localPoinX, localPoiny - 1}
	DbottomRight := []float32{localPoinX - 1, localPoiny - 1}

	// 
	tx1 := dot(DtopLeft, topLeft)
	tx2 := dot(DtopRight, topRight)
	bx1 := dot(DbottomLeft, bottomLeft)
	bx2 := dot(DbottomRight, bottomRight)

	//  
	pointX := curve(localPoinX)
	pointY := curve(localPoiny)

	//

	tx := lerp(tx1, tx2, pointX)
	bx := lerp(bx1, bx2, pointX)
	tb := lerp(tx, bx, pointY)
	return tb

}
func getRandomVector(x, y float32) []float32 {
	rand.Seed(int64(x * y))
	v := rand.Intn(3)

	switch v {

	case 0:
		return []float32{-1, 0}
	case 1:
		return []float32{1, 0}
	case 2:
		return []float32{0, 1}
	default:
		return []float32{0, -1}

	}
}
func dot(a []float32, b []float32) float32 {

	return (a[0]*b[0] + b[1]*a[1])
}
func lerp(a, b, c float32) float32 {

	return a*(1-c) + b*c

}
func curve(t float32) float32 {

	return (t * t * t * (t*(t*6-15) + 10))

}


main.go
package main

import (
	"fmt"
	"habr/Chunk"
	"os"
)

func main() {
	coord:= Chunk.GetChunkID(0,0)
	fmt.Println(coord)
	chunk := Chunk.NewChunk(coord)
	m := chunk.Map
	out := os.Stdout
	for y := 8; y < 32*32; y += 16 {
		for x := 8; x < 32*32; x += 16 {
			c := Chunk.Coordinate{X: x, Y: y}
			out.Write([]byte(m[c].Key))

		}
		out.Write([]byte("\n"))
	}

}


рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ , рд╣рдо HTTP рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдпрджрд┐ рд╣рдо рдЗрд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ WS рдХрдиреЗрдХреНрд╢рдиред рдЪрд▓рд┐рдП рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЧреЗрдо рдХрд╛рд░реНрдб рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рд░реЗрдВрдбрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП json рдлреЙрд░реНрдореЗрдЯ рдореЗрдВ рдХреНрд░рдордмрджреНрдз рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЖрдо рддреМрд░ рдкрд░ рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдЗрдВрдЯрд░реИрдХреНрдЯ рдХрд░рддреЗ рд╣реИрдВред

All Articles