First commit
This commit is contained in:
parent
664e6378ca
commit
498f3ddf8d
|
@ -0,0 +1,8 @@
|
|||
# Procedura 1D terrain generator
|
||||
|
||||
This is a demo of a 1D terrain generator using [Perlin noise](https://en.wikipedia.org/wiki/Perlin_noise) algorithm.
|
||||
Press *space* to generate a random terrain.
|
||||
|
||||
Uses [Go-Perlin](https://github.com/aquilax/go-perlin).
|
||||
|
||||
Texture by [hh316](https://hhh316.deviantart.com/art/Seamless-stone-cliff-face-mountain-texture-377076626).
|
|
@ -0,0 +1,106 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "image/jpeg"
|
||||
|
||||
perlin "github.com/aquilax/go-perlin"
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"github.com/svera/pixel/imdraw"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
const (
|
||||
width = 800
|
||||
height = 600
|
||||
// Top of the mountain must be around the half of the screen height
|
||||
verticalOffset = height / 2
|
||||
// Perlin noise provides variations in values between -1 and 1,
|
||||
// we multiply those so they're visible on screen
|
||||
scale = 100
|
||||
waveLength = 100
|
||||
alpha = 2.
|
||||
beta = 2.
|
||||
n = 3
|
||||
maximumSeedValue = 100
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
||||
|
||||
func run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Procedural terrain 1D",
|
||||
Bounds: pixel.R(0, 0, width, height),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pic, err := loadPicture("stone.jpg")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
imd := imdraw.New(pic)
|
||||
|
||||
drawTerrain(win, imd)
|
||||
|
||||
for !win.Closed() {
|
||||
if win.JustPressed(pixelgl.KeySpace) {
|
||||
drawTerrain(win, imd)
|
||||
}
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func loadPicture(path string) (pixel.Picture, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
img, _, err := image.Decode(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pixel.PictureDataFromImage(img), nil
|
||||
}
|
||||
|
||||
func drawTerrain(win *pixelgl.Window, imd *imdraw.IMDraw) {
|
||||
var seed = rand.Int63n(maximumSeedValue)
|
||||
p := perlin.NewPerlin(alpha, beta, n, seed)
|
||||
|
||||
imd.Clear()
|
||||
win.Clear(colornames.Skyblue)
|
||||
for x := 0.; x < width; x++ {
|
||||
y := p.Noise1D(x/waveLength)*scale + verticalOffset
|
||||
log.Printf("%f\n", y)
|
||||
renderTexturedLine(x, y, imd)
|
||||
}
|
||||
imd.Draw(win)
|
||||
}
|
||||
|
||||
// Render a textured line in position x with a height y.
|
||||
// Note that the textured line is just a 1 px width rectangle.
|
||||
// We push the opposite vertices of that rectangle and specify the points of the
|
||||
// texture we want to apply to them. Pixel will fill the rest of the rectangle interpolating the texture.
|
||||
func renderTexturedLine(x, y float64, imd *imdraw.IMDraw) {
|
||||
imd.Intensity = 1.
|
||||
imd.Picture = pixel.V(x, 0)
|
||||
imd.Push(pixel.V(x, 0))
|
||||
imd.Picture = pixel.V(x+1, y)
|
||||
imd.Push(pixel.V(x+1, y))
|
||||
imd.Rectangle(0)
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 368 KiB |
Loading…
Reference in New Issue