dep -> govendor
73
Gopkg.lock
generated
@@ -1,73 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/faiface/glhf"
|
||||
packages = ["."]
|
||||
revision = "98c0391c0fd3f0b365cfe5d467ac162b79dfb002"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/faiface/mainthread"
|
||||
packages = ["."]
|
||||
revision = "8b78f0a41ae388189090ac4506612659fa53082b"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/faiface/pixel"
|
||||
packages = [
|
||||
".",
|
||||
"imdraw",
|
||||
"pixelgl"
|
||||
]
|
||||
revision = "2d9a739e406f1f7093747c599d844e50c6e92d0e"
|
||||
version = "v0.7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-gl/gl"
|
||||
packages = ["v3.3-core/gl"]
|
||||
revision = "eafa86a81d9705ff0b4ab163d26fe74da80e0559"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-gl/glfw"
|
||||
packages = ["v3.2/glfw"]
|
||||
revision = "513e4f2bf85c31fba0fc4907abd7895242ccbe50"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-gl/mathgl"
|
||||
packages = ["mgl32"]
|
||||
revision = "d28d8d903c65929938eaac4953b3eb50a425b5ee"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/image"
|
||||
packages = [
|
||||
"colornames",
|
||||
"math/f32"
|
||||
]
|
||||
revision = "f3a9b89b59def9194717c1d0bd4c0d08fa1afa7b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"html",
|
||||
"html/atom"
|
||||
]
|
||||
revision = "24dd3780ca4f75fed9f321890729414a4b5d3f13"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "20e4628692bb0166d60606bd2f9e88c17bbd484bfe0e1fc0e3478c05a5d5f736"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
38
Gopkg.toml
@@ -1,38 +0,0 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/faiface/pixel"
|
||||
version = "0.7.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/image"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
@@ -35,8 +35,10 @@ They're not very interesting :D.
|
||||
Place your WH40K: Chaos Gate installation in `./orig` to benefit from automatic
|
||||
path defaults. Otherwise, point to it with `-game-path`
|
||||
|
||||
Dependency management uses `dep`. Unless you're contributing code you shouldn't
|
||||
have to worry about it.
|
||||
Dependency management uses `govendor`. Unless you're contributing code you
|
||||
shouldn't have to worry about it.
|
||||
|
||||
`dep` bug https://github.com/golang/dep/issues/1725 means I can't use it.
|
||||
|
||||
## Unmigrated text
|
||||
|
||||
|
BIN
vendor/github.com/faiface/glhf/examples/demo/celebrate.png
generated
vendored
Normal file
After Width: | Height: | Size: 82 KiB |
189
vendor/github.com/faiface/glhf/examples/demo/main.go
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/draw"
|
||||
_ "image/png"
|
||||
"os"
|
||||
|
||||
"github.com/faiface/glhf"
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/go-gl/glfw/v3.1/glfw"
|
||||
)
|
||||
|
||||
func loadImage(path string) (*image.NRGBA, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
img, _, err := image.Decode(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bounds := img.Bounds()
|
||||
nrgba := image.NewNRGBA(image.Rect(0, 0, bounds.Dx(), bounds.Dy()))
|
||||
draw.Draw(nrgba, nrgba.Bounds(), img, bounds.Min, draw.Src)
|
||||
return nrgba, nil
|
||||
}
|
||||
|
||||
func run() {
|
||||
var win *glfw.Window
|
||||
|
||||
defer func() {
|
||||
mainthread.Call(func() {
|
||||
glfw.Terminate()
|
||||
})
|
||||
}()
|
||||
|
||||
mainthread.Call(func() {
|
||||
glfw.Init()
|
||||
|
||||
glfw.WindowHint(glfw.ContextVersionMajor, 3)
|
||||
glfw.WindowHint(glfw.ContextVersionMinor, 3)
|
||||
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
|
||||
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
|
||||
glfw.WindowHint(glfw.Resizable, glfw.False)
|
||||
|
||||
var err error
|
||||
|
||||
win, err = glfw.CreateWindow(560, 697, "GLHF Rocks!", nil, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
win.MakeContextCurrent()
|
||||
|
||||
glhf.Init()
|
||||
})
|
||||
|
||||
var (
|
||||
// Here we define a vertex format of our vertex slice. It's actually a basic slice
|
||||
// literal.
|
||||
//
|
||||
// The vertex format consists of names and types of the attributes. The name is the
|
||||
// name that the attribute is referenced by inside a shader.
|
||||
vertexFormat = glhf.AttrFormat{
|
||||
{Name: "position", Type: glhf.Vec2},
|
||||
{Name: "texture", Type: glhf.Vec2},
|
||||
}
|
||||
|
||||
// Here we declare some variables for later use.
|
||||
shader *glhf.Shader
|
||||
texture *glhf.Texture
|
||||
slice *glhf.VertexSlice
|
||||
)
|
||||
|
||||
// Here we load an image from a file. The loadImage function is not within the library, it
|
||||
// just loads and returns a image.NRGBA.
|
||||
gopherImage, err := loadImage("celebrate.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Every OpenGL call needs to be done inside the main thread.
|
||||
mainthread.Call(func() {
|
||||
var err error
|
||||
|
||||
// Here we create a shader. The second argument is the format of the uniform
|
||||
// attributes. Since our shader has no uniform attributes, the format is empty.
|
||||
shader, err = glhf.NewShader(vertexFormat, glhf.AttrFormat{}, vertexShader, fragmentShader)
|
||||
|
||||
// If the shader compilation did not go successfully, an error with a full
|
||||
// description is returned.
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// We create a texture from the loaded image.
|
||||
texture = glhf.NewTexture(
|
||||
gopherImage.Bounds().Dx(),
|
||||
gopherImage.Bounds().Dy(),
|
||||
true,
|
||||
gopherImage.Pix,
|
||||
)
|
||||
|
||||
// And finally, we make a vertex slice, which is basically a dynamically sized
|
||||
// vertex array. The length of the slice is 6 and the capacity is the same.
|
||||
//
|
||||
// The slice inherits the vertex format of the supplied shader. Also, it should
|
||||
// only be used with that shader.
|
||||
slice = glhf.MakeVertexSlice(shader, 6, 6)
|
||||
|
||||
// Before we use a slice, we need to Begin it. The same holds for all objects in
|
||||
// GLHF.
|
||||
slice.Begin()
|
||||
|
||||
// We assign data to the vertex slice. The values are in the order as in the vertex
|
||||
// format of the slice (shader). Each two floats correspond to an attribute of type
|
||||
// glhf.Vec2.
|
||||
slice.SetVertexData([]float32{
|
||||
-1, -1, 0, 1,
|
||||
+1, -1, 1, 1,
|
||||
+1, +1, 1, 0,
|
||||
|
||||
-1, -1, 0, 1,
|
||||
+1, +1, 1, 0,
|
||||
-1, +1, 0, 0,
|
||||
})
|
||||
|
||||
// When we're done with the slice, we End it.
|
||||
slice.End()
|
||||
})
|
||||
|
||||
shouldQuit := false
|
||||
for !shouldQuit {
|
||||
mainthread.Call(func() {
|
||||
if win.ShouldClose() {
|
||||
shouldQuit = true
|
||||
}
|
||||
|
||||
// Clear the window.
|
||||
glhf.Clear(1, 1, 1, 1)
|
||||
|
||||
// Here we Begin/End all necessary objects and finally draw the vertex
|
||||
// slice.
|
||||
shader.Begin()
|
||||
texture.Begin()
|
||||
slice.Begin()
|
||||
slice.Draw()
|
||||
slice.End()
|
||||
texture.End()
|
||||
shader.End()
|
||||
|
||||
win.SwapBuffers()
|
||||
glfw.PollEvents()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
mainthread.Run(run)
|
||||
}
|
||||
|
||||
var vertexShader = `
|
||||
#version 330 core
|
||||
|
||||
in vec2 position;
|
||||
in vec2 texture;
|
||||
|
||||
out vec2 Texture;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
Texture = texture;
|
||||
}
|
||||
`
|
||||
|
||||
var fragmentShader = `
|
||||
#version 330 core
|
||||
|
||||
in vec2 Texture;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
void main() {
|
||||
color = texture(tex, Texture);
|
||||
}
|
||||
`
|
16
vendor/github.com/faiface/pixel/examples/community/bouncing/README.md
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# bouncing
|
||||
|
||||
Bouncing particles using the [imdraw](https://godoc.org/github.com/faiface/pixel/imdraw) package.
|
||||
|
||||
Made by [Peter Hellberg](https://github.com/peterhellberg/) as part of his [pixel-experiments](https://github.com/peterhellberg/pixel-experiments)
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Links
|
||||
|
||||
- https://github.com/peterhellberg/pixel-experiments/tree/master/bouncing
|
||||
- https://gist.github.com/peterhellberg/674f32a15a7d2d249e634ce781f333e8
|
303
vendor/github.com/faiface/pixel/examples/community/bouncing/bouncing.go
generated
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
)
|
||||
|
||||
var (
|
||||
w, h, s, scale = float64(640), float64(360), float64(2.3), float64(32)
|
||||
|
||||
p, bg = newPalette(Colors), color.RGBA{32, p.color().G, 32, 255}
|
||||
|
||||
balls = []*ball{
|
||||
newRandomBall(scale),
|
||||
newRandomBall(scale),
|
||||
}
|
||||
)
|
||||
|
||||
func run() {
|
||||
win, err := pixelgl.NewWindow(pixelgl.WindowConfig{
|
||||
Bounds: pixel.R(0, 0, w, h),
|
||||
VSync: true,
|
||||
Undecorated: true,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
imd := imdraw.New(nil)
|
||||
|
||||
imd.EndShape = imdraw.RoundEndShape
|
||||
imd.Precision = 3
|
||||
|
||||
go func() {
|
||||
start := time.Now()
|
||||
|
||||
for range time.Tick(16 * time.Millisecond) {
|
||||
bg = color.RGBA{32 + (p.color().R/128)*4, 32 + (p.color().G/128)*4, 32 + (p.color().B/128)*4, 255}
|
||||
s = pixel.V(math.Sin(time.Since(start).Seconds())*0.8, 0).Len()*2 - 1
|
||||
scale = 64 + 15*s
|
||||
imd.Intensity = 1.2 * s
|
||||
}
|
||||
}()
|
||||
|
||||
for !win.Closed() {
|
||||
win.SetClosed(win.JustPressed(pixelgl.KeyEscape) || win.JustPressed(pixelgl.KeyQ))
|
||||
|
||||
if win.JustPressed(pixelgl.KeySpace) {
|
||||
for _, ball := range balls {
|
||||
ball.color = ball.palette.next()
|
||||
}
|
||||
}
|
||||
|
||||
if win.JustPressed(pixelgl.KeyEnter) {
|
||||
for _, ball := range balls {
|
||||
ball.pos = center()
|
||||
ball.vel = randomVelocity()
|
||||
}
|
||||
}
|
||||
|
||||
imd.Clear()
|
||||
|
||||
for _, ball := range balls {
|
||||
imd.Color = ball.color
|
||||
imd.Push(ball.pos)
|
||||
}
|
||||
|
||||
imd.Polygon(scale)
|
||||
|
||||
for _, ball := range balls {
|
||||
imd.Color = color.RGBA{ball.color.R, ball.color.G, ball.color.B, 128 - uint8(128*s)}
|
||||
imd.Push(ball.pos)
|
||||
}
|
||||
|
||||
imd.Polygon(scale * s)
|
||||
|
||||
for _, ball := range balls {
|
||||
aliveParticles := []*particle{}
|
||||
|
||||
for _, particle := range ball.particles {
|
||||
if particle.life > 0 {
|
||||
aliveParticles = append(aliveParticles, particle)
|
||||
}
|
||||
}
|
||||
|
||||
for _, particle := range aliveParticles {
|
||||
imd.Color = particle.color
|
||||
imd.Push(particle.pos)
|
||||
imd.Circle(16*particle.life, 0)
|
||||
}
|
||||
}
|
||||
|
||||
win.Clear(bg)
|
||||
imd.Draw(win)
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(4)
|
||||
|
||||
go func() {
|
||||
for range time.Tick(32 * time.Millisecond) {
|
||||
for _, ball := range balls {
|
||||
go ball.update()
|
||||
|
||||
for _, particle := range ball.particles {
|
||||
go particle.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
pixelgl.Run(run)
|
||||
}
|
||||
|
||||
func newParticleAt(pos, vel pixel.Vec) *particle {
|
||||
c := p.color()
|
||||
c.A = 5
|
||||
|
||||
return &particle{pos, vel, c, rand.Float64() * 1.5}
|
||||
}
|
||||
|
||||
func newRandomBall(radius float64) *ball {
|
||||
return &ball{
|
||||
center(), randomVelocity(),
|
||||
math.Pi * (radius * radius),
|
||||
radius, p.random(), p, []*particle{},
|
||||
}
|
||||
}
|
||||
|
||||
func center() pixel.Vec {
|
||||
return pixel.V(w/2, h/2)
|
||||
}
|
||||
|
||||
func randomVelocity() pixel.Vec {
|
||||
return pixel.V((rand.Float64()*2)-1, (rand.Float64()*2)-1).Scaled(scale / 4)
|
||||
}
|
||||
|
||||
type particle struct {
|
||||
pos pixel.Vec
|
||||
vel pixel.Vec
|
||||
color color.RGBA
|
||||
life float64
|
||||
}
|
||||
|
||||
func (p *particle) update() {
|
||||
p.pos = p.pos.Add(p.vel)
|
||||
p.life -= 0.03
|
||||
|
||||
switch {
|
||||
case p.pos.Y < 0 || p.pos.Y >= h:
|
||||
p.vel.Y *= -1.0
|
||||
case p.pos.X < 0 || p.pos.X >= w:
|
||||
p.vel.X *= -1.0
|
||||
}
|
||||
}
|
||||
|
||||
type ball struct {
|
||||
pos pixel.Vec
|
||||
vel pixel.Vec
|
||||
mass float64
|
||||
radius float64
|
||||
color color.RGBA
|
||||
palette *Palette
|
||||
particles []*particle
|
||||
}
|
||||
|
||||
func (b *ball) update() {
|
||||
b.pos = b.pos.Add(b.vel)
|
||||
|
||||
var bounced bool
|
||||
|
||||
switch {
|
||||
case b.pos.Y <= b.radius || b.pos.Y >= h-b.radius:
|
||||
b.vel.Y *= -1.0
|
||||
bounced = true
|
||||
|
||||
if b.pos.Y < b.radius {
|
||||
b.pos.Y = b.radius
|
||||
} else {
|
||||
b.pos.Y = h - b.radius
|
||||
}
|
||||
case b.pos.X <= b.radius || b.pos.X >= w-b.radius:
|
||||
b.vel.X *= -1.0
|
||||
bounced = true
|
||||
|
||||
if b.pos.X < b.radius {
|
||||
b.pos.X = b.radius
|
||||
} else {
|
||||
b.pos.X = w - b.radius
|
||||
}
|
||||
}
|
||||
|
||||
for _, a := range balls {
|
||||
if a != b {
|
||||
d := a.pos.Sub(b.pos)
|
||||
|
||||
if d.Len() > a.radius+b.radius {
|
||||
continue
|
||||
}
|
||||
|
||||
pen := d.Unit().Scaled(a.radius + b.radius - d.Len())
|
||||
|
||||
a.pos = a.pos.Add(pen.Scaled(b.mass / (a.mass + b.mass)))
|
||||
b.pos = b.pos.Sub(pen.Scaled(a.mass / (a.mass + b.mass)))
|
||||
|
||||
u := d.Unit()
|
||||
v := 2 * (a.vel.Dot(u) - b.vel.Dot(u)) / (a.mass + b.mass)
|
||||
|
||||
a.vel = a.vel.Sub(u.Scaled(v * b.mass))
|
||||
b.vel = b.vel.Add(u.Scaled(v * a.mass))
|
||||
|
||||
bounced = true
|
||||
}
|
||||
}
|
||||
|
||||
if bounced {
|
||||
b.color = p.next()
|
||||
b.particles = append(b.particles,
|
||||
newParticleAt(b.pos, b.vel.Rotated(1).Scaled(rand.Float64())),
|
||||
newParticleAt(b.pos, b.vel.Rotated(2).Scaled(rand.Float64())),
|
||||
newParticleAt(b.pos, b.vel.Rotated(3).Scaled(rand.Float64())),
|
||||
newParticleAt(b.pos, b.vel.Rotated(4).Scaled(rand.Float64())),
|
||||
newParticleAt(b.pos, b.vel.Rotated(5).Scaled(rand.Float64())),
|
||||
newParticleAt(b.pos, b.vel.Rotated(6).Scaled(rand.Float64())),
|
||||
newParticleAt(b.pos, b.vel.Rotated(7).Scaled(rand.Float64())),
|
||||
newParticleAt(b.pos, b.vel.Rotated(8).Scaled(rand.Float64())),
|
||||
newParticleAt(b.pos, b.vel.Rotated(9).Scaled(rand.Float64())),
|
||||
|
||||
newParticleAt(b.pos, b.vel.Rotated(10).Scaled(rand.Float64()+1)),
|
||||
newParticleAt(b.pos, b.vel.Rotated(20).Scaled(rand.Float64()+1)),
|
||||
newParticleAt(b.pos, b.vel.Rotated(30).Scaled(rand.Float64()+1)),
|
||||
newParticleAt(b.pos, b.vel.Rotated(40).Scaled(rand.Float64()+1)),
|
||||
newParticleAt(b.pos, b.vel.Rotated(50).Scaled(rand.Float64()+1)),
|
||||
newParticleAt(b.pos, b.vel.Rotated(60).Scaled(rand.Float64()+1)),
|
||||
newParticleAt(b.pos, b.vel.Rotated(70).Scaled(rand.Float64()+1)),
|
||||
newParticleAt(b.pos, b.vel.Rotated(80).Scaled(rand.Float64()+1)),
|
||||
newParticleAt(b.pos, b.vel.Rotated(90).Scaled(rand.Float64()+1)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func newPalette(cc []color.Color) *Palette {
|
||||
colors := []color.RGBA{}
|
||||
|
||||
for _, v := range cc {
|
||||
if c, ok := v.(color.RGBA); ok {
|
||||
colors = append(colors, c)
|
||||
}
|
||||
}
|
||||
|
||||
return &Palette{colors, len(colors), 0}
|
||||
}
|
||||
|
||||
type Palette struct {
|
||||
colors []color.RGBA
|
||||
size int
|
||||
index int
|
||||
}
|
||||
|
||||
func (p *Palette) clone() *Palette {
|
||||
return &Palette{p.colors, p.size, p.index}
|
||||
}
|
||||
|
||||
func (p *Palette) next() color.RGBA {
|
||||
if p.index++; p.index >= p.size {
|
||||
p.index = 0
|
||||
}
|
||||
|
||||
return p.colors[p.index]
|
||||
}
|
||||
|
||||
func (p *Palette) color() color.RGBA {
|
||||
return p.colors[p.index]
|
||||
}
|
||||
|
||||
func (p *Palette) random() color.RGBA {
|
||||
p.index = rand.Intn(p.size)
|
||||
|
||||
return p.colors[p.index]
|
||||
}
|
||||
|
||||
var Colors = []color.Color{
|
||||
color.RGBA{190, 38, 51, 255},
|
||||
color.RGBA{224, 111, 139, 255},
|
||||
color.RGBA{73, 60, 43, 255},
|
||||
color.RGBA{164, 100, 34, 255},
|
||||
color.RGBA{235, 137, 49, 255},
|
||||
color.RGBA{247, 226, 107, 255},
|
||||
color.RGBA{47, 72, 78, 255},
|
||||
color.RGBA{68, 137, 26, 255},
|
||||
color.RGBA{163, 206, 39, 255},
|
||||
color.RGBA{0, 87, 132, 255},
|
||||
color.RGBA{49, 162, 242, 255},
|
||||
color.RGBA{178, 220, 239, 255},
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/community/bouncing/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 6.9 KiB |
20
vendor/github.com/faiface/pixel/examples/community/game_of_life/README.md
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# Conway's Game of Lfe
|
||||
|
||||
Created by [Nathan Leniz](https://github.com/terakilobyte).
|
||||
Inspired by and heavily uses [the doc](https://golang.org/doc/play/life.go)
|
||||
|
||||
> The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970. The "game" is a zero-player game, meaning that its evolution is determined by its initial state, requiring no further input. One interacts with the Game of Life by creating an initial configuration and observing how it evolves, or, for advanced "players", by creating patterns with particular properties. The Game has been reprogrammed multiple times in various coding languages.
|
||||
|
||||
For more information, please see the [wikipedia](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) article.
|
||||
|
||||
## Use
|
||||
|
||||
go run main.go -h
|
||||
-frameRate duration
|
||||
The framerate in milliseconds (default 33ms)
|
||||
-size int
|
||||
The size of each cell (default 5)
|
||||
-windowSize float
|
||||
The pixel size of one side of the grid (default 800)
|
||||
|
||||

|
BIN
vendor/github.com/faiface/pixel/examples/community/game_of_life/life.png
generated
vendored
Normal file
After Width: | Height: | Size: 86 KiB |
74
vendor/github.com/faiface/pixel/examples/community/game_of_life/life/grid.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package life
|
||||
|
||||
import (
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
// Shamelessly taken/inspired by https://golang.org/doc/play/life.go
|
||||
// Grid is the structure in which the cellular automota live
|
||||
type Grid struct {
|
||||
h int
|
||||
cellSize int
|
||||
Cells [][]bool
|
||||
}
|
||||
|
||||
// NewGrid constructs a new Grid
|
||||
func NewGrid(h, size int) *Grid {
|
||||
cells := make([][]bool, h)
|
||||
for i := 0; i < h; i++ {
|
||||
cells[i] = make([]bool, h)
|
||||
}
|
||||
return &Grid{h: h, cellSize: size, Cells: cells}
|
||||
}
|
||||
|
||||
// Alive returns whether the specified position is alive
|
||||
func (g *Grid) Alive(x, y int) bool {
|
||||
x += g.h
|
||||
x %= g.h
|
||||
y += g.h
|
||||
y %= g.h
|
||||
return g.Cells[y][x]
|
||||
}
|
||||
|
||||
// Set sets the state of a specific location
|
||||
func (g *Grid) Set(x, y int, state bool) {
|
||||
g.Cells[y][x] = state
|
||||
}
|
||||
|
||||
// Draw draws the grid
|
||||
func (g *Grid) Draw(imd *imdraw.IMDraw) {
|
||||
for i := 0; i < g.h; i++ {
|
||||
for j := 0; j < g.h; j++ {
|
||||
if g.Alive(i, j) {
|
||||
imd.Color = colornames.Black
|
||||
} else {
|
||||
imd.Color = colornames.White
|
||||
}
|
||||
imd.Push(
|
||||
pixel.V(float64(i*g.cellSize), float64(j*g.cellSize)),
|
||||
pixel.V(float64(i*g.cellSize+g.cellSize), float64(j*g.cellSize+g.cellSize)),
|
||||
)
|
||||
imd.Rectangle(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next returns the next state
|
||||
func (g *Grid) Next(x, y int) bool {
|
||||
// Count the adjacent cells that are alive.
|
||||
alive := 0
|
||||
for i := -1; i <= 1; i++ {
|
||||
for j := -1; j <= 1; j++ {
|
||||
if (j != 0 || i != 0) && g.Alive(x+i, y+j) {
|
||||
alive++
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return next state according to the game rules:
|
||||
// exactly 3 neighbors: on,
|
||||
// exactly 2 neighbors: maintain current state,
|
||||
// otherwise: off.
|
||||
return alive == 3 || alive == 2 && g.Alive(x, y)
|
||||
}
|
35
vendor/github.com/faiface/pixel/examples/community/game_of_life/life/life.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Package life manages the "game" state
|
||||
// Shamelessly taken from https://golang.org/doc/play/life.go
|
||||
package life
|
||||
|
||||
import "math/rand"
|
||||
|
||||
// Life stores the state of a round of Conway's Game of Life.
|
||||
type Life struct {
|
||||
A, b *Grid
|
||||
h int
|
||||
}
|
||||
|
||||
// NewLife returns a new Life game state with a random initial state.
|
||||
func NewLife(h, size int) *Life {
|
||||
a := NewGrid(h, size)
|
||||
for i := 0; i < (h * h / 2); i++ {
|
||||
a.Set(rand.Intn(h), rand.Intn(h), true)
|
||||
}
|
||||
return &Life{
|
||||
A: a, b: NewGrid(h, size),
|
||||
h: h,
|
||||
}
|
||||
}
|
||||
|
||||
// Step advances the game by one instant, recomputing and updating all cells.
|
||||
func (l *Life) Step() {
|
||||
// Update the state of the next field (b) from the current field (a).
|
||||
for y := 0; y < l.h; y++ {
|
||||
for x := 0; x < l.h; x++ {
|
||||
l.b.Set(x, y, l.A.Next(x, y))
|
||||
}
|
||||
}
|
||||
// Swap fields a and b.
|
||||
l.A, l.b = l.b, l.A
|
||||
}
|
64
vendor/github.com/faiface/pixel/examples/community/game_of_life/main.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"golang.org/x/image/colornames"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/examples/community/game_of_life/life"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
)
|
||||
|
||||
var (
|
||||
size *int
|
||||
windowSize *float64
|
||||
frameRate *time.Duration
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
size = flag.Int("size", 5, "The size of each cell")
|
||||
windowSize = flag.Float64("windowSize", 800, "The pixel size of one side of the grid")
|
||||
frameRate = flag.Duration("frameRate", 33*time.Millisecond, "The framerate in milliseconds")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
||||
|
||||
func run() {
|
||||
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks!",
|
||||
Bounds: pixel.R(0, 0, *windowSize, *windowSize),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
win.Clear(colornames.White)
|
||||
|
||||
// since the game board is square, rows and cols will be the same
|
||||
rows := int(*windowSize) / *size
|
||||
|
||||
gridDraw := imdraw.New(nil)
|
||||
game := life.NewLife(rows, *size)
|
||||
tick := time.Tick(*frameRate)
|
||||
for !win.Closed() {
|
||||
// game loop
|
||||
select {
|
||||
case <-tick:
|
||||
gridDraw.Clear()
|
||||
game.A.Draw(gridDraw)
|
||||
gridDraw.Draw(win)
|
||||
game.Step()
|
||||
}
|
||||
win.Update()
|
||||
}
|
||||
}
|
13
vendor/github.com/faiface/pixel/examples/community/isometric-basics/README.md
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Isometric view basics
|
||||
|
||||
Created by [Sergio Vera](https://github.com/svera).
|
||||
|
||||
Isometric view is a display method used to create an illusion of 3D for an otherwise 2D game - sometimes referred to as pseudo 3D or 2.5D.
|
||||
|
||||
Implementing an isometric view can be done in many ways, but for the sake of simplicity we'll implement a tile-based approach, which is the most efficient and widely used method.
|
||||
|
||||
In the tile-based approach, each visual element is broken down into smaller pieces, called tiles, of a standard size. These tiles will be arranged to form the game world according to pre-determined level data - usually a 2D array.
|
||||
|
||||
For a detailed explanation about the maths behind this, read [http://clintbellanger.net/articles/isometric_math/](http://clintbellanger.net/articles/isometric_math/).
|
||||
|
||||

|
BIN
vendor/github.com/faiface/pixel/examples/community/isometric-basics/castle.png
generated
vendored
Normal file
After Width: | Height: | Size: 26 KiB |
102
vendor/github.com/faiface/pixel/examples/community/isometric-basics/main.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"os"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
|
||||
_ "image/png"
|
||||
)
|
||||
|
||||
const (
|
||||
windowWidth = 800
|
||||
windowHeight = 800
|
||||
// sprite tiles are squared, 64x64 size
|
||||
tileSize = 64
|
||||
f = 0 // floor identifier
|
||||
w = 1 // wall identifier
|
||||
)
|
||||
|
||||
var levelData = [][]uint{
|
||||
{f, f, f, f, f, f}, // This row will be rendered in the lower left part of the screen (closer to the viewer)
|
||||
{w, f, f, f, f, w},
|
||||
{w, f, f, f, f, w},
|
||||
{w, f, f, f, f, w},
|
||||
{w, f, f, f, f, w},
|
||||
{w, w, w, w, w, w}, // And this in the upper right
|
||||
}
|
||||
var win *pixelgl.Window
|
||||
var offset = pixel.V(400, 325)
|
||||
var floorTile, wallTile *pixel.Sprite
|
||||
|
||||
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 run() {
|
||||
var err error
|
||||
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Isometric demo",
|
||||
Bounds: pixel.R(0, 0, windowWidth, windowHeight),
|
||||
VSync: true,
|
||||
}
|
||||
win, err = pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pic, err := loadPicture("castle.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
wallTile = pixel.NewSprite(pic, pixel.R(0, 448, tileSize, 512))
|
||||
floorTile = pixel.NewSprite(pic, pixel.R(0, 128, tileSize, 192))
|
||||
|
||||
depthSort()
|
||||
|
||||
for !win.Closed() {
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
// Draw level data tiles to window, from farthest to closest.
|
||||
// In order to achieve the depth effect, we need to render tiles up to down, being lower
|
||||
// closer to the viewer (see painter's algorithm). To do that, we need to process levelData in reverse order,
|
||||
// so its first row is rendered last, as OpenGL considers its origin to be in the lower left corner of the display.
|
||||
func depthSort() {
|
||||
for x := len(levelData) - 1; x >= 0; x-- {
|
||||
for y := len(levelData[x]) - 1; y >= 0; y-- {
|
||||
isoCoords := cartesianToIso(pixel.V(float64(x), float64(y)))
|
||||
mat := pixel.IM.Moved(offset.Add(isoCoords))
|
||||
// Not really needed, just put to show bigger blocks
|
||||
mat = mat.ScaledXY(win.Bounds().Center(), pixel.V(2, 2))
|
||||
tileType := levelData[x][y]
|
||||
if tileType == f {
|
||||
floorTile.Draw(win, mat)
|
||||
} else {
|
||||
wallTile.Draw(win, mat)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cartesianToIso(pt pixel.Vec) pixel.Vec {
|
||||
return pixel.V((pt.X-pt.Y)*(tileSize/2), (pt.X+pt.Y)*(tileSize/4))
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/community/isometric-basics/result.png
generated
vendored
Normal file
After Width: | Height: | Size: 126 KiB |
19
vendor/github.com/faiface/pixel/examples/community/maze/README.md
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# Maze generator in Go
|
||||
|
||||
Created by [Stephen Chavez](https://github.com/redragonx)
|
||||
|
||||
This uses the game engine: Pixel. Install it here: https://github.com/faiface/pixel
|
||||
|
||||
I made this to improve my understanding of Go and some game concepts with some basic maze generating algorithms.
|
||||
|
||||
Controls: Press 'R' to restart the maze.
|
||||
|
||||
Optional command-line arguments: `go run ./maze-generator.go`
|
||||
- `-w` sets the maze's width in pixels.
|
||||
- `-h` sets the maze's height in pixels.
|
||||
- `-c` sets the maze cell's size in pixels.
|
||||
|
||||
Code based on the Recursive backtracker algorithm.
|
||||
- https://en.wikipedia.org/wiki/Maze_generation_algorithm#Recursive_backtracker
|
||||
|
||||

|
317
vendor/github.com/faiface/pixel/examples/community/maze/maze-generator.go
generated
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
package main
|
||||
|
||||
// Code based on the Recursive backtracker algorithm.
|
||||
// https://en.wikipedia.org/wiki/Maze_generation_algorithm#Recursive_backtracker
|
||||
// See https://youtu.be/HyK_Q5rrcr4 as an example
|
||||
// YouTube example ported to Go for the Pixel library.
|
||||
|
||||
// Created by Stephen Chavez
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/examples/community/maze/stack"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
|
||||
"github.com/pkg/profile"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
var visitedColor = pixel.RGB(0.5, 0, 1).Mul(pixel.Alpha(0.35))
|
||||
var hightlightColor = pixel.RGB(0.3, 0, 0).Mul(pixel.Alpha(0.45))
|
||||
var debug = false
|
||||
|
||||
type cell struct {
|
||||
walls [4]bool // Wall order: top, right, bottom, left
|
||||
|
||||
row int
|
||||
col int
|
||||
visited bool
|
||||
}
|
||||
|
||||
func (c *cell) Draw(imd *imdraw.IMDraw, wallSize int) {
|
||||
drawCol := c.col * wallSize // x
|
||||
drawRow := c.row * wallSize // y
|
||||
|
||||
imd.Color = colornames.White
|
||||
if c.walls[0] {
|
||||
// top line
|
||||
imd.Push(pixel.V(float64(drawCol), float64(drawRow)), pixel.V(float64(drawCol+wallSize), float64(drawRow)))
|
||||
imd.Line(3)
|
||||
}
|
||||
if c.walls[1] {
|
||||
// right Line
|
||||
imd.Push(pixel.V(float64(drawCol+wallSize), float64(drawRow)), pixel.V(float64(drawCol+wallSize), float64(drawRow+wallSize)))
|
||||
imd.Line(3)
|
||||
}
|
||||
if c.walls[2] {
|
||||
// bottom line
|
||||
imd.Push(pixel.V(float64(drawCol+wallSize), float64(drawRow+wallSize)), pixel.V(float64(drawCol), float64(drawRow+wallSize)))
|
||||
imd.Line(3)
|
||||
}
|
||||
if c.walls[3] {
|
||||
// left line
|
||||
imd.Push(pixel.V(float64(drawCol), float64(drawRow+wallSize)), pixel.V(float64(drawCol), float64(drawRow)))
|
||||
imd.Line(3)
|
||||
}
|
||||
imd.EndShape = imdraw.SharpEndShape
|
||||
|
||||
if c.visited {
|
||||
imd.Color = visitedColor
|
||||
imd.Push(pixel.V(float64(drawCol), (float64(drawRow))), pixel.V(float64(drawCol+wallSize), float64(drawRow+wallSize)))
|
||||
imd.Rectangle(0)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cell) GetNeighbors(grid []*cell, cols int, rows int) ([]*cell, error) {
|
||||
neighbors := []*cell{}
|
||||
j := c.row
|
||||
i := c.col
|
||||
|
||||
top, _ := getCellAt(i, j-1, cols, rows, grid)
|
||||
right, _ := getCellAt(i+1, j, cols, rows, grid)
|
||||
bottom, _ := getCellAt(i, j+1, cols, rows, grid)
|
||||
left, _ := getCellAt(i-1, j, cols, rows, grid)
|
||||
|
||||
if top != nil && !top.visited {
|
||||
neighbors = append(neighbors, top)
|
||||
}
|
||||
if right != nil && !right.visited {
|
||||
neighbors = append(neighbors, right)
|
||||
}
|
||||
if bottom != nil && !bottom.visited {
|
||||
neighbors = append(neighbors, bottom)
|
||||
}
|
||||
if left != nil && !left.visited {
|
||||
neighbors = append(neighbors, left)
|
||||
}
|
||||
|
||||
if len(neighbors) == 0 {
|
||||
return nil, errors.New("We checked all cells...")
|
||||
}
|
||||
return neighbors, nil
|
||||
}
|
||||
|
||||
func (c *cell) GetRandomNeighbor(grid []*cell, cols int, rows int) (*cell, error) {
|
||||
neighbors, err := c.GetNeighbors(grid, cols, rows)
|
||||
if neighbors == nil {
|
||||
return nil, err
|
||||
}
|
||||
nBig, err := rand.Int(rand.Reader, big.NewInt(int64(len(neighbors))))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
randomIndex := nBig.Int64()
|
||||
return neighbors[randomIndex], nil
|
||||
}
|
||||
|
||||
func (c *cell) hightlight(imd *imdraw.IMDraw, wallSize int) {
|
||||
x := c.col * wallSize
|
||||
y := c.row * wallSize
|
||||
|
||||
imd.Color = hightlightColor
|
||||
imd.Push(pixel.V(float64(x), float64(y)), pixel.V(float64(x+wallSize), float64(y+wallSize)))
|
||||
imd.Rectangle(0)
|
||||
}
|
||||
|
||||
func newCell(col int, row int) *cell {
|
||||
newCell := new(cell)
|
||||
newCell.row = row
|
||||
newCell.col = col
|
||||
|
||||
for i := range newCell.walls {
|
||||
newCell.walls[i] = true
|
||||
}
|
||||
return newCell
|
||||
}
|
||||
|
||||
// Creates the inital maze slice for use.
|
||||
func initGrid(cols, rows int) []*cell {
|
||||
grid := []*cell{}
|
||||
for j := 0; j < rows; j++ {
|
||||
for i := 0; i < cols; i++ {
|
||||
newCell := newCell(i, j)
|
||||
grid = append(grid, newCell)
|
||||
}
|
||||
}
|
||||
return grid
|
||||
}
|
||||
|
||||
func setupMaze(cols, rows int) ([]*cell, *stack.Stack, *cell) {
|
||||
// Make an empty grid
|
||||
grid := initGrid(cols, rows)
|
||||
backTrackStack := stack.NewStack(len(grid))
|
||||
currentCell := grid[0]
|
||||
|
||||
return grid, backTrackStack, currentCell
|
||||
}
|
||||
|
||||
func cellIndex(i, j, cols, rows int) int {
|
||||
if i < 0 || j < 0 || i > cols-1 || j > rows-1 {
|
||||
return -1
|
||||
}
|
||||
return i + j*cols
|
||||
}
|
||||
|
||||
func getCellAt(i int, j int, cols int, rows int, grid []*cell) (*cell, error) {
|
||||
possibleIndex := cellIndex(i, j, cols, rows)
|
||||
|
||||
if possibleIndex == -1 {
|
||||
return nil, fmt.Errorf("cellIndex: CellIndex is a negative number %d", possibleIndex)
|
||||
}
|
||||
return grid[possibleIndex], nil
|
||||
}
|
||||
|
||||
func removeWalls(a *cell, b *cell) {
|
||||
x := a.col - b.col
|
||||
|
||||
if x == 1 {
|
||||
a.walls[3] = false
|
||||
b.walls[1] = false
|
||||
} else if x == -1 {
|
||||
a.walls[1] = false
|
||||
b.walls[3] = false
|
||||
}
|
||||
|
||||
y := a.row - b.row
|
||||
|
||||
if y == 1 {
|
||||
a.walls[0] = false
|
||||
b.walls[2] = false
|
||||
} else if y == -1 {
|
||||
a.walls[2] = false
|
||||
b.walls[0] = false
|
||||
}
|
||||
}
|
||||
|
||||
func run() {
|
||||
// unsiged integers, because easier parsing error checks.
|
||||
// We must convert these to intergers, as done below...
|
||||
uScreenWidth, uScreenHeight, uWallSize := parseArgs()
|
||||
|
||||
var (
|
||||
// In pixels
|
||||
// Defualt is 800x800x40 = 20x20 wallgrid
|
||||
screenWidth = int(uScreenWidth)
|
||||
screenHeight = int(uScreenHeight)
|
||||
wallSize = int(uWallSize)
|
||||
|
||||
frames = 0
|
||||
second = time.Tick(time.Second)
|
||||
|
||||
grid = []*cell{}
|
||||
cols = screenWidth / wallSize
|
||||
rows = screenHeight / wallSize
|
||||
currentCell = new(cell)
|
||||
backTrackStack = stack.NewStack(1)
|
||||
)
|
||||
|
||||
// Set game FPS manually
|
||||
fps := time.Tick(time.Second / 60)
|
||||
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks! - Maze example",
|
||||
Bounds: pixel.R(0, 0, float64(screenHeight), float64(screenWidth)),
|
||||
}
|
||||
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
grid, backTrackStack, currentCell = setupMaze(cols, rows)
|
||||
|
||||
gridIMDraw := imdraw.New(nil)
|
||||
|
||||
for !win.Closed() {
|
||||
if win.JustReleased(pixelgl.KeyR) {
|
||||
fmt.Println("R pressed")
|
||||
grid, backTrackStack, currentCell = setupMaze(cols, rows)
|
||||
}
|
||||
|
||||
win.Clear(colornames.Gray)
|
||||
gridIMDraw.Clear()
|
||||
|
||||
for i := range grid {
|
||||
grid[i].Draw(gridIMDraw, wallSize)
|
||||
}
|
||||
|
||||
// step 1
|
||||
// Make the initial cell the current cell and mark it as visited
|
||||
currentCell.visited = true
|
||||
currentCell.hightlight(gridIMDraw, wallSize)
|
||||
|
||||
// step 2.1
|
||||
// If the current cell has any neighbours which have not been visited
|
||||
// Choose a random unvisited cell
|
||||
nextCell, _ := currentCell.GetRandomNeighbor(grid, cols, rows)
|
||||
if nextCell != nil && !nextCell.visited {
|
||||
// step 2.2
|
||||
// Push the current cell to the stack
|
||||
backTrackStack.Push(currentCell)
|
||||
|
||||
// step 2.3
|
||||
// Remove the wall between the current cell and the chosen cell
|
||||
|
||||
removeWalls(currentCell, nextCell)
|
||||
|
||||
// step 2.4
|
||||
// Make the chosen cell the current cell and mark it as visited
|
||||
nextCell.visited = true
|
||||
currentCell = nextCell
|
||||
} else if backTrackStack.Len() > 0 {
|
||||
currentCell = backTrackStack.Pop().(*cell)
|
||||
}
|
||||
|
||||
gridIMDraw.Draw(win)
|
||||
win.Update()
|
||||
<-fps
|
||||
updateFPSDisplay(win, &cfg, &frames, grid, second)
|
||||
}
|
||||
}
|
||||
|
||||
// Parses the maze arguments, all of them are optional.
|
||||
// Uses uint as implicit error checking :)
|
||||
func parseArgs() (uint, uint, uint) {
|
||||
var mazeWidthPtr = flag.Uint("w", 800, "w sets the maze's width in pixels.")
|
||||
var mazeHeightPtr = flag.Uint("h", 800, "h sets the maze's height in pixels.")
|
||||
var wallSizePtr = flag.Uint("c", 40, "c sets the maze cell's size in pixels.")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// If these aren't default values AND if they're not the same values.
|
||||
// We should warn the user that the maze will look funny.
|
||||
if *mazeWidthPtr != 800 || *mazeHeightPtr != 800 {
|
||||
if *mazeWidthPtr != *mazeHeightPtr {
|
||||
fmt.Printf("WARNING: maze width: %d and maze height: %d don't match. \n", *mazeWidthPtr, *mazeHeightPtr)
|
||||
fmt.Println("Maze will look funny because the maze size is bond to the window size!")
|
||||
}
|
||||
}
|
||||
|
||||
return *mazeWidthPtr, *mazeHeightPtr, *wallSizePtr
|
||||
}
|
||||
|
||||
func updateFPSDisplay(win *pixelgl.Window, cfg *pixelgl.WindowConfig, frames *int, grid []*cell, second <-chan time.Time) {
|
||||
*frames++
|
||||
select {
|
||||
case <-second:
|
||||
win.SetTitle(fmt.Sprintf("%s | FPS: %d with %d Cells", cfg.Title, *frames, len(grid)))
|
||||
*frames = 0
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
if debug {
|
||||
defer profile.Start().Stop()
|
||||
}
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/community/maze/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 14 KiB |
86
vendor/github.com/faiface/pixel/examples/community/maze/stack/stack.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
package stack
|
||||
|
||||
type Stack struct {
|
||||
top *Element
|
||||
size int
|
||||
max int
|
||||
}
|
||||
|
||||
type Element struct {
|
||||
value interface{}
|
||||
next *Element
|
||||
}
|
||||
|
||||
func NewStack(max int) *Stack {
|
||||
return &Stack{max: max}
|
||||
}
|
||||
|
||||
// Return the stack's length
|
||||
func (s *Stack) Len() int {
|
||||
return s.size
|
||||
}
|
||||
|
||||
// Return the stack's max
|
||||
func (s *Stack) Max() int {
|
||||
return s.max
|
||||
}
|
||||
|
||||
// Push a new element onto the stack
|
||||
func (s *Stack) Push(value interface{}) {
|
||||
if s.size+1 > s.max {
|
||||
if last := s.PopLast(); last == nil {
|
||||
panic("Unexpected nil in stack")
|
||||
}
|
||||
}
|
||||
s.top = &Element{value, s.top}
|
||||
s.size++
|
||||
}
|
||||
|
||||
// Remove the top element from the stack and return it's value
|
||||
// If the stack is empty, return nil
|
||||
func (s *Stack) Pop() (value interface{}) {
|
||||
if s.size > 0 {
|
||||
value, s.top = s.top.value, s.top.next
|
||||
s.size--
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Stack) PopLast() (value interface{}) {
|
||||
if lastElem := s.popLast(s.top); lastElem != nil {
|
||||
return lastElem.value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//Peek returns a top without removing it from list
|
||||
func (s *Stack) Peek() (value interface{}, exists bool) {
|
||||
exists = false
|
||||
if s.size > 0 {
|
||||
value = s.top.value
|
||||
exists = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Stack) popLast(elem *Element) *Element {
|
||||
if elem == nil {
|
||||
return nil
|
||||
}
|
||||
// not last because it has next and a grandchild
|
||||
if elem.next != nil && elem.next.next != nil {
|
||||
return s.popLast(elem.next)
|
||||
}
|
||||
|
||||
// current elem is second from bottom, as next elem has no child
|
||||
if elem.next != nil && elem.next.next == nil {
|
||||
last := elem.next
|
||||
// make current elem bottom of stack by removing its next element
|
||||
elem.next = nil
|
||||
s.size--
|
||||
return last
|
||||
}
|
||||
return nil
|
||||
}
|
9
vendor/github.com/faiface/pixel/examples/community/parallax-scrolling-background/README.md
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# Parallax scrolling demo
|
||||
|
||||
Created by [Sergio Vera](https://github.com/svera)
|
||||
|
||||
This example shows how to implement an infinite side scrolling background with a depth effect, using [parallax scrolling](https://en.wikipedia.org/wiki/Parallax_scrolling). Code is based in the [infinite scrolling background](https://github.com/faiface/pixel/tree/master/examples/community/scrolling-background) demo.
|
||||
|
||||
Credits to [Peter Hellberg](https://github.com/peterhellberg) for the improved background images.
|
||||
|
||||

|
BIN
vendor/github.com/faiface/pixel/examples/community/parallax-scrolling-background/background.png
generated
vendored
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
vendor/github.com/faiface/pixel/examples/community/parallax-scrolling-background/foreground.png
generated
vendored
Normal file
After Width: | Height: | Size: 25 KiB |
74
vendor/github.com/faiface/pixel/examples/community/parallax-scrolling-background/main.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
const (
|
||||
windowWidth = 600
|
||||
windowHeight = 450
|
||||
foregroundHeight = 149
|
||||
// This is the scrolling speed (pixels per second)
|
||||
// Negative values will make background to scroll to the left,
|
||||
// positive to the right.
|
||||
backgroundSpeed = -60
|
||||
foregroundSpeed = -120
|
||||
)
|
||||
|
||||
func run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Parallax scrolling demo",
|
||||
Bounds: pixel.R(0, 0, windowWidth, windowHeight),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Pic must have double the width of the window, as it will scroll to the left or right
|
||||
picBackground, err := loadPicture("background.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
picForeground, err := loadPicture("foreground.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
background := NewScrollingBackground(picBackground, windowWidth, windowHeight, backgroundSpeed)
|
||||
foreground := NewScrollingBackground(picForeground, windowWidth, foregroundHeight, foregroundSpeed)
|
||||
|
||||
last := time.Now()
|
||||
for !win.Closed() {
|
||||
dt := time.Since(last).Seconds()
|
||||
last = time.Now()
|
||||
background.Update(win, dt)
|
||||
foreground.Update(win, dt)
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/community/parallax-scrolling-background/result.png
generated
vendored
Normal file
After Width: | Height: | Size: 91 KiB |
64
vendor/github.com/faiface/pixel/examples/community/parallax-scrolling-background/scrolling_background.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
)
|
||||
|
||||
// ScrollingBackground stores all needed information to scroll a background
|
||||
// to the left or right
|
||||
type ScrollingBackground struct {
|
||||
width float64
|
||||
height float64
|
||||
displacement float64
|
||||
speed float64
|
||||
backgrounds [2]*pixel.Sprite
|
||||
positions [2]pixel.Vec
|
||||
}
|
||||
|
||||
// NewScrollingBackground construct and returns a new instance of scrollingBackground,
|
||||
// positioning the background images according to the speed value
|
||||
func NewScrollingBackground(pic pixel.Picture, width, height, speed float64) *ScrollingBackground {
|
||||
sb := &ScrollingBackground{
|
||||
width: width,
|
||||
height: height,
|
||||
speed: speed,
|
||||
backgrounds: [2]*pixel.Sprite{
|
||||
pixel.NewSprite(pic, pixel.R(0, 0, width, height)),
|
||||
pixel.NewSprite(pic, pixel.R(width, 0, width*2, height)),
|
||||
},
|
||||
}
|
||||
|
||||
sb.positionImages()
|
||||
return sb
|
||||
}
|
||||
|
||||
// If scrolling speed > 0, put second background image ouside the screen,
|
||||
// at the left side, otherwise put it at the right side.
|
||||
func (sb *ScrollingBackground) positionImages() {
|
||||
if sb.speed > 0 {
|
||||
sb.positions = [2]pixel.Vec{
|
||||
pixel.V(sb.width/2, sb.height/2),
|
||||
pixel.V((sb.width/2)-sb.width, sb.height/2),
|
||||
}
|
||||
} else {
|
||||
sb.positions = [2]pixel.Vec{
|
||||
pixel.V(sb.width/2, sb.height/2),
|
||||
pixel.V(sb.width+(sb.width/2), sb.height/2),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update will move backgrounds certain pixels, depending of the amount of time passed
|
||||
func (sb *ScrollingBackground) Update(win *pixelgl.Window, dt float64) {
|
||||
if math.Abs(sb.displacement) >= sb.width {
|
||||
sb.displacement = 0
|
||||
sb.positions[0], sb.positions[1] = sb.positions[1], sb.positions[0]
|
||||
}
|
||||
d := pixel.V(sb.displacement, 0)
|
||||
sb.backgrounds[0].Draw(win, pixel.IM.Moved(sb.positions[0].Add(d)))
|
||||
sb.backgrounds[1].Draw(win, pixel.IM.Moved(sb.positions[1].Add(d)))
|
||||
sb.displacement += sb.speed * dt
|
||||
}
|
12
vendor/github.com/faiface/pixel/examples/community/procedural-terrain-1d/README.md
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# Procedural 1D terrain generator
|
||||
|
||||
Created by [Sergio Vera](https://github.com/svera).
|
||||
|
||||
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).
|
||||
|
||||

|
104
vendor/github.com/faiface/pixel/examples/community/procedural-terrain-1d/main.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "image/jpeg"
|
||||
|
||||
perlin "github.com/aquilax/go-perlin"
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"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
|
||||
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)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/community/procedural-terrain-1d/result.png
generated
vendored
Normal file
After Width: | Height: | Size: 759 KiB |
BIN
vendor/github.com/faiface/pixel/examples/community/procedural-terrain-1d/stone.jpg
generated
vendored
Normal file
After Width: | Height: | Size: 368 KiB |
22
vendor/github.com/faiface/pixel/examples/community/raycaster/README.md
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# raycaster
|
||||
|
||||
A raycaster made by [Peter Hellberg](https://github.com/peterhellberg/) as part of his [pixel-experiments](https://github.com/peterhellberg/pixel-experiments).
|
||||
|
||||
Based on Lode’s article on [raycasting](http://lodev.org/cgtutor/raycasting.html).
|
||||
|
||||
## Controls
|
||||
|
||||
WASD for strafing and arrow keys for rotation.
|
||||
|
||||
Place blocks using the number keys.
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Links
|
||||
|
||||
- https://github.com/peterhellberg/pixel-experiments/tree/master/raycaster
|
||||
- https://gist.github.com/peterhellberg/835eccabf95800555120cc8f0c9e16c2
|
550
vendor/github.com/faiface/pixel/examples/community/raycaster/raycaster.go
generated
vendored
Normal file
BIN
vendor/github.com/faiface/pixel/examples/community/raycaster/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 47 KiB |
7
vendor/github.com/faiface/pixel/examples/community/scrolling-background/README.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# Infinite scrolling background demo
|
||||
|
||||
Created by [Sergio Vera](https://github.com/svera)
|
||||
|
||||
This example shows how to implement an infinite side scrolling background.
|
||||
|
||||
Credits to [Peter Hellberg](https://github.com/peterhellberg) for the improved background image.
|
BIN
vendor/github.com/faiface/pixel/examples/community/scrolling-background/gamebackground.png
generated
vendored
Normal file
After Width: | Height: | Size: 56 KiB |
83
vendor/github.com/faiface/pixel/examples/community/scrolling-background/main.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
const (
|
||||
windowWidth = 600
|
||||
windowHeight = 450
|
||||
// This is the scrolling speed
|
||||
linesPerSecond = 60
|
||||
)
|
||||
|
||||
func run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Scrolling background demo",
|
||||
Bounds: pixel.R(0, 0, windowWidth, windowHeight),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Pic must have double the width of the window, as it will scroll to the left
|
||||
pic, err := loadPicture("gamebackground.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Backgrounds are made taking the left and right halves of the image
|
||||
background1 := pixel.NewSprite(pic, pixel.R(0, 0, windowWidth, windowHeight))
|
||||
background2 := pixel.NewSprite(pic, pixel.R(windowWidth, 0, windowWidth*2, windowHeight))
|
||||
|
||||
// In the beginning, vector1 will put background1 filling the whole window, while vector2 will
|
||||
// put background2 just at the right side of the window, out of view
|
||||
vector1 := pixel.V(windowWidth/2, windowHeight/2)
|
||||
vector2 := pixel.V(windowWidth+(windowWidth/2), windowHeight/2)
|
||||
|
||||
i := float64(0)
|
||||
last := time.Now()
|
||||
for !win.Closed() {
|
||||
dt := time.Since(last).Seconds()
|
||||
last = time.Now()
|
||||
// When one of the backgrounds has completely scrolled, we swap displacement vectors,
|
||||
// so the backgrounds will swap positions too regarding the previous iteration,
|
||||
// thus making the background endless.
|
||||
if i <= -windowWidth {
|
||||
i = 0
|
||||
vector1, vector2 = vector2, vector1
|
||||
}
|
||||
// This delta vector will move the backgrounds to the left
|
||||
d := pixel.V(-i, 0)
|
||||
background1.Draw(win, pixel.IM.Moved(vector1.Sub(d)))
|
||||
background2.Draw(win, pixel.IM.Moved(vector2.Sub(d)))
|
||||
i -= linesPerSecond * dt
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
20
vendor/github.com/faiface/pixel/examples/community/starfield/README.md
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# starfield
|
||||
|
||||
Classic starfield… with [supposedly accurate stellar colors](http://www.vendian.org/mncharity/dir3/starcolor/)
|
||||
|
||||
Made by [Peter Hellberg](https://github.com/peterhellberg/) as part of his [pixel-experiments](https://github.com/peterhellberg/pixel-experiments)
|
||||
|
||||
## Controls
|
||||
|
||||
Arrow up and down to change speed. Space bar to almost stop.
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Links
|
||||
|
||||
- https://github.com/peterhellberg/pixel-experiments/tree/master/starfield
|
||||
- https://gist.github.com/peterhellberg/4018e228cced61a0bb26991e49299c96
|
BIN
vendor/github.com/faiface/pixel/examples/community/starfield/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 6.0 KiB |
165
vendor/github.com/faiface/pixel/examples/community/starfield/starfield.go
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
)
|
||||
|
||||
const w, h = float64(1024), float64(512)
|
||||
|
||||
var speed = float64(200)
|
||||
|
||||
var stars [1024]*star
|
||||
|
||||
func init() {
|
||||
rand.Seed(4)
|
||||
|
||||
for i := 0; i < len(stars); i++ {
|
||||
stars[i] = newStar()
|
||||
}
|
||||
}
|
||||
|
||||
type star struct {
|
||||
pixel.Vec
|
||||
Z float64
|
||||
P float64
|
||||
C color.RGBA
|
||||
}
|
||||
|
||||
func newStar() *star {
|
||||
return &star{
|
||||
pixel.V(random(-w, w), random(-h, h)),
|
||||
random(0, w), 0, Colors[rand.Intn(len(Colors))],
|
||||
}
|
||||
}
|
||||
|
||||
func (s *star) update(d float64) {
|
||||
s.P = s.Z
|
||||
s.Z -= d * speed
|
||||
|
||||
if s.Z < 0 {
|
||||
s.X = random(-w, w)
|
||||
s.Y = random(-h, h)
|
||||
s.Z = w
|
||||
s.P = s.Z
|
||||
}
|
||||
}
|
||||
|
||||
func (s *star) draw(imd *imdraw.IMDraw) {
|
||||
p := pixel.V(
|
||||
scale(s.X/s.Z, 0, 1, 0, w),
|
||||
scale(s.Y/s.Z, 0, 1, 0, h),
|
||||
)
|
||||
|
||||
o := pixel.V(
|
||||
scale(s.X/s.P, 0, 1, 0, w),
|
||||
scale(s.Y/s.P, 0, 1, 0, h),
|
||||
)
|
||||
|
||||
r := scale(s.Z, 0, w, 11, 0)
|
||||
|
||||
imd.Color = s.C
|
||||
|
||||
if p.Sub(o).Len() > 6 {
|
||||
imd.Push(p, o)
|
||||
imd.Line(r)
|
||||
}
|
||||
|
||||
imd.Push(p)
|
||||
imd.Circle(r, 0)
|
||||
}
|
||||
|
||||
func run() {
|
||||
win, err := pixelgl.NewWindow(pixelgl.WindowConfig{
|
||||
Bounds: pixel.R(0, 0, w, h),
|
||||
VSync: true,
|
||||
Undecorated: true,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
imd := imdraw.New(nil)
|
||||
|
||||
imd.Precision = 7
|
||||
|
||||
imd.SetMatrix(pixel.IM.Moved(win.Bounds().Center()))
|
||||
|
||||
last := time.Now()
|
||||
|
||||
for !win.Closed() {
|
||||
win.SetClosed(win.JustPressed(pixelgl.KeyEscape) || win.JustPressed(pixelgl.KeyQ))
|
||||
|
||||
if win.Pressed(pixelgl.KeyUp) {
|
||||
speed += 10
|
||||
}
|
||||
|
||||
if win.Pressed(pixelgl.KeyDown) {
|
||||
if speed > 10 {
|
||||
speed -= 10
|
||||
}
|
||||
}
|
||||
|
||||
if win.Pressed(pixelgl.KeySpace) {
|
||||
speed = 100
|
||||
}
|
||||
|
||||
d := time.Since(last).Seconds()
|
||||
|
||||
last = time.Now()
|
||||
|
||||
imd.Clear()
|
||||
|
||||
for _, s := range stars {
|
||||
s.update(d)
|
||||
s.draw(imd)
|
||||
}
|
||||
|
||||
win.Clear(color.Black)
|
||||
imd.Draw(win)
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
||||
|
||||
func random(min, max float64) float64 {
|
||||
return rand.Float64()*(max-min) + min
|
||||
}
|
||||
|
||||
func scale(unscaledNum, min, max, minAllowed, maxAllowed float64) float64 {
|
||||
return (maxAllowed-minAllowed)*(unscaledNum-min)/(max-min) + minAllowed
|
||||
}
|
||||
|
||||
// Colors based on stellar types listed at
|
||||
// http://www.vendian.org/mncharity/dir3/starcolor/
|
||||
var Colors = []color.RGBA{
|
||||
color.RGBA{157, 180, 255, 255},
|
||||
color.RGBA{162, 185, 255, 255},
|
||||
color.RGBA{167, 188, 255, 255},
|
||||
color.RGBA{170, 191, 255, 255},
|
||||
color.RGBA{175, 195, 255, 255},
|
||||
color.RGBA{186, 204, 255, 255},
|
||||
color.RGBA{192, 209, 255, 255},
|
||||
color.RGBA{202, 216, 255, 255},
|
||||
color.RGBA{228, 232, 255, 255},
|
||||
color.RGBA{237, 238, 255, 255},
|
||||
color.RGBA{251, 248, 255, 255},
|
||||
color.RGBA{255, 249, 249, 255},
|
||||
color.RGBA{255, 245, 236, 255},
|
||||
color.RGBA{255, 244, 232, 255},
|
||||
color.RGBA{255, 241, 223, 255},
|
||||
color.RGBA{255, 235, 209, 255},
|
||||
color.RGBA{255, 215, 174, 255},
|
||||
color.RGBA{255, 198, 144, 255},
|
||||
color.RGBA{255, 190, 127, 255},
|
||||
color.RGBA{255, 187, 123, 255},
|
||||
color.RGBA{255, 187, 123, 255},
|
||||
}
|
29
vendor/github.com/faiface/pixel/examples/guide/01_creating_a_window/main.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
func run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks!",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
win.Clear(colornames.Skyblue)
|
||||
|
||||
for !win.Closed() {
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/guide/02_drawing_a_sprite/hiking.png
generated
vendored
Normal file
After Width: | Height: | Size: 68 KiB |
56
vendor/github.com/faiface/pixel/examples/guide/02_drawing_a_sprite/main.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"os"
|
||||
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
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 run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks!",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pic, err := loadPicture("hiking.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sprite := pixel.NewSprite(pic, pic.Bounds())
|
||||
|
||||
win.Clear(colornames.Greenyellow)
|
||||
|
||||
sprite.Draw(win, pixel.IM.Moved(win.Bounds().Center()))
|
||||
|
||||
for !win.Closed() {
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/guide/03_moving_scaling_and_rotating_with_matrix/hiking.png
generated
vendored
Normal file
After Width: | Height: | Size: 68 KiB |
70
vendor/github.com/faiface/pixel/examples/guide/03_moving_scaling_and_rotating_with_matrix/main.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
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 run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks!",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
win.SetSmooth(true)
|
||||
|
||||
pic, err := loadPicture("hiking.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sprite := pixel.NewSprite(pic, pic.Bounds())
|
||||
|
||||
angle := 0.0
|
||||
|
||||
last := time.Now()
|
||||
for !win.Closed() {
|
||||
dt := time.Since(last).Seconds()
|
||||
last = time.Now()
|
||||
|
||||
angle += 3 * dt
|
||||
|
||||
win.Clear(colornames.Firebrick)
|
||||
|
||||
mat := pixel.IM
|
||||
mat = mat.Rotated(pixel.ZV, angle)
|
||||
mat = mat.Moved(win.Bounds().Center())
|
||||
sprite.Draw(win, mat)
|
||||
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
102
vendor/github.com/faiface/pixel/examples/guide/04_pressing_keys_and_clicking_mouse/main.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
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 run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks!",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
spritesheet, err := loadPicture("trees.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var treesFrames []pixel.Rect
|
||||
for x := spritesheet.Bounds().Min.X; x < spritesheet.Bounds().Max.X; x += 32 {
|
||||
for y := spritesheet.Bounds().Min.Y; y < spritesheet.Bounds().Max.Y; y += 32 {
|
||||
treesFrames = append(treesFrames, pixel.R(x, y, x+32, y+32))
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
camPos = pixel.ZV
|
||||
camSpeed = 500.0
|
||||
camZoom = 1.0
|
||||
camZoomSpeed = 1.2
|
||||
trees []*pixel.Sprite
|
||||
matrices []pixel.Matrix
|
||||
)
|
||||
|
||||
last := time.Now()
|
||||
for !win.Closed() {
|
||||
dt := time.Since(last).Seconds()
|
||||
last = time.Now()
|
||||
|
||||
cam := pixel.IM.Scaled(camPos, camZoom).Moved(win.Bounds().Center().Sub(camPos))
|
||||
win.SetMatrix(cam)
|
||||
|
||||
if win.JustPressed(pixelgl.MouseButtonLeft) {
|
||||
tree := pixel.NewSprite(spritesheet, treesFrames[rand.Intn(len(treesFrames))])
|
||||
trees = append(trees, tree)
|
||||
mouse := cam.Unproject(win.MousePosition())
|
||||
matrices = append(matrices, pixel.IM.Scaled(pixel.ZV, 4).Moved(mouse))
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyLeft) {
|
||||
camPos.X -= camSpeed * dt
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyRight) {
|
||||
camPos.X += camSpeed * dt
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyDown) {
|
||||
camPos.Y -= camSpeed * dt
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyUp) {
|
||||
camPos.Y += camSpeed * dt
|
||||
}
|
||||
camZoom *= math.Pow(camZoomSpeed, win.MouseScroll().Y)
|
||||
|
||||
win.Clear(colornames.Forestgreen)
|
||||
|
||||
for i, tree := range trees {
|
||||
tree.Draw(win, matrices[i])
|
||||
}
|
||||
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/guide/04_pressing_keys_and_clicking_mouse/trees.png
generated
vendored
Normal file
After Width: | Height: | Size: 2.5 KiB |
110
vendor/github.com/faiface/pixel/examples/guide/05_drawing_efficiently_with_batch/main.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
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 run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks!",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
spritesheet, err := loadPicture("trees.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
batch := pixel.NewBatch(&pixel.TrianglesData{}, spritesheet)
|
||||
|
||||
var treesFrames []pixel.Rect
|
||||
for x := spritesheet.Bounds().Min.X; x < spritesheet.Bounds().Max.X; x += 32 {
|
||||
for y := spritesheet.Bounds().Min.Y; y < spritesheet.Bounds().Max.Y; y += 32 {
|
||||
treesFrames = append(treesFrames, pixel.R(x, y, x+32, y+32))
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
camPos = pixel.ZV
|
||||
camSpeed = 500.0
|
||||
camZoom = 1.0
|
||||
camZoomSpeed = 1.2
|
||||
)
|
||||
|
||||
var (
|
||||
frames = 0
|
||||
second = time.Tick(time.Second)
|
||||
)
|
||||
|
||||
last := time.Now()
|
||||
for !win.Closed() {
|
||||
dt := time.Since(last).Seconds()
|
||||
last = time.Now()
|
||||
|
||||
cam := pixel.IM.Scaled(camPos, camZoom).Moved(win.Bounds().Center().Sub(camPos))
|
||||
win.SetMatrix(cam)
|
||||
|
||||
if win.Pressed(pixelgl.MouseButtonLeft) {
|
||||
tree := pixel.NewSprite(spritesheet, treesFrames[rand.Intn(len(treesFrames))])
|
||||
mouse := cam.Unproject(win.MousePosition())
|
||||
tree.Draw(batch, pixel.IM.Scaled(pixel.ZV, 4).Moved(mouse))
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyLeft) {
|
||||
camPos.X -= camSpeed * dt
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyRight) {
|
||||
camPos.X += camSpeed * dt
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyDown) {
|
||||
camPos.Y -= camSpeed * dt
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyUp) {
|
||||
camPos.Y += camSpeed * dt
|
||||
}
|
||||
camZoom *= math.Pow(camZoomSpeed, win.MouseScroll().Y)
|
||||
|
||||
win.Clear(colornames.Forestgreen)
|
||||
batch.Draw(win)
|
||||
win.Update()
|
||||
|
||||
frames++
|
||||
select {
|
||||
case <-second:
|
||||
win.SetTitle(fmt.Sprintf("%s | FPS: %d", cfg.Title, frames))
|
||||
frames = 0
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/guide/05_drawing_efficiently_with_batch/trees.png
generated
vendored
Normal file
After Width: | Height: | Size: 2.5 KiB |
53
vendor/github.com/faiface/pixel/examples/guide/06_drawing_shapes_with_imdraw/main.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
func run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks!",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
imd := imdraw.New(nil)
|
||||
|
||||
imd.Color = colornames.Blueviolet
|
||||
imd.EndShape = imdraw.RoundEndShape
|
||||
imd.Push(pixel.V(100, 100), pixel.V(700, 100))
|
||||
imd.EndShape = imdraw.SharpEndShape
|
||||
imd.Push(pixel.V(100, 500), pixel.V(700, 500))
|
||||
imd.Line(30)
|
||||
|
||||
imd.Color = colornames.Limegreen
|
||||
imd.Push(pixel.V(500, 500))
|
||||
imd.Circle(300, 50)
|
||||
imd.Color = colornames.Navy
|
||||
imd.Push(pixel.V(200, 500), pixel.V(800, 500))
|
||||
imd.Ellipse(pixel.V(120, 80), 0)
|
||||
|
||||
imd.Color = colornames.Red
|
||||
imd.EndShape = imdraw.RoundEndShape
|
||||
imd.Push(pixel.V(500, 350))
|
||||
imd.CircleArc(150, -math.Pi, 0, 30)
|
||||
|
||||
for !win.Closed() {
|
||||
win.Clear(colornames.Aliceblue)
|
||||
imd.Draw(win)
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/guide/07_typing_text_on_the_screen/intuitive.ttf
generated
vendored
Normal file
78
vendor/github.com/faiface/pixel/examples/guide/07_typing_text_on_the_screen/main.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"github.com/faiface/pixel/text"
|
||||
"github.com/golang/freetype/truetype"
|
||||
"golang.org/x/image/colornames"
|
||||
"golang.org/x/image/font"
|
||||
)
|
||||
|
||||
func loadTTF(path string, size float64) (font.Face, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
bytes, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
font, err := truetype.Parse(bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return truetype.NewFace(font, &truetype.Options{
|
||||
Size: size,
|
||||
GlyphCacheEntries: 1,
|
||||
}), nil
|
||||
}
|
||||
|
||||
func run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Pixel Rocks!",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
win.SetSmooth(true)
|
||||
|
||||
face, err := loadTTF("intuitive.ttf", 80)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
atlas := text.NewAtlas(face, text.ASCII)
|
||||
txt := text.New(pixel.V(50, 500), atlas)
|
||||
|
||||
txt.Color = colornames.Lightgrey
|
||||
|
||||
fps := time.Tick(time.Second / 120)
|
||||
|
||||
for !win.Closed() {
|
||||
txt.WriteString(win.Typed())
|
||||
if win.JustPressed(pixelgl.KeyEnter) || win.Repeated(pixelgl.KeyEnter) {
|
||||
txt.WriteRune('\n')
|
||||
}
|
||||
|
||||
win.Clear(colornames.Darkcyan)
|
||||
txt.Draw(win, pixel.IM.Moved(win.Bounds().Center().Sub(txt.Bounds().Center())))
|
||||
win.Update()
|
||||
|
||||
<-fps
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
13
vendor/github.com/faiface/pixel/examples/lights/README.md
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Lights
|
||||
|
||||
This example demonstrates powerful Porter-Duff composition used to create a nice noisy light effect.
|
||||
|
||||
**Use W and S keys** to adjust the level of "dust".
|
||||
|
||||
The FPS is limited to 30, because the effect is a little expensive and my computer couldn't handle
|
||||
60 FPS. If you have a more powerful computer (which is quite likely), peek into the code and disable
|
||||
the limit.
|
||||
|
||||
Credit for the panda art goes to [Ján Štrba](https://www.artstation.com/artist/janstrba).
|
||||
|
||||

|
195
vendor/github.com/faiface/pixel/examples/lights/main.go
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"math"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
type colorlight struct {
|
||||
color pixel.RGBA
|
||||
point pixel.Vec
|
||||
angle float64
|
||||
radius float64
|
||||
dust float64
|
||||
|
||||
spread float64
|
||||
|
||||
imd *imdraw.IMDraw
|
||||
}
|
||||
|
||||
func (cl *colorlight) apply(dst pixel.ComposeTarget, center pixel.Vec, src, noise *pixel.Sprite) {
|
||||
// create the light arc if not created already
|
||||
if cl.imd == nil {
|
||||
imd := imdraw.New(nil)
|
||||
imd.Color = pixel.Alpha(1)
|
||||
imd.Push(pixel.ZV)
|
||||
imd.Color = pixel.Alpha(0)
|
||||
for angle := -cl.spread / 2; angle <= cl.spread/2; angle += cl.spread / 64 {
|
||||
imd.Push(pixel.V(1, 0).Rotated(angle))
|
||||
}
|
||||
imd.Polygon(0)
|
||||
cl.imd = imd
|
||||
}
|
||||
|
||||
// draw the light arc
|
||||
dst.SetMatrix(pixel.IM.Scaled(pixel.ZV, cl.radius).Rotated(pixel.ZV, cl.angle).Moved(cl.point))
|
||||
dst.SetColorMask(pixel.Alpha(1))
|
||||
dst.SetComposeMethod(pixel.ComposePlus)
|
||||
cl.imd.Draw(dst)
|
||||
|
||||
// draw the noise inside the light
|
||||
dst.SetMatrix(pixel.IM)
|
||||
dst.SetComposeMethod(pixel.ComposeIn)
|
||||
noise.Draw(dst, pixel.IM.Moved(center))
|
||||
|
||||
// draw an image inside the noisy light
|
||||
dst.SetColorMask(cl.color)
|
||||
dst.SetComposeMethod(pixel.ComposeIn)
|
||||
src.Draw(dst, pixel.IM.Moved(center))
|
||||
|
||||
// draw the light reflected from the dust
|
||||
dst.SetMatrix(pixel.IM.Scaled(pixel.ZV, cl.radius).Rotated(pixel.ZV, cl.angle).Moved(cl.point))
|
||||
dst.SetColorMask(cl.color.Mul(pixel.Alpha(cl.dust)))
|
||||
dst.SetComposeMethod(pixel.ComposePlus)
|
||||
cl.imd.Draw(dst)
|
||||
}
|
||||
|
||||
func run() {
|
||||
pandaPic, err := loadPicture("panda.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
noisePic, err := loadPicture("noise.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Lights",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
panda := pixel.NewSprite(pandaPic, pandaPic.Bounds())
|
||||
noise := pixel.NewSprite(noisePic, noisePic.Bounds())
|
||||
|
||||
colors := []pixel.RGBA{
|
||||
pixel.RGB(1, 0, 0),
|
||||
pixel.RGB(0, 1, 0),
|
||||
pixel.RGB(0, 0, 1),
|
||||
pixel.RGB(1/math.Sqrt2, 1/math.Sqrt2, 0),
|
||||
}
|
||||
|
||||
points := []pixel.Vec{
|
||||
{X: win.Bounds().Min.X, Y: win.Bounds().Min.Y},
|
||||
{X: win.Bounds().Max.X, Y: win.Bounds().Min.Y},
|
||||
{X: win.Bounds().Max.X, Y: win.Bounds().Max.Y},
|
||||
{X: win.Bounds().Min.X, Y: win.Bounds().Max.Y},
|
||||
}
|
||||
|
||||
angles := []float64{
|
||||
math.Pi / 4,
|
||||
math.Pi/4 + math.Pi/2,
|
||||
math.Pi/4 + 2*math.Pi/2,
|
||||
math.Pi/4 + 3*math.Pi/2,
|
||||
}
|
||||
|
||||
lights := make([]colorlight, 4)
|
||||
for i := range lights {
|
||||
lights[i] = colorlight{
|
||||
color: colors[i],
|
||||
point: points[i],
|
||||
angle: angles[i],
|
||||
radius: 800,
|
||||
dust: 0.3,
|
||||
spread: math.Pi / math.E,
|
||||
}
|
||||
}
|
||||
|
||||
speed := []float64{11.0 / 23, 13.0 / 23, 17.0 / 23, 19.0 / 23}
|
||||
|
||||
oneLight := pixelgl.NewCanvas(win.Bounds())
|
||||
allLight := pixelgl.NewCanvas(win.Bounds())
|
||||
|
||||
fps30 := time.Tick(time.Second / 30)
|
||||
|
||||
start := time.Now()
|
||||
for !win.Closed() {
|
||||
if win.Pressed(pixelgl.KeyW) {
|
||||
for i := range lights {
|
||||
lights[i].dust += 0.05
|
||||
if lights[i].dust > 1 {
|
||||
lights[i].dust = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyS) {
|
||||
for i := range lights {
|
||||
lights[i].dust -= 0.05
|
||||
if lights[i].dust < 0 {
|
||||
lights[i].dust = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
since := time.Since(start).Seconds()
|
||||
for i := range lights {
|
||||
lights[i].angle = angles[i] + math.Sin(since*speed[i])*math.Pi/8
|
||||
}
|
||||
|
||||
win.Clear(pixel.RGB(0, 0, 0))
|
||||
|
||||
// draw the panda visible outside the light
|
||||
win.SetColorMask(pixel.Alpha(0.4))
|
||||
win.SetComposeMethod(pixel.ComposePlus)
|
||||
panda.Draw(win, pixel.IM.Moved(win.Bounds().Center()))
|
||||
|
||||
allLight.Clear(pixel.Alpha(0))
|
||||
allLight.SetComposeMethod(pixel.ComposePlus)
|
||||
|
||||
// accumulate all the lights
|
||||
for i := range lights {
|
||||
oneLight.Clear(pixel.Alpha(0))
|
||||
lights[i].apply(oneLight, oneLight.Bounds().Center(), panda, noise)
|
||||
oneLight.Draw(allLight, pixel.IM.Moved(allLight.Bounds().Center()))
|
||||
}
|
||||
|
||||
// compose the final result
|
||||
win.SetColorMask(pixel.Alpha(1))
|
||||
allLight.Draw(win, pixel.IM.Moved(win.Bounds().Center()))
|
||||
|
||||
win.Update()
|
||||
|
||||
<-fps30 // maintain 30 fps, because my computer couldn't handle 60 here
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/lights/noise.png
generated
vendored
Normal file
After Width: | Height: | Size: 838 KiB |
BIN
vendor/github.com/faiface/pixel/examples/lights/panda.png
generated
vendored
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
vendor/github.com/faiface/pixel/examples/lights/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 1.1 MiB |
14
vendor/github.com/faiface/pixel/examples/platformer/README.md
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Platformer
|
||||
|
||||
This example demostrates a way to put things together and create a simple platformer game with a
|
||||
Gopher!
|
||||
|
||||
Use **arrow keys** to run and jump around. Press **ENTER** to restart. (And hush, hush, secret.
|
||||
Press TAB for slo-mo!)
|
||||
|
||||
The retro feel is, other than from the pixel art spritesheet, achieved by using a 160x120px large
|
||||
off-screen canvas, drawing everything to it and then stretching it to fit the window.
|
||||
|
||||
The Gopher spritesheet comes from excellent [Egon Elbre](https://github.com/egonelbre/gophers).
|
||||
|
||||

|
394
vendor/github.com/faiface/pixel/examples/platformer/main.go
generated
vendored
Normal file
@@ -0,0 +1,394 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
func loadAnimationSheet(sheetPath, descPath string, frameWidth float64) (sheet pixel.Picture, anims map[string][]pixel.Rect, err error) {
|
||||
// total hack, nicely format the error at the end, so I don't have to type it every time
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "error loading animation sheet")
|
||||
}
|
||||
}()
|
||||
|
||||
// open and load the spritesheet
|
||||
sheetFile, err := os.Open(sheetPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer sheetFile.Close()
|
||||
sheetImg, _, err := image.Decode(sheetFile)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
sheet = pixel.PictureDataFromImage(sheetImg)
|
||||
|
||||
// create a slice of frames inside the spritesheet
|
||||
var frames []pixel.Rect
|
||||
for x := 0.0; x+frameWidth <= sheet.Bounds().Max.X; x += frameWidth {
|
||||
frames = append(frames, pixel.R(
|
||||
x,
|
||||
0,
|
||||
x+frameWidth,
|
||||
sheet.Bounds().H(),
|
||||
))
|
||||
}
|
||||
|
||||
descFile, err := os.Open(descPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer descFile.Close()
|
||||
|
||||
anims = make(map[string][]pixel.Rect)
|
||||
|
||||
// load the animation information, name and interval inside the spritesheet
|
||||
desc := csv.NewReader(descFile)
|
||||
for {
|
||||
anim, err := desc.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
name := anim[0]
|
||||
start, _ := strconv.Atoi(anim[1])
|
||||
end, _ := strconv.Atoi(anim[2])
|
||||
|
||||
anims[name] = frames[start : end+1]
|
||||
}
|
||||
|
||||
return sheet, anims, nil
|
||||
}
|
||||
|
||||
type platform struct {
|
||||
rect pixel.Rect
|
||||
color color.Color
|
||||
}
|
||||
|
||||
func (p *platform) draw(imd *imdraw.IMDraw) {
|
||||
imd.Color = p.color
|
||||
imd.Push(p.rect.Min, p.rect.Max)
|
||||
imd.Rectangle(0)
|
||||
}
|
||||
|
||||
type gopherPhys struct {
|
||||
gravity float64
|
||||
runSpeed float64
|
||||
jumpSpeed float64
|
||||
|
||||
rect pixel.Rect
|
||||
vel pixel.Vec
|
||||
ground bool
|
||||
}
|
||||
|
||||
func (gp *gopherPhys) update(dt float64, ctrl pixel.Vec, platforms []platform) {
|
||||
// apply controls
|
||||
switch {
|
||||
case ctrl.X < 0:
|
||||
gp.vel.X = -gp.runSpeed
|
||||
case ctrl.X > 0:
|
||||
gp.vel.X = +gp.runSpeed
|
||||
default:
|
||||
gp.vel.X = 0
|
||||
}
|
||||
|
||||
// apply gravity and velocity
|
||||
gp.vel.Y += gp.gravity * dt
|
||||
gp.rect = gp.rect.Moved(gp.vel.Scaled(dt))
|
||||
|
||||
// check collisions against each platform
|
||||
gp.ground = false
|
||||
if gp.vel.Y <= 0 {
|
||||
for _, p := range platforms {
|
||||
if gp.rect.Max.X <= p.rect.Min.X || gp.rect.Min.X >= p.rect.Max.X {
|
||||
continue
|
||||
}
|
||||
if gp.rect.Min.Y > p.rect.Max.Y || gp.rect.Min.Y < p.rect.Max.Y+gp.vel.Y*dt {
|
||||
continue
|
||||
}
|
||||
gp.vel.Y = 0
|
||||
gp.rect = gp.rect.Moved(pixel.V(0, p.rect.Max.Y-gp.rect.Min.Y))
|
||||
gp.ground = true
|
||||
}
|
||||
}
|
||||
|
||||
// jump if on the ground and the player wants to jump
|
||||
if gp.ground && ctrl.Y > 0 {
|
||||
gp.vel.Y = gp.jumpSpeed
|
||||
}
|
||||
}
|
||||
|
||||
type animState int
|
||||
|
||||
const (
|
||||
idle animState = iota
|
||||
running
|
||||
jumping
|
||||
)
|
||||
|
||||
type gopherAnim struct {
|
||||
sheet pixel.Picture
|
||||
anims map[string][]pixel.Rect
|
||||
rate float64
|
||||
|
||||
state animState
|
||||
counter float64
|
||||
dir float64
|
||||
|
||||
frame pixel.Rect
|
||||
|
||||
sprite *pixel.Sprite
|
||||
}
|
||||
|
||||
func (ga *gopherAnim) update(dt float64, phys *gopherPhys) {
|
||||
ga.counter += dt
|
||||
|
||||
// determine the new animation state
|
||||
var newState animState
|
||||
switch {
|
||||
case !phys.ground:
|
||||
newState = jumping
|
||||
case phys.vel.Len() == 0:
|
||||
newState = idle
|
||||
case phys.vel.Len() > 0:
|
||||
newState = running
|
||||
}
|
||||
|
||||
// reset the time counter if the state changed
|
||||
if ga.state != newState {
|
||||
ga.state = newState
|
||||
ga.counter = 0
|
||||
}
|
||||
|
||||
// determine the correct animation frame
|
||||
switch ga.state {
|
||||
case idle:
|
||||
ga.frame = ga.anims["Front"][0]
|
||||
case running:
|
||||
i := int(math.Floor(ga.counter / ga.rate))
|
||||
ga.frame = ga.anims["Run"][i%len(ga.anims["Run"])]
|
||||
case jumping:
|
||||
speed := phys.vel.Y
|
||||
i := int((-speed/phys.jumpSpeed + 1) / 2 * float64(len(ga.anims["Jump"])))
|
||||
if i < 0 {
|
||||
i = 0
|
||||
}
|
||||
if i >= len(ga.anims["Jump"]) {
|
||||
i = len(ga.anims["Jump"]) - 1
|
||||
}
|
||||
ga.frame = ga.anims["Jump"][i]
|
||||
}
|
||||
|
||||
// set the facing direction of the gopher
|
||||
if phys.vel.X != 0 {
|
||||
if phys.vel.X > 0 {
|
||||
ga.dir = +1
|
||||
} else {
|
||||
ga.dir = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ga *gopherAnim) draw(t pixel.Target, phys *gopherPhys) {
|
||||
if ga.sprite == nil {
|
||||
ga.sprite = pixel.NewSprite(nil, pixel.Rect{})
|
||||
}
|
||||
// draw the correct frame with the correct position and direction
|
||||
ga.sprite.Set(ga.sheet, ga.frame)
|
||||
ga.sprite.Draw(t, pixel.IM.
|
||||
ScaledXY(pixel.ZV, pixel.V(
|
||||
phys.rect.W()/ga.sprite.Frame().W(),
|
||||
phys.rect.H()/ga.sprite.Frame().H(),
|
||||
)).
|
||||
ScaledXY(pixel.ZV, pixel.V(-ga.dir, 1)).
|
||||
Moved(phys.rect.Center()),
|
||||
)
|
||||
}
|
||||
|
||||
type goal struct {
|
||||
pos pixel.Vec
|
||||
radius float64
|
||||
step float64
|
||||
|
||||
counter float64
|
||||
cols [5]pixel.RGBA
|
||||
}
|
||||
|
||||
func (g *goal) update(dt float64) {
|
||||
g.counter += dt
|
||||
for g.counter > g.step {
|
||||
g.counter -= g.step
|
||||
for i := len(g.cols) - 2; i >= 0; i-- {
|
||||
g.cols[i+1] = g.cols[i]
|
||||
}
|
||||
g.cols[0] = randomNiceColor()
|
||||
}
|
||||
}
|
||||
|
||||
func (g *goal) draw(imd *imdraw.IMDraw) {
|
||||
for i := len(g.cols) - 1; i >= 0; i-- {
|
||||
imd.Color = g.cols[i]
|
||||
imd.Push(g.pos)
|
||||
imd.Circle(float64(i+1)*g.radius/float64(len(g.cols)), 0)
|
||||
}
|
||||
}
|
||||
|
||||
func randomNiceColor() pixel.RGBA {
|
||||
again:
|
||||
r := rand.Float64()
|
||||
g := rand.Float64()
|
||||
b := rand.Float64()
|
||||
len := math.Sqrt(r*r + g*g + b*b)
|
||||
if len == 0 {
|
||||
goto again
|
||||
}
|
||||
return pixel.RGB(r/len, g/len, b/len)
|
||||
}
|
||||
|
||||
func run() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
sheet, anims, err := loadAnimationSheet("sheet.png", "sheet.csv", 12)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Platformer",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
phys := &gopherPhys{
|
||||
gravity: -512,
|
||||
runSpeed: 64,
|
||||
jumpSpeed: 192,
|
||||
rect: pixel.R(-6, -7, 6, 7),
|
||||
}
|
||||
|
||||
anim := &gopherAnim{
|
||||
sheet: sheet,
|
||||
anims: anims,
|
||||
rate: 1.0 / 10,
|
||||
dir: +1,
|
||||
}
|
||||
|
||||
// hardcoded level
|
||||
platforms := []platform{
|
||||
{rect: pixel.R(-50, -34, 50, -32)},
|
||||
{rect: pixel.R(20, 0, 70, 2)},
|
||||
{rect: pixel.R(-100, 10, -50, 12)},
|
||||
{rect: pixel.R(120, -22, 140, -20)},
|
||||
{rect: pixel.R(120, -72, 140, -70)},
|
||||
{rect: pixel.R(120, -122, 140, -120)},
|
||||
{rect: pixel.R(-100, -152, 100, -150)},
|
||||
{rect: pixel.R(-150, -127, -140, -125)},
|
||||
{rect: pixel.R(-180, -97, -170, -95)},
|
||||
{rect: pixel.R(-150, -67, -140, -65)},
|
||||
{rect: pixel.R(-180, -37, -170, -35)},
|
||||
{rect: pixel.R(-150, -7, -140, -5)},
|
||||
}
|
||||
for i := range platforms {
|
||||
platforms[i].color = randomNiceColor()
|
||||
}
|
||||
|
||||
gol := &goal{
|
||||
pos: pixel.V(-75, 40),
|
||||
radius: 18,
|
||||
step: 1.0 / 7,
|
||||
}
|
||||
|
||||
canvas := pixelgl.NewCanvas(pixel.R(-160/2, -120/2, 160/2, 120/2))
|
||||
imd := imdraw.New(sheet)
|
||||
imd.Precision = 32
|
||||
|
||||
camPos := pixel.ZV
|
||||
|
||||
last := time.Now()
|
||||
for !win.Closed() {
|
||||
dt := time.Since(last).Seconds()
|
||||
last = time.Now()
|
||||
|
||||
// lerp the camera position towards the gopher
|
||||
camPos = pixel.Lerp(camPos, phys.rect.Center(), 1-math.Pow(1.0/128, dt))
|
||||
cam := pixel.IM.Moved(camPos.Scaled(-1))
|
||||
canvas.SetMatrix(cam)
|
||||
|
||||
// slow motion with tab
|
||||
if win.Pressed(pixelgl.KeyTab) {
|
||||
dt /= 8
|
||||
}
|
||||
|
||||
// restart the level on pressing enter
|
||||
if win.JustPressed(pixelgl.KeyEnter) {
|
||||
phys.rect = phys.rect.Moved(phys.rect.Center().Scaled(-1))
|
||||
phys.vel = pixel.ZV
|
||||
}
|
||||
|
||||
// control the gopher with keys
|
||||
ctrl := pixel.ZV
|
||||
if win.Pressed(pixelgl.KeyLeft) {
|
||||
ctrl.X--
|
||||
}
|
||||
if win.Pressed(pixelgl.KeyRight) {
|
||||
ctrl.X++
|
||||
}
|
||||
if win.JustPressed(pixelgl.KeyUp) {
|
||||
ctrl.Y = 1
|
||||
}
|
||||
|
||||
// update the physics and animation
|
||||
phys.update(dt, ctrl, platforms)
|
||||
gol.update(dt)
|
||||
anim.update(dt, phys)
|
||||
|
||||
// draw the scene to the canvas using IMDraw
|
||||
canvas.Clear(colornames.Black)
|
||||
imd.Clear()
|
||||
for _, p := range platforms {
|
||||
p.draw(imd)
|
||||
}
|
||||
gol.draw(imd)
|
||||
anim.draw(imd, phys)
|
||||
imd.Draw(canvas)
|
||||
|
||||
// stretch the canvas to the window
|
||||
win.Clear(colornames.White)
|
||||
win.SetMatrix(pixel.IM.Scaled(pixel.ZV,
|
||||
math.Min(
|
||||
win.Bounds().W()/canvas.Bounds().W(),
|
||||
win.Bounds().H()/canvas.Bounds().H(),
|
||||
),
|
||||
).Moved(win.Bounds().Center()))
|
||||
canvas.Draw(win, pixel.IM.Moved(canvas.Bounds().Center()))
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/platformer/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 8.3 KiB |
9
vendor/github.com/faiface/pixel/examples/platformer/sheet.csv
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
Front,0,0
|
||||
FrontBlink,1,1
|
||||
LookUp,2,2
|
||||
Left,3,7
|
||||
LeftRight,4,6
|
||||
LeftBlink,7,7
|
||||
Walk,8,15
|
||||
Run,16,23
|
||||
Jump,24,26
|
|
BIN
vendor/github.com/faiface/pixel/examples/platformer/sheet.png
generated
vendored
Normal file
After Width: | Height: | Size: 530 B |
8
vendor/github.com/faiface/pixel/examples/smoke/README.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Smoke
|
||||
|
||||
This example implements a smoke particle effect using sprites. It uses a spritesheet with a CSV
|
||||
description.
|
||||
|
||||
The art in the spritesheet comes from [Kenney](https://kenney.nl/).
|
||||
|
||||

|
25
vendor/github.com/faiface/pixel/examples/smoke/blackSmoke.csv
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
1543,1146,362,336
|
||||
396,0,398,364
|
||||
761,1535,386,342
|
||||
795,794,351,367
|
||||
394,1163,386,364
|
||||
1120,1163,377,348
|
||||
795,0,368,407
|
||||
0,0,395,397
|
||||
1164,0,378,415
|
||||
781,1163,338,360
|
||||
1543,0,372,370
|
||||
1148,1535,393,327
|
||||
387,1535,373,364
|
||||
396,365,371,388
|
||||
0,758,378,404
|
||||
379,758,378,371
|
||||
1543,774,360,371
|
||||
1543,1483,350,398
|
||||
0,398,382,359
|
||||
1164,416,356,382
|
||||
1164,799,369,350
|
||||
0,1535,386,394
|
||||
795,408,366,385
|
||||
1543,371,367,402
|
||||
0,1163,393,371
|
|
BIN
vendor/github.com/faiface/pixel/examples/smoke/blackSmoke.png
generated
vendored
Normal file
After Width: | Height: | Size: 3.0 MiB |
230
vendor/github.com/faiface/pixel/examples/smoke/main.go
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"encoding/csv"
|
||||
"image"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
_ "image/png"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
type particle struct {
|
||||
Sprite *pixel.Sprite
|
||||
Pos pixel.Vec
|
||||
Rot, Scale float64
|
||||
Mask pixel.RGBA
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
type particles struct {
|
||||
Generate func() *particle
|
||||
Update func(dt float64, p *particle) bool
|
||||
SpawnAvg, SpawnDist float64
|
||||
|
||||
parts list.List
|
||||
spawnTime float64
|
||||
}
|
||||
|
||||
func (p *particles) UpdateAll(dt float64) {
|
||||
p.spawnTime -= dt
|
||||
for p.spawnTime <= 0 {
|
||||
p.parts.PushFront(p.Generate())
|
||||
p.spawnTime += math.Max(0, p.SpawnAvg+rand.NormFloat64()*p.SpawnDist)
|
||||
}
|
||||
|
||||
for e := p.parts.Front(); e != nil; e = e.Next() {
|
||||
part := e.Value.(*particle)
|
||||
if !p.Update(dt, part) {
|
||||
defer p.parts.Remove(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *particles) DrawAll(t pixel.Target) {
|
||||
for e := p.parts.Front(); e != nil; e = e.Next() {
|
||||
part := e.Value.(*particle)
|
||||
|
||||
part.Sprite.DrawColorMask(
|
||||
t,
|
||||
pixel.IM.
|
||||
Scaled(pixel.ZV, part.Scale).
|
||||
Rotated(pixel.ZV, part.Rot).
|
||||
Moved(part.Pos),
|
||||
part.Mask,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type smokeData struct {
|
||||
Vel pixel.Vec
|
||||
Time float64
|
||||
Life float64
|
||||
}
|
||||
|
||||
type smokeSystem struct {
|
||||
Sheet pixel.Picture
|
||||
Rects []pixel.Rect
|
||||
Orig pixel.Vec
|
||||
|
||||
VelBasis []pixel.Vec
|
||||
VelDist float64
|
||||
|
||||
LifeAvg, LifeDist float64
|
||||
}
|
||||
|
||||
func (ss *smokeSystem) Generate() *particle {
|
||||
sd := new(smokeData)
|
||||
for _, base := range ss.VelBasis {
|
||||
c := math.Max(0, 1+rand.NormFloat64()*ss.VelDist)
|
||||
sd.Vel = sd.Vel.Add(base.Scaled(c))
|
||||
}
|
||||
sd.Vel = sd.Vel.Scaled(1 / float64(len(ss.VelBasis)))
|
||||
sd.Life = math.Max(0, ss.LifeAvg+rand.NormFloat64()*ss.LifeDist)
|
||||
|
||||
p := new(particle)
|
||||
p.Data = sd
|
||||
|
||||
p.Pos = ss.Orig
|
||||
p.Scale = 1
|
||||
p.Mask = pixel.Alpha(1)
|
||||
p.Sprite = pixel.NewSprite(ss.Sheet, ss.Rects[rand.Intn(len(ss.Rects))])
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (ss *smokeSystem) Update(dt float64, p *particle) bool {
|
||||
sd := p.Data.(*smokeData)
|
||||
sd.Time += dt
|
||||
|
||||
frac := sd.Time / sd.Life
|
||||
|
||||
p.Pos = p.Pos.Add(sd.Vel.Scaled(dt))
|
||||
p.Scale = 0.5 + frac*1.5
|
||||
|
||||
const (
|
||||
fadeIn = 0.2
|
||||
fadeOut = 0.4
|
||||
)
|
||||
if frac < fadeIn {
|
||||
p.Mask = pixel.Alpha(math.Pow(frac/fadeIn, 0.75))
|
||||
} else if frac >= fadeOut {
|
||||
p.Mask = pixel.Alpha(math.Pow(1-(frac-fadeOut)/(1-fadeOut), 1.5))
|
||||
} else {
|
||||
p.Mask = pixel.Alpha(1)
|
||||
}
|
||||
|
||||
return sd.Time < sd.Life
|
||||
}
|
||||
|
||||
func loadSpriteSheet(sheetPath, descriptionPath string) (sheet pixel.Picture, rects []pixel.Rect, err error) {
|
||||
sheetFile, err := os.Open(sheetPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer sheetFile.Close()
|
||||
|
||||
sheetImg, _, err := image.Decode(sheetFile)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sheet = pixel.PictureDataFromImage(sheetImg)
|
||||
|
||||
descriptionFile, err := os.Open(descriptionPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer descriptionFile.Close()
|
||||
|
||||
description := csv.NewReader(descriptionFile)
|
||||
for {
|
||||
record, err := description.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
x, _ := strconv.ParseFloat(record[0], 64)
|
||||
y, _ := strconv.ParseFloat(record[1], 64)
|
||||
w, _ := strconv.ParseFloat(record[2], 64)
|
||||
h, _ := strconv.ParseFloat(record[3], 64)
|
||||
|
||||
y = sheet.Bounds().H() - y - h
|
||||
|
||||
rects = append(rects, pixel.R(x, y, x+w, y+h))
|
||||
}
|
||||
|
||||
return sheet, rects, nil
|
||||
}
|
||||
|
||||
func run() {
|
||||
sheet, rects, err := loadSpriteSheet("blackSmoke.png", "blackSmoke.csv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Smoke",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
Resizable: true,
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ss := &smokeSystem{
|
||||
Rects: rects,
|
||||
Orig: pixel.ZV,
|
||||
VelBasis: []pixel.Vec{pixel.V(-100, 100), pixel.V(100, 100), pixel.V(0, 100)},
|
||||
VelDist: 0.1,
|
||||
LifeAvg: 7,
|
||||
LifeDist: 0.5,
|
||||
}
|
||||
|
||||
p := &particles{
|
||||
Generate: ss.Generate,
|
||||
Update: ss.Update,
|
||||
SpawnAvg: 0.3,
|
||||
SpawnDist: 0.1,
|
||||
}
|
||||
|
||||
batch := pixel.NewBatch(&pixel.TrianglesData{}, sheet)
|
||||
|
||||
last := time.Now()
|
||||
for !win.Closed() {
|
||||
dt := time.Since(last).Seconds()
|
||||
last = time.Now()
|
||||
|
||||
p.UpdateAll(dt)
|
||||
|
||||
win.Clear(colornames.Aliceblue)
|
||||
|
||||
orig := win.Bounds().Center()
|
||||
orig.Y -= win.Bounds().H() / 2
|
||||
win.SetMatrix(pixel.IM.Moved(orig))
|
||||
|
||||
batch.Clear()
|
||||
p.DrawAll(batch)
|
||||
batch.Draw(win)
|
||||
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/smoke/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 381 KiB |
13
vendor/github.com/faiface/pixel/examples/typewriter/README.md
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Typewriter
|
||||
|
||||
This example demonstrates text drawing and text input facilities by implementing a fancy typewriter
|
||||
with a red laser cursor. Screen shakes a bit when typing and some letters turn bold or italic
|
||||
randomly.
|
||||
|
||||
ASCII and Latin characters are supported here. Feel free to add support for more characters in the
|
||||
code (it's easy, but increases load time).
|
||||
|
||||
The seemingly buggy letters (one over another) in the screenshot are not bugs, but a result of using
|
||||
the typewriter backspace functionality.
|
||||
|
||||

|
317
vendor/github.com/faiface/pixel/examples/typewriter/main.go
generated
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"github.com/faiface/pixel/text"
|
||||
"github.com/golang/freetype/truetype"
|
||||
"golang.org/x/image/colornames"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/font/gofont/gobold"
|
||||
"golang.org/x/image/font/gofont/goitalic"
|
||||
"golang.org/x/image/font/gofont/goregular"
|
||||
)
|
||||
|
||||
func ttfFromBytesMust(b []byte, size float64) font.Face {
|
||||
ttf, err := truetype.Parse(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return truetype.NewFace(ttf, &truetype.Options{
|
||||
Size: size,
|
||||
GlyphCacheEntries: 1,
|
||||
})
|
||||
}
|
||||
|
||||
type typewriter struct {
|
||||
mu sync.Mutex
|
||||
|
||||
regular *text.Text
|
||||
bold *text.Text
|
||||
italic *text.Text
|
||||
|
||||
offset pixel.Vec
|
||||
position pixel.Vec
|
||||
move pixel.Vec
|
||||
}
|
||||
|
||||
func newTypewriter(c color.Color, regular, bold, italic *text.Atlas) *typewriter {
|
||||
tw := &typewriter{
|
||||
regular: text.New(pixel.ZV, regular),
|
||||
bold: text.New(pixel.ZV, bold),
|
||||
italic: text.New(pixel.ZV, italic),
|
||||
}
|
||||
tw.regular.Color = c
|
||||
tw.bold.Color = c
|
||||
tw.italic.Color = c
|
||||
return tw
|
||||
}
|
||||
|
||||
func (tw *typewriter) Ribbon(r rune) {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
|
||||
dice := rand.Intn(21)
|
||||
switch {
|
||||
case 0 <= dice && dice <= 18:
|
||||
tw.regular.WriteRune(r)
|
||||
case dice == 19:
|
||||
tw.bold.Dot = tw.regular.Dot
|
||||
tw.bold.WriteRune(r)
|
||||
tw.regular.Dot = tw.bold.Dot
|
||||
case dice == 20:
|
||||
tw.italic.Dot = tw.regular.Dot
|
||||
tw.italic.WriteRune(r)
|
||||
tw.regular.Dot = tw.italic.Dot
|
||||
}
|
||||
}
|
||||
|
||||
func (tw *typewriter) Back() {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
tw.regular.Dot = tw.regular.Dot.Sub(pixel.V(tw.regular.Atlas().Glyph(' ').Advance, 0))
|
||||
}
|
||||
|
||||
func (tw *typewriter) Offset(off pixel.Vec) {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
tw.offset = tw.offset.Add(off)
|
||||
}
|
||||
|
||||
func (tw *typewriter) Position() pixel.Vec {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
return tw.position
|
||||
}
|
||||
|
||||
func (tw *typewriter) Move(vel pixel.Vec) {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
tw.move = vel
|
||||
}
|
||||
|
||||
func (tw *typewriter) Dot() pixel.Vec {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
return tw.regular.Dot
|
||||
}
|
||||
|
||||
func (tw *typewriter) Update(dt float64) {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
tw.position = tw.position.Add(tw.move.Scaled(dt))
|
||||
}
|
||||
|
||||
func (tw *typewriter) Draw(t pixel.Target, m pixel.Matrix) {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
|
||||
m = pixel.IM.Moved(tw.position.Add(tw.offset)).Chained(m)
|
||||
tw.regular.Draw(t, m)
|
||||
tw.bold.Draw(t, m)
|
||||
tw.italic.Draw(t, m)
|
||||
}
|
||||
|
||||
func typeRune(tw *typewriter, r rune) {
|
||||
tw.Ribbon(r)
|
||||
if !unicode.IsSpace(r) {
|
||||
go shake(tw, 3, 17)
|
||||
}
|
||||
}
|
||||
|
||||
func back(tw *typewriter) {
|
||||
tw.Back()
|
||||
}
|
||||
|
||||
func shake(tw *typewriter, intensity, friction float64) {
|
||||
const (
|
||||
freq = 24
|
||||
dt = 1.0 / freq
|
||||
)
|
||||
ticker := time.NewTicker(time.Second / freq)
|
||||
defer ticker.Stop()
|
||||
|
||||
off := pixel.ZV
|
||||
|
||||
for range ticker.C {
|
||||
tw.Offset(off.Scaled(-1))
|
||||
|
||||
if intensity < 0.01*dt {
|
||||
break
|
||||
}
|
||||
|
||||
off = pixel.V((rand.Float64()-0.5)*intensity*2, (rand.Float64()-0.5)*intensity*2)
|
||||
intensity -= friction * dt
|
||||
|
||||
tw.Offset(off)
|
||||
}
|
||||
}
|
||||
|
||||
func scroll(tw *typewriter, intensity, speedUp float64) {
|
||||
const (
|
||||
freq = 120
|
||||
dt = 1.0 / freq
|
||||
)
|
||||
ticker := time.NewTicker(time.Second / freq)
|
||||
defer ticker.Stop()
|
||||
|
||||
speed := 0.0
|
||||
|
||||
for range ticker.C {
|
||||
if math.Abs(tw.Dot().Y+tw.Position().Y) < 0.01 {
|
||||
break
|
||||
}
|
||||
|
||||
targetSpeed := -(tw.Dot().Y + tw.Position().Y) * intensity
|
||||
if speed < targetSpeed {
|
||||
speed += speedUp * dt
|
||||
} else {
|
||||
speed = targetSpeed
|
||||
}
|
||||
|
||||
tw.Move(pixel.V(0, speed))
|
||||
}
|
||||
}
|
||||
|
||||
type dotlight struct {
|
||||
tw *typewriter
|
||||
color color.Color
|
||||
radius float64
|
||||
intensity float64
|
||||
acceleration float64
|
||||
maxSpeed float64
|
||||
|
||||
pos pixel.Vec
|
||||
vel pixel.Vec
|
||||
|
||||
imd *imdraw.IMDraw
|
||||
}
|
||||
|
||||
func newDotlight(tw *typewriter, c color.Color, radius, intensity, acceleration, maxSpeed float64) *dotlight {
|
||||
return &dotlight{
|
||||
tw: tw,
|
||||
color: c,
|
||||
radius: radius,
|
||||
intensity: intensity,
|
||||
acceleration: acceleration,
|
||||
maxSpeed: maxSpeed,
|
||||
pos: tw.Dot(),
|
||||
vel: pixel.ZV,
|
||||
imd: imdraw.New(nil),
|
||||
}
|
||||
}
|
||||
|
||||
func (dl *dotlight) Update(dt float64) {
|
||||
targetVel := dl.tw.Dot().Add(dl.tw.Position()).Sub(dl.pos).Scaled(dl.intensity)
|
||||
acc := targetVel.Sub(dl.vel).Scaled(dl.acceleration)
|
||||
dl.vel = dl.vel.Add(acc.Scaled(dt))
|
||||
if dl.vel.Len() > dl.maxSpeed {
|
||||
dl.vel = dl.vel.Unit().Scaled(dl.maxSpeed)
|
||||
}
|
||||
dl.pos = dl.pos.Add(dl.vel.Scaled(dt))
|
||||
}
|
||||
|
||||
func (dl *dotlight) Draw(t pixel.Target, m pixel.Matrix) {
|
||||
dl.imd.Clear()
|
||||
dl.imd.SetMatrix(m)
|
||||
dl.imd.Color = dl.color
|
||||
dl.imd.Push(dl.pos)
|
||||
dl.imd.Color = pixel.Alpha(0)
|
||||
for i := 0.0; i <= 32; i++ {
|
||||
angle := i * 2 * math.Pi / 32
|
||||
dl.imd.Push(dl.pos.Add(pixel.V(dl.radius, 0).Rotated(angle)))
|
||||
}
|
||||
dl.imd.Polygon(0)
|
||||
dl.imd.Draw(t)
|
||||
}
|
||||
|
||||
func run() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Typewriter",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
Resizable: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
win.SetSmooth(true)
|
||||
|
||||
var (
|
||||
regular = text.NewAtlas(
|
||||
ttfFromBytesMust(goregular.TTF, 42),
|
||||
text.ASCII, text.RangeTable(unicode.Latin),
|
||||
)
|
||||
bold = text.NewAtlas(
|
||||
ttfFromBytesMust(gobold.TTF, 42),
|
||||
text.ASCII, text.RangeTable(unicode.Latin),
|
||||
)
|
||||
italic = text.NewAtlas(
|
||||
ttfFromBytesMust(goitalic.TTF, 42),
|
||||
text.ASCII, text.RangeTable(unicode.Latin),
|
||||
)
|
||||
|
||||
bgColor = color.RGBA{
|
||||
R: 241,
|
||||
G: 241,
|
||||
B: 212,
|
||||
A: 255,
|
||||
}
|
||||
fgColor = color.RGBA{
|
||||
R: 0,
|
||||
G: 15,
|
||||
B: 85,
|
||||
A: 255,
|
||||
}
|
||||
|
||||
tw = newTypewriter(pixel.ToRGBA(fgColor).Scaled(0.9), regular, bold, italic)
|
||||
dl = newDotlight(tw, colornames.Red, 6, 30, 20, 1600)
|
||||
)
|
||||
|
||||
fps := time.Tick(time.Second / 120)
|
||||
last := time.Now()
|
||||
for !win.Closed() {
|
||||
for _, r := range win.Typed() {
|
||||
go typeRune(tw, r)
|
||||
}
|
||||
if win.JustPressed(pixelgl.KeyTab) || win.Repeated(pixelgl.KeyTab) {
|
||||
go typeRune(tw, '\t')
|
||||
}
|
||||
if win.JustPressed(pixelgl.KeyEnter) || win.Repeated(pixelgl.KeyEnter) {
|
||||
go typeRune(tw, '\n')
|
||||
go scroll(tw, 20, 6400)
|
||||
}
|
||||
if win.JustPressed(pixelgl.KeyBackspace) || win.Repeated(pixelgl.KeyBackspace) {
|
||||
go back(tw)
|
||||
}
|
||||
|
||||
dt := time.Since(last).Seconds()
|
||||
last = time.Now()
|
||||
|
||||
tw.Update(dt)
|
||||
dl.Update(dt)
|
||||
|
||||
win.Clear(bgColor)
|
||||
|
||||
m := pixel.IM.Moved(pixel.V(32, 32))
|
||||
tw.Draw(win, m)
|
||||
dl.Draw(win, m)
|
||||
|
||||
win.Update()
|
||||
<-fps
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/typewriter/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 156 KiB |
8
vendor/github.com/faiface/pixel/examples/xor/README.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Xor
|
||||
|
||||
This example demonstrates an unusual Porter-Duff composition method: Xor. (And the capability of
|
||||
drawing circles.)
|
||||
|
||||
Just thought it was cool.
|
||||
|
||||

|
76
vendor/github.com/faiface/pixel/examples/xor/main.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/faiface/pixel/imdraw"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
func run() {
|
||||
cfg := pixelgl.WindowConfig{
|
||||
Title: "Xor",
|
||||
Bounds: pixel.R(0, 0, 1024, 768),
|
||||
Resizable: true,
|
||||
VSync: true,
|
||||
}
|
||||
win, err := pixelgl.NewWindow(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
imd := imdraw.New(nil)
|
||||
|
||||
canvas := pixelgl.NewCanvas(win.Bounds())
|
||||
|
||||
start := time.Now()
|
||||
for !win.Closed() {
|
||||
// in case window got resized, we also need to resize our canvas
|
||||
canvas.SetBounds(win.Bounds())
|
||||
|
||||
offset := math.Sin(time.Since(start).Seconds()) * 300
|
||||
|
||||
// clear the canvas to be totally transparent and set the xor compose method
|
||||
canvas.Clear(pixel.Alpha(0))
|
||||
canvas.SetComposeMethod(pixel.ComposeXor)
|
||||
|
||||
// red circle
|
||||
imd.Clear()
|
||||
imd.Color = pixel.RGB(1, 0, 0)
|
||||
imd.Push(win.Bounds().Center().Add(pixel.V(-offset, 0)))
|
||||
imd.Circle(200, 0)
|
||||
imd.Draw(canvas)
|
||||
|
||||
// blue circle
|
||||
imd.Clear()
|
||||
imd.Color = pixel.RGB(0, 0, 1)
|
||||
imd.Push(win.Bounds().Center().Add(pixel.V(offset, 0)))
|
||||
imd.Circle(150, 0)
|
||||
imd.Draw(canvas)
|
||||
|
||||
// yellow circle
|
||||
imd.Clear()
|
||||
imd.Color = pixel.RGB(1, 1, 0)
|
||||
imd.Push(win.Bounds().Center().Add(pixel.V(0, -offset)))
|
||||
imd.Circle(100, 0)
|
||||
imd.Draw(canvas)
|
||||
|
||||
// magenta circle
|
||||
imd.Clear()
|
||||
imd.Color = pixel.RGB(1, 0, 1)
|
||||
imd.Push(win.Bounds().Center().Add(pixel.V(0, offset)))
|
||||
imd.Circle(50, 0)
|
||||
imd.Draw(canvas)
|
||||
|
||||
win.Clear(colornames.Green)
|
||||
canvas.Draw(win, pixel.IM.Moved(win.Bounds().Center()))
|
||||
win.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pixelgl.Run(run)
|
||||
}
|
BIN
vendor/github.com/faiface/pixel/examples/xor/screenshot.png
generated
vendored
Normal file
After Width: | Height: | Size: 10 KiB |
248
vendor/github.com/faiface/pixel/text/atlas.go
generated
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
package text
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/draw"
|
||||
"sort"
|
||||
"unicode"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
// Atlas7x13 is an Atlas using basicfont.Face7x13 with the ASCII rune set
|
||||
var Atlas7x13 *Atlas
|
||||
|
||||
// Glyph describes one glyph in an Atlas.
|
||||
type Glyph struct {
|
||||
Dot pixel.Vec
|
||||
Frame pixel.Rect
|
||||
Advance float64
|
||||
}
|
||||
|
||||
// Atlas is a set of pre-drawn glyphs of a fixed set of runes. This allows for efficient text drawing.
|
||||
type Atlas struct {
|
||||
face font.Face
|
||||
pic pixel.Picture
|
||||
mapping map[rune]Glyph
|
||||
ascent float64
|
||||
descent float64
|
||||
lineHeight float64
|
||||
}
|
||||
|
||||
// NewAtlas creates a new Atlas containing glyphs of the union of the given sets of runes (plus
|
||||
// unicode.ReplacementChar) from the given font face.
|
||||
//
|
||||
// Creating an Atlas is rather expensive, do not create a new Atlas each frame.
|
||||
//
|
||||
// Do not destroy or close the font.Face after creating the Atlas. Atlas still uses it.
|
||||
func NewAtlas(face font.Face, runeSets ...[]rune) *Atlas {
|
||||
seen := make(map[rune]bool)
|
||||
runes := []rune{unicode.ReplacementChar}
|
||||
for _, set := range runeSets {
|
||||
for _, r := range set {
|
||||
if !seen[r] {
|
||||
runes = append(runes, r)
|
||||
seen[r] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixedMapping, fixedBounds := makeSquareMapping(face, runes, fixed.I(2))
|
||||
|
||||
atlasImg := image.NewRGBA(image.Rect(
|
||||
fixedBounds.Min.X.Floor(),
|
||||
fixedBounds.Min.Y.Floor(),
|
||||
fixedBounds.Max.X.Ceil(),
|
||||
fixedBounds.Max.Y.Ceil(),
|
||||
))
|
||||
|
||||
for r, fg := range fixedMapping {
|
||||
dr, mask, maskp, _, _ := face.Glyph(fg.dot, r)
|
||||
draw.Draw(atlasImg, dr, mask, maskp, draw.Src)
|
||||
}
|
||||
|
||||
bounds := pixel.R(
|
||||
i2f(fixedBounds.Min.X),
|
||||
i2f(fixedBounds.Min.Y),
|
||||
i2f(fixedBounds.Max.X),
|
||||
i2f(fixedBounds.Max.Y),
|
||||
)
|
||||
|
||||
mapping := make(map[rune]Glyph)
|
||||
for r, fg := range fixedMapping {
|
||||
mapping[r] = Glyph{
|
||||
Dot: pixel.V(
|
||||
i2f(fg.dot.X),
|
||||
bounds.Max.Y-(i2f(fg.dot.Y)-bounds.Min.Y),
|
||||
),
|
||||
Frame: pixel.R(
|
||||
i2f(fg.frame.Min.X),
|
||||
bounds.Max.Y-(i2f(fg.frame.Min.Y)-bounds.Min.Y),
|
||||
i2f(fg.frame.Max.X),
|
||||
bounds.Max.Y-(i2f(fg.frame.Max.Y)-bounds.Min.Y),
|
||||
).Norm(),
|
||||
Advance: i2f(fg.advance),
|
||||
}
|
||||
}
|
||||
|
||||
return &Atlas{
|
||||
face: face,
|
||||
pic: pixel.PictureDataFromImage(atlasImg),
|
||||
mapping: mapping,
|
||||
ascent: i2f(face.Metrics().Ascent),
|
||||
descent: i2f(face.Metrics().Descent),
|
||||
lineHeight: i2f(face.Metrics().Height),
|
||||
}
|
||||
}
|
||||
|
||||
// Picture returns the underlying Picture containing an arrangement of all the glyphs contained
|
||||
// within the Atlas.
|
||||
func (a *Atlas) Picture() pixel.Picture {
|
||||
return a.pic
|
||||
}
|
||||
|
||||
// Contains reports wheter r in contained within the Atlas.
|
||||
func (a *Atlas) Contains(r rune) bool {
|
||||
_, ok := a.mapping[r]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Glyph returns the description of r within the Atlas.
|
||||
func (a *Atlas) Glyph(r rune) Glyph {
|
||||
return a.mapping[r]
|
||||
}
|
||||
|
||||
// Kern returns the kerning distance between runes r0 and r1. Positive distance means that the
|
||||
// glyphs should be further apart.
|
||||
func (a *Atlas) Kern(r0, r1 rune) float64 {
|
||||
return i2f(a.face.Kern(r0, r1))
|
||||
}
|
||||
|
||||
// Ascent returns the distance from the top of the line to the baseline.
|
||||
func (a *Atlas) Ascent() float64 {
|
||||
return a.ascent
|
||||
}
|
||||
|
||||
// Descent returns the distance from the baseline to the bottom of the line.
|
||||
func (a *Atlas) Descent() float64 {
|
||||
return a.descent
|
||||
}
|
||||
|
||||
// LineHeight returns the recommended vertical distance between two lines of text.
|
||||
func (a *Atlas) LineHeight() float64 {
|
||||
return a.lineHeight
|
||||
}
|
||||
|
||||
// DrawRune returns parameters necessary for drawing a rune glyph.
|
||||
//
|
||||
// Rect is a rectangle where the glyph should be positioned. Frame is the glyph frame inside the
|
||||
// Atlas's Picture. NewDot is the new position of the dot.
|
||||
func (a *Atlas) DrawRune(prevR, r rune, dot pixel.Vec) (rect, frame, bounds pixel.Rect, newDot pixel.Vec) {
|
||||
if !a.Contains(r) {
|
||||
r = unicode.ReplacementChar
|
||||
}
|
||||
if !a.Contains(unicode.ReplacementChar) {
|
||||
return pixel.Rect{}, pixel.Rect{}, pixel.Rect{}, dot
|
||||
}
|
||||
if !a.Contains(prevR) {
|
||||
prevR = unicode.ReplacementChar
|
||||
}
|
||||
|
||||
if prevR >= 0 {
|
||||
dot.X += a.Kern(prevR, r)
|
||||
}
|
||||
|
||||
glyph := a.Glyph(r)
|
||||
|
||||
rect = glyph.Frame.Moved(dot.Sub(glyph.Dot))
|
||||
bounds = rect
|
||||
|
||||
if bounds.W()*bounds.H() != 0 {
|
||||
bounds = pixel.R(
|
||||
bounds.Min.X,
|
||||
dot.Y-a.Descent(),
|
||||
bounds.Max.X,
|
||||
dot.Y+a.Ascent(),
|
||||
)
|
||||
}
|
||||
|
||||
dot.X += glyph.Advance
|
||||
|
||||
return rect, glyph.Frame, bounds, dot
|
||||
}
|
||||
|
||||
type fixedGlyph struct {
|
||||
dot fixed.Point26_6
|
||||
frame fixed.Rectangle26_6
|
||||
advance fixed.Int26_6
|
||||
}
|
||||
|
||||
// makeSquareMapping finds an optimal glyph arrangement of the given runes, so that their common
|
||||
// bounding box is as square as possible.
|
||||
func makeSquareMapping(face font.Face, runes []rune, padding fixed.Int26_6) (map[rune]fixedGlyph, fixed.Rectangle26_6) {
|
||||
width := sort.Search(int(fixed.I(1024*1024)), func(i int) bool {
|
||||
width := fixed.Int26_6(i)
|
||||
_, bounds := makeMapping(face, runes, padding, width)
|
||||
return bounds.Max.X-bounds.Min.X >= bounds.Max.Y-bounds.Min.Y
|
||||
})
|
||||
return makeMapping(face, runes, padding, fixed.Int26_6(width))
|
||||
}
|
||||
|
||||
// makeMapping arranges glyphs of the given runes into rows in such a way, that no glyph is located
|
||||
// fully to the right of the specified width. Specifically, it places glyphs in a row one by one and
|
||||
// once it reaches the specified width, it starts a new row.
|
||||
func makeMapping(face font.Face, runes []rune, padding, width fixed.Int26_6) (map[rune]fixedGlyph, fixed.Rectangle26_6) {
|
||||
mapping := make(map[rune]fixedGlyph)
|
||||
bounds := fixed.Rectangle26_6{}
|
||||
|
||||
dot := fixed.P(0, 0)
|
||||
|
||||
for _, r := range runes {
|
||||
b, advance, ok := face.GlyphBounds(r)
|
||||
if !ok {
|
||||
fmt.Println(r)
|
||||
continue
|
||||
}
|
||||
|
||||
// this is important for drawing, artifacts arise otherwise
|
||||
frame := fixed.Rectangle26_6{
|
||||
Min: fixed.P(b.Min.X.Floor(), b.Min.Y.Floor()),
|
||||
Max: fixed.P(b.Max.X.Ceil(), b.Max.Y.Ceil()),
|
||||
}
|
||||
|
||||
dot.X -= frame.Min.X
|
||||
frame = frame.Add(dot)
|
||||
|
||||
mapping[r] = fixedGlyph{
|
||||
dot: dot,
|
||||
frame: frame,
|
||||
advance: advance,
|
||||
}
|
||||
bounds = bounds.Union(frame)
|
||||
|
||||
dot.X = frame.Max.X
|
||||
|
||||
// padding + align to integer
|
||||
dot.X += padding
|
||||
dot.X = fixed.I(dot.X.Ceil())
|
||||
|
||||
// width exceeded, new row
|
||||
if frame.Max.X >= width {
|
||||
dot.X = 0
|
||||
dot.Y += face.Metrics().Ascent + face.Metrics().Descent
|
||||
|
||||
// padding + align to integer
|
||||
dot.Y += padding
|
||||
dot.Y = fixed.I(dot.Y.Ceil())
|
||||
}
|
||||
}
|
||||
|
||||
return mapping, bounds
|
||||
}
|
||||
|
||||
func i2f(i fixed.Int26_6) float64 {
|
||||
return float64(i) / (1 << 6)
|
||||
}
|
2
vendor/github.com/faiface/pixel/text/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package text implements efficient text drawing for the Pixel library.
|
||||
package text
|
347
vendor/github.com/faiface/pixel/text/text.go
generated
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
package text
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
"golang.org/x/image/font/basicfont"
|
||||
)
|
||||
|
||||
// ASCII is a set of all ASCII runes. These runes are codepoints from 32 to 127 inclusive.
|
||||
var ASCII []rune
|
||||
|
||||
func init() {
|
||||
ASCII = make([]rune, unicode.MaxASCII-32)
|
||||
for i := range ASCII {
|
||||
ASCII[i] = rune(32 + i)
|
||||
}
|
||||
Atlas7x13 = NewAtlas(basicfont.Face7x13, ASCII)
|
||||
}
|
||||
|
||||
// RangeTable takes a *unicode.RangeTable and generates a set of runes contained within that
|
||||
// RangeTable.
|
||||
func RangeTable(table *unicode.RangeTable) []rune {
|
||||
var runes []rune
|
||||
for _, rng := range table.R16 {
|
||||
for r := rng.Lo; r <= rng.Hi; r += rng.Stride {
|
||||
runes = append(runes, rune(r))
|
||||
}
|
||||
}
|
||||
for _, rng := range table.R32 {
|
||||
for r := rng.Lo; r <= rng.Hi; r += rng.Stride {
|
||||
runes = append(runes, rune(r))
|
||||
}
|
||||
}
|
||||
return runes
|
||||
}
|
||||
|
||||
// Text allows for effiecient and convenient text drawing.
|
||||
//
|
||||
// To create a Text object, use the New constructor:
|
||||
// txt := text.New(pixel.ZV, text.NewAtlas(face, text.ASCII))
|
||||
//
|
||||
// As suggested by the constructor, a Text object is always associated with one font face and a
|
||||
// fixed set of runes. For example, the Text we created above can draw text using the font face
|
||||
// contained in the face variable and is capable of drawing ASCII characters.
|
||||
//
|
||||
// Here we create a Text object which can draw ASCII and Katakana characters:
|
||||
// txt := text.New(0, text.NewAtlas(face, text.ASCII, text.RangeTable(unicode.Katakana)))
|
||||
//
|
||||
// Similarly to IMDraw, Text functions as a buffer. It implements io.Writer interface, so writing
|
||||
// text to it is really simple:
|
||||
// fmt.Print(txt, "Hello, world!")
|
||||
//
|
||||
// Newlines, tabs and carriage returns are supported.
|
||||
//
|
||||
// Finally, if we want the written text to show up on some other Target, we can draw it:
|
||||
// txt.Draw(target)
|
||||
//
|
||||
// Text exports two important fields: Orig and Dot. Dot is the position where the next character
|
||||
// will be written. Dot is automatically moved when writing to a Text object, but you can also
|
||||
// manipulate it manually. Orig specifies the text origin, usually the top-left dot position. Dot is
|
||||
// always aligned to Orig when writing newlines. The Clear method resets the Dot to Orig.
|
||||
type Text struct {
|
||||
// Orig specifies the text origin, usually the top-left dot position. Dot is always aligned
|
||||
// to Orig when writing newlines.
|
||||
Orig pixel.Vec
|
||||
|
||||
// Dot is the position where the next character will be written. Dot is automatically moved
|
||||
// when writing to a Text object, but you can also manipulate it manually
|
||||
Dot pixel.Vec
|
||||
|
||||
// Color is the color of the text that is to be written. Defaults to white.
|
||||
Color color.Color
|
||||
|
||||
// LineHeight is the vertical distance between two lines of text.
|
||||
//
|
||||
// Example:
|
||||
// txt.LineHeight = 1.5 * txt.Atlas().LineHeight()
|
||||
LineHeight float64
|
||||
|
||||
// TabWidth is the horizontal tab width. Tab characters will align to the multiples of this
|
||||
// width.
|
||||
//
|
||||
// Example:
|
||||
// txt.TabWidth = 8 * txt.Atlas().Glyph(' ').Advance
|
||||
TabWidth float64
|
||||
|
||||
atlas *Atlas
|
||||
|
||||
buf []byte
|
||||
prevR rune
|
||||
bounds pixel.Rect
|
||||
glyph pixel.TrianglesData
|
||||
tris pixel.TrianglesData
|
||||
|
||||
mat pixel.Matrix
|
||||
col pixel.RGBA
|
||||
trans pixel.TrianglesData
|
||||
transD pixel.Drawer
|
||||
dirty bool
|
||||
}
|
||||
|
||||
// New creates a new Text capable of drawing runes contained in the provided Atlas. Orig and Dot
|
||||
// will be initially set to orig.
|
||||
//
|
||||
// Here we create a Text capable of drawing ASCII characters using the Go Regular font.
|
||||
// ttf, err := truetype.Parse(goregular.TTF)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// face := truetype.NewFace(ttf, &truetype.Options{
|
||||
// Size: 14,
|
||||
// })
|
||||
// txt := text.New(orig, text.NewAtlas(face, text.ASCII))
|
||||
func New(orig pixel.Vec, atlas *Atlas) *Text {
|
||||
txt := &Text{
|
||||
Orig: orig,
|
||||
Dot: orig,
|
||||
Color: pixel.Alpha(1),
|
||||
LineHeight: atlas.LineHeight(),
|
||||
TabWidth: atlas.Glyph(' ').Advance * 4,
|
||||
atlas: atlas,
|
||||
mat: pixel.IM,
|
||||
col: pixel.Alpha(1),
|
||||
}
|
||||
|
||||
txt.glyph.SetLen(6)
|
||||
for i := range txt.glyph {
|
||||
txt.glyph[i].Color = pixel.Alpha(1)
|
||||
txt.glyph[i].Intensity = 1
|
||||
}
|
||||
|
||||
txt.transD.Picture = txt.atlas.pic
|
||||
txt.transD.Triangles = &txt.trans
|
||||
|
||||
txt.Clear()
|
||||
|
||||
return txt
|
||||
}
|
||||
|
||||
// Atlas returns the underlying Text's Atlas containing all of the pre-drawn glyphs. The Atlas is
|
||||
// also useful for getting values such as the recommended line height.
|
||||
func (txt *Text) Atlas() *Atlas {
|
||||
return txt.atlas
|
||||
}
|
||||
|
||||
// Bounds returns the bounding box of the text currently written to the Text excluding whitespace.
|
||||
//
|
||||
// If the Text is empty, a zero rectangle is returned.
|
||||
func (txt *Text) Bounds() pixel.Rect {
|
||||
return txt.bounds
|
||||
}
|
||||
|
||||
// BoundsOf returns the bounding box of s if it was to be written to the Text right now.
|
||||
func (txt *Text) BoundsOf(s string) pixel.Rect {
|
||||
dot := txt.Dot
|
||||
prevR := txt.prevR
|
||||
bounds := pixel.Rect{}
|
||||
|
||||
for _, r := range s {
|
||||
var control bool
|
||||
dot, control = txt.controlRune(r, dot)
|
||||
if control {
|
||||
continue
|
||||
}
|
||||
|
||||
var b pixel.Rect
|
||||
_, _, b, dot = txt.Atlas().DrawRune(prevR, r, dot)
|
||||
|
||||
if bounds.W()*bounds.H() == 0 {
|
||||
bounds = b
|
||||
} else {
|
||||
bounds = bounds.Union(b)
|
||||
}
|
||||
|
||||
prevR = r
|
||||
}
|
||||
|
||||
return bounds
|
||||
}
|
||||
|
||||
// Clear removes all written text from the Text. The Dot field is reset to Orig.
|
||||
func (txt *Text) Clear() {
|
||||
txt.prevR = -1
|
||||
txt.bounds = pixel.Rect{}
|
||||
txt.tris.SetLen(0)
|
||||
txt.dirty = true
|
||||
txt.Dot = txt.Orig
|
||||
}
|
||||
|
||||
// Write writes a slice of bytes to the Text. This method never fails, always returns len(p), nil.
|
||||
func (txt *Text) Write(p []byte) (n int, err error) {
|
||||
txt.buf = append(txt.buf, p...)
|
||||
txt.drawBuf()
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// WriteString writes a string to the Text. This method never fails, always returns len(s), nil.
|
||||
func (txt *Text) WriteString(s string) (n int, err error) {
|
||||
txt.buf = append(txt.buf, s...)
|
||||
txt.drawBuf()
|
||||
return len(s), nil
|
||||
}
|
||||
|
||||
// WriteByte writes a byte to the Text. This method never fails, always returns nil.
|
||||
//
|
||||
// Writing a multi-byte rune byte-by-byte is perfectly supported.
|
||||
func (txt *Text) WriteByte(c byte) error {
|
||||
txt.buf = append(txt.buf, c)
|
||||
txt.drawBuf()
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteRune writes a rune to the Text. This method never fails, always returns utf8.RuneLen(r), nil.
|
||||
func (txt *Text) WriteRune(r rune) (n int, err error) {
|
||||
var b [4]byte
|
||||
n = utf8.EncodeRune(b[:], r)
|
||||
txt.buf = append(txt.buf, b[:n]...)
|
||||
txt.drawBuf()
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Draw draws all text written to the Text to the provided Target. The text is transformed by the
|
||||
// provided Matrix.
|
||||
//
|
||||
// This method is equivalent to calling DrawColorMask with nil color mask.
|
||||
//
|
||||
// If there's a lot of text written to the Text, changing a matrix or a color mask often might hurt
|
||||
// performance. Consider using your Target's SetMatrix or SetColorMask methods if available.
|
||||
func (txt *Text) Draw(t pixel.Target, matrix pixel.Matrix) {
|
||||
txt.DrawColorMask(t, matrix, nil)
|
||||
}
|
||||
|
||||
// DrawColorMask draws all text written to the Text to the provided Target. The text is transformed
|
||||
// by the provided Matrix and masked by the provided color mask.
|
||||
//
|
||||
// If there's a lot of text written to the Text, changing a matrix or a color mask often might hurt
|
||||
// performance. Consider using your Target's SetMatrix or SetColorMask methods if available.
|
||||
func (txt *Text) DrawColorMask(t pixel.Target, matrix pixel.Matrix, mask color.Color) {
|
||||
if matrix != txt.mat {
|
||||
txt.mat = matrix
|
||||
txt.dirty = true
|
||||
}
|
||||
if mask == nil {
|
||||
mask = pixel.Alpha(1)
|
||||
}
|
||||
rgba := pixel.ToRGBA(mask)
|
||||
if rgba != txt.col {
|
||||
txt.col = rgba
|
||||
txt.dirty = true
|
||||
}
|
||||
|
||||
if txt.dirty {
|
||||
txt.trans.SetLen(txt.tris.Len())
|
||||
txt.trans.Update(&txt.tris)
|
||||
|
||||
for i := range txt.trans {
|
||||
txt.trans[i].Position = txt.mat.Project(txt.trans[i].Position)
|
||||
txt.trans[i].Color = txt.trans[i].Color.Mul(txt.col)
|
||||
}
|
||||
|
||||
txt.transD.Dirty()
|
||||
txt.dirty = false
|
||||
}
|
||||
|
||||
txt.transD.Draw(t)
|
||||
}
|
||||
|
||||
// controlRune checks if r is a control rune (newline, tab, ...). If it is, a new dot position and
|
||||
// true is returned. If r is not a control rune, the original dot and false is returned.
|
||||
func (txt *Text) controlRune(r rune, dot pixel.Vec) (newDot pixel.Vec, control bool) {
|
||||
switch r {
|
||||
case '\n':
|
||||
dot.X = txt.Orig.X
|
||||
dot.Y -= txt.LineHeight
|
||||
case '\r':
|
||||
dot.X = txt.Orig.X
|
||||
case '\t':
|
||||
rem := math.Mod(dot.X-txt.Orig.X, txt.TabWidth)
|
||||
rem = math.Mod(rem, rem+txt.TabWidth)
|
||||
if rem == 0 {
|
||||
rem = txt.TabWidth
|
||||
}
|
||||
dot.X += rem
|
||||
default:
|
||||
return dot, false
|
||||
}
|
||||
return dot, true
|
||||
}
|
||||
|
||||
func (txt *Text) drawBuf() {
|
||||
if !utf8.FullRune(txt.buf) {
|
||||
return
|
||||
}
|
||||
|
||||
rgba := pixel.ToRGBA(txt.Color)
|
||||
for i := range txt.glyph {
|
||||
txt.glyph[i].Color = rgba
|
||||
}
|
||||
|
||||
for utf8.FullRune(txt.buf) {
|
||||
r, size := utf8.DecodeRune(txt.buf)
|
||||
txt.buf = txt.buf[size:]
|
||||
|
||||
var control bool
|
||||
txt.Dot, control = txt.controlRune(r, txt.Dot)
|
||||
if control {
|
||||
continue
|
||||
}
|
||||
|
||||
var rect, frame, bounds pixel.Rect
|
||||
rect, frame, bounds, txt.Dot = txt.Atlas().DrawRune(txt.prevR, r, txt.Dot)
|
||||
|
||||
txt.prevR = r
|
||||
|
||||
rv := [...]pixel.Vec{
|
||||
{X: rect.Min.X, Y: rect.Min.Y},
|
||||
{X: rect.Max.X, Y: rect.Min.Y},
|
||||
{X: rect.Max.X, Y: rect.Max.Y},
|
||||
{X: rect.Min.X, Y: rect.Max.Y},
|
||||
}
|
||||
|
||||
fv := [...]pixel.Vec{
|
||||
{X: frame.Min.X, Y: frame.Min.Y},
|
||||
{X: frame.Max.X, Y: frame.Min.Y},
|
||||
{X: frame.Max.X, Y: frame.Max.Y},
|
||||
{X: frame.Min.X, Y: frame.Max.Y},
|
||||
}
|
||||
|
||||
for i, j := range [...]int{0, 1, 2, 0, 2, 3} {
|
||||
txt.glyph[i].Position = rv[j]
|
||||
txt.glyph[i].Picture = fv[j]
|
||||
}
|
||||
|
||||
txt.tris = append(txt.tris, txt.glyph...)
|
||||
txt.dirty = true
|
||||
|
||||
if txt.bounds.W()*txt.bounds.H() == 0 {
|
||||
txt.bounds = bounds
|
||||
} else {
|
||||
txt.bounds = txt.bounds.Union(bounds)
|
||||
}
|
||||
}
|
||||
}
|
21
vendor/github.com/go-gl/gl/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
sudo: false
|
||||
addons:
|
||||
apt_packages:
|
||||
- libgles2-mesa-dev
|
||||
language: go
|
||||
go:
|
||||
- 1.8.x
|
||||
- 1.4.x
|
||||
- master
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: master
|
||||
fast_finish: true
|
||||
install:
|
||||
- # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
|
||||
script:
|
||||
- go get -t -v ./...
|
||||
- diff -u <(echo -n) <(gofmt -d -s .)
|
||||
- # vet is reporting "possible misuse of unsafe.Pointer", need to fix that.
|
||||
- # go tool vet .
|
||||
- go test -v -race ./...
|
65
vendor/github.com/go-gl/gl/README.md
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
# gl [](https://travis-ci.org/go-gl/gl) [](https://godoc.org/github.com/go-gl/gl)
|
||||
|
||||
This repository holds Go bindings to various OpenGL versions. They are auto-generated using [Glow](https://github.com/go-gl/glow).
|
||||
|
||||
Features:
|
||||
- Go functions that mirror the C specification using Go types.
|
||||
- Support for multiple OpenGL APIs (GL/GLES/EGL/WGL/GLX/EGL), versions, and profiles.
|
||||
- Support for extensions (including debug callbacks).
|
||||
|
||||
Requirements:
|
||||
- A cgo compiler (typically gcc).
|
||||
- On Ubuntu/Debian-based systems, the `libgl1-mesa-dev` package.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Use `go get -u` to download and install the prebuilt packages. The prebuilt packages support OpenGL versions 2.1, 3.1, 3.2, 3.3, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6 across both the core and compatibility profiles and include all extensions. Pick whichever one(s) you need:
|
||||
|
||||
go get -u github.com/go-gl/gl/v{3.2,3.3,4.1,4.2,4.3,4.4,4.5,4.6}-{core,compatibility}/gl
|
||||
go get -u github.com/go-gl/gl/v3.1/gles2
|
||||
go get -u github.com/go-gl/gl/v2.1/gl
|
||||
|
||||
Once the bindings are installed you can use them with the appropriate import statements.
|
||||
|
||||
```Go
|
||||
import "github.com/go-gl/gl/v3.3-core/gl"
|
||||
|
||||
func main() {
|
||||
window := ... // Open a window.
|
||||
window.MakeContextCurrent()
|
||||
|
||||
// Important! Call gl.Init only under the presence of an active OpenGL context,
|
||||
// i.e., after MakeContextCurrent.
|
||||
if err := gl.Init(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `gl` package contains the OpenGL functions and enumeration values for the imported version. It also contains helper functions for working with the API. Of note is `gl.Ptr` which takes a Go array or slice or pointer and returns a corresponding `uintptr` to use with functions expecting data pointers. Also of note is `gl.Str` which takes a null-terminated Go string and returns a corresponding `*int8` to use with functions expecting character pointers.
|
||||
|
||||
A note about threading and goroutines. The bindings do not expose a mechanism to make an OpenGL context current on a different thread so you must restrict your usage to the thread on which you called `gl.Init()`. To do so you should use [LockOSThread](https://code.google.com/p/go-wiki/wiki/LockOSThread).
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Examples illustrating how to use the bindings are available in the [example](https://github.com/go-gl/example) repo. There are examples for [OpenGL 4.1 core](https://github.com/go-gl/example/tree/master/gl41core-cube) and [OpenGL 2.1](https://github.com/go-gl/example/tree/master/gl21-cube).
|
||||
|
||||
Function Loading
|
||||
----------------
|
||||
|
||||
The `procaddr` package contains platform-specific functions for [loading OpenGL functions](https://www.opengl.org/wiki/Load_OpenGL_Functions). Calling `gl.Init()` uses the `auto` subpackage to automatically select an appropriate implementation based on the build environment. If you want to select a specific implementation you can use the `noauto` build tag and the `gl.InitWithProcAddrFunc` initialization function.
|
||||
|
||||
Generating
|
||||
----------
|
||||
|
||||
These gl bindings are generated using the [Glow](https://github.com/go-gl/glow) generator. Only developers of this repository need to do this step.
|
||||
|
||||
It is required to have `glow` source in the same Go workspace (since relative paths are used) and the `glow` binary should be in your `$PATH`. Doable with `go get -u github.com/go-gl/glow` if your `$GOPATH/bin` is in your `$PATH`.
|
||||
|
||||
```bash
|
||||
go generate -tags=gen github.com/go-gl/gl
|
||||
```
|
||||
|
||||
More information about these bindings can be found in the [Glow repository](https://github.com/go-gl/glow).
|
109
vendor/github.com/go-gl/gl/all-core/gl/conversions.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
// Ptr takes a slice or pointer (to a singular scalar value or the first
|
||||
// element of an array or slice) and returns its GL-compatible address.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var data []uint8
|
||||
// ...
|
||||
// gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
|
||||
func Ptr(data interface{}) unsafe.Pointer {
|
||||
if data == nil {
|
||||
return unsafe.Pointer(nil)
|
||||
}
|
||||
var addr unsafe.Pointer
|
||||
v := reflect.ValueOf(data)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
switch e.Kind() {
|
||||
case
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
addr = unsafe.Pointer(e.UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
addr = unsafe.Pointer(v.Pointer())
|
||||
case reflect.Slice:
|
||||
addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// PtrOffset takes a pointer offset and returns a GL-compatible pointer.
|
||||
// Useful for functions such as glVertexAttribPointer that take pointer
|
||||
// parameters indicating an offset rather than an absolute memory address.
|
||||
func PtrOffset(offset int) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(offset))
|
||||
}
|
||||
|
||||
// Str takes a null-terminated Go string and returns its GL-compatible address.
|
||||
// This function reaches into Go string storage in an unsafe way so the caller
|
||||
// must ensure the string is not garbage collected.
|
||||
func Str(str string) *uint8 {
|
||||
if !strings.HasSuffix(str, "\x00") {
|
||||
panic("str argument missing null terminator: " + str)
|
||||
}
|
||||
header := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
return (*uint8)(unsafe.Pointer(header.Data))
|
||||
}
|
||||
|
||||
// GoStr takes a null-terminated string returned by OpenGL and constructs a
|
||||
// corresponding Go string.
|
||||
func GoStr(cstr *uint8) string {
|
||||
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
|
||||
}
|
||||
|
||||
// Strs takes a list of Go strings (with or without null-termination) and
|
||||
// returns their C counterpart.
|
||||
//
|
||||
// The returned free function must be called once you are done using the strings
|
||||
// in order to free the memory.
|
||||
//
|
||||
// If no strings are provided as a parameter this function will panic.
|
||||
func Strs(strs ...string) (cstrs **uint8, free func()) {
|
||||
if len(strs) == 0 {
|
||||
panic("Strs: expected at least 1 string")
|
||||
}
|
||||
|
||||
// Allocate a contiguous array large enough to hold all the strings' contents.
|
||||
n := 0
|
||||
for i := range strs {
|
||||
n += len(strs[i])
|
||||
}
|
||||
data := C.malloc(C.size_t(n))
|
||||
|
||||
// Copy all the strings into data.
|
||||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(data),
|
||||
Len: n,
|
||||
Cap: n,
|
||||
}))
|
||||
css := make([]*uint8, len(strs)) // Populated with pointers to each string.
|
||||
offset := 0
|
||||
for i := range strs {
|
||||
copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location.
|
||||
css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it.
|
||||
offset += len(strs[i])
|
||||
}
|
||||
|
||||
return (**uint8)(&css[0]), func() { C.free(data) }
|
||||
}
|
31
vendor/github.com/go-gl/gl/all-core/gl/debug.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type DebugProc func(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message string,
|
||||
userParam unsafe.Pointer)
|
||||
|
||||
var userDebugCallback DebugProc
|
||||
|
||||
//export glowDebugCallback_glcoreall
|
||||
func glowDebugCallback_glcoreall(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message *uint8,
|
||||
userParam unsafe.Pointer) {
|
||||
if userDebugCallback != nil {
|
||||
userDebugCallback(source, gltype, id, severity, length, GoStr(message), userParam)
|
||||
}
|
||||
}
|
12623
vendor/github.com/go-gl/gl/all-core/gl/package.go
generated
vendored
Normal file
65
vendor/github.com/go-gl/gl/all-core/gl/procaddr.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// This file implements GlowGetProcAddress for every supported platform. The
|
||||
// correct version is chosen automatically based on build tags:
|
||||
// windows: WGL
|
||||
// darwin: CGL
|
||||
// linux freebsd: GLX
|
||||
// Use of EGL instead of the platform's default (listed above) is made possible
|
||||
// via the "egl" build tag.
|
||||
// It is also possible to install your own function outside this package for
|
||||
// retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc.
|
||||
package gl
|
||||
|
||||
/*
|
||||
#cgo windows CFLAGS: -DTAG_WINDOWS
|
||||
#cgo windows LDFLAGS: -lopengl32
|
||||
#cgo darwin CFLAGS: -DTAG_DARWIN
|
||||
#cgo darwin LDFLAGS: -framework OpenGL
|
||||
#cgo linux freebsd CFLAGS: -DTAG_POSIX
|
||||
#cgo linux freebsd LDFLAGS: -lGL
|
||||
#cgo egl CFLAGS: -DTAG_EGL
|
||||
#cgo egl LDFLAGS: -lEGL
|
||||
// Check the EGL tag first as it takes priority over the platform's default
|
||||
// configuration of WGL/GLX/CGL.
|
||||
#if defined(TAG_EGL)
|
||||
#include <stdlib.h>
|
||||
#include <EGL/egl.h>
|
||||
void* GlowGetProcAddress_glcoreall(const char* name) {
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
#elif defined(TAG_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
static HMODULE ogl32dll = NULL;
|
||||
void* GlowGetProcAddress_glcoreall(const char* name) {
|
||||
void* pf = wglGetProcAddress((LPCSTR) name);
|
||||
if (pf) {
|
||||
return pf;
|
||||
}
|
||||
if (ogl32dll == NULL) {
|
||||
ogl32dll = LoadLibraryA("opengl32.dll");
|
||||
}
|
||||
return GetProcAddress(ogl32dll, (LPCSTR) name);
|
||||
}
|
||||
#elif defined(TAG_DARWIN)
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
void* GlowGetProcAddress_glcoreall(const char* name) {
|
||||
return dlsym(RTLD_DEFAULT, name);
|
||||
}
|
||||
#elif defined(TAG_POSIX)
|
||||
#include <stdlib.h>
|
||||
#include <GL/glx.h>
|
||||
void* GlowGetProcAddress_glcoreall(const char* name) {
|
||||
return glXGetProcAddress(name);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func getProcAddress(namea string) unsafe.Pointer {
|
||||
cname := C.CString(namea)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
return C.GlowGetProcAddress_glcoreall(cname)
|
||||
}
|
25
vendor/github.com/go-gl/gl/generate.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// +build gen
|
||||
|
||||
//go:generate glow generate -out=./v2.1/gl/ -api=gl -version=2.1 -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./all-core/gl/ -api=gl -version=all -profile=core -lenientInit -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v3.2-core/gl/ -api=gl -version=3.2 -profile=core -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v3.3-core/gl/ -api=gl -version=3.3 -profile=core -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.1-core/gl/ -api=gl -version=4.1 -profile=core -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.2-core/gl/ -api=gl -version=4.2 -profile=core -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.3-core/gl/ -api=gl -version=4.3 -profile=core -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.4-core/gl/ -api=gl -version=4.4 -profile=core -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.5-core/gl/ -api=gl -version=4.5 -profile=core -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.6-core/gl/ -api=gl -version=4.6 -profile=core -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v3.2-compatibility/gl/ -api=gl -version=3.2 -profile=compatibility -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v3.3-compatibility/gl/ -api=gl -version=3.3 -profile=compatibility -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.1-compatibility/gl/ -api=gl -version=4.1 -profile=compatibility -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.2-compatibility/gl/ -api=gl -version=4.2 -profile=compatibility -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.3-compatibility/gl/ -api=gl -version=4.3 -profile=compatibility -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.4-compatibility/gl/ -api=gl -version=4.4 -profile=compatibility -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.5-compatibility/gl/ -api=gl -version=4.5 -profile=compatibility -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v4.6-compatibility/gl/ -api=gl -version=4.6 -profile=compatibility -xml=../glow/xml/
|
||||
//go:generate glow generate -out=./v3.1/gles2/ -api=gles2 -version=3.1 -xml=../glow/xml/
|
||||
|
||||
// This is an empty pseudo-package with the sole purpose of containing go generate directives
|
||||
// that generate all gl binding packages inside this repository.
|
||||
package gl
|
109
vendor/github.com/go-gl/gl/v2.1/gl/conversions.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
// Ptr takes a slice or pointer (to a singular scalar value or the first
|
||||
// element of an array or slice) and returns its GL-compatible address.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var data []uint8
|
||||
// ...
|
||||
// gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
|
||||
func Ptr(data interface{}) unsafe.Pointer {
|
||||
if data == nil {
|
||||
return unsafe.Pointer(nil)
|
||||
}
|
||||
var addr unsafe.Pointer
|
||||
v := reflect.ValueOf(data)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
switch e.Kind() {
|
||||
case
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
addr = unsafe.Pointer(e.UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
addr = unsafe.Pointer(v.Pointer())
|
||||
case reflect.Slice:
|
||||
addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// PtrOffset takes a pointer offset and returns a GL-compatible pointer.
|
||||
// Useful for functions such as glVertexAttribPointer that take pointer
|
||||
// parameters indicating an offset rather than an absolute memory address.
|
||||
func PtrOffset(offset int) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(offset))
|
||||
}
|
||||
|
||||
// Str takes a null-terminated Go string and returns its GL-compatible address.
|
||||
// This function reaches into Go string storage in an unsafe way so the caller
|
||||
// must ensure the string is not garbage collected.
|
||||
func Str(str string) *uint8 {
|
||||
if !strings.HasSuffix(str, "\x00") {
|
||||
panic("str argument missing null terminator: " + str)
|
||||
}
|
||||
header := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
return (*uint8)(unsafe.Pointer(header.Data))
|
||||
}
|
||||
|
||||
// GoStr takes a null-terminated string returned by OpenGL and constructs a
|
||||
// corresponding Go string.
|
||||
func GoStr(cstr *uint8) string {
|
||||
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
|
||||
}
|
||||
|
||||
// Strs takes a list of Go strings (with or without null-termination) and
|
||||
// returns their C counterpart.
|
||||
//
|
||||
// The returned free function must be called once you are done using the strings
|
||||
// in order to free the memory.
|
||||
//
|
||||
// If no strings are provided as a parameter this function will panic.
|
||||
func Strs(strs ...string) (cstrs **uint8, free func()) {
|
||||
if len(strs) == 0 {
|
||||
panic("Strs: expected at least 1 string")
|
||||
}
|
||||
|
||||
// Allocate a contiguous array large enough to hold all the strings' contents.
|
||||
n := 0
|
||||
for i := range strs {
|
||||
n += len(strs[i])
|
||||
}
|
||||
data := C.malloc(C.size_t(n))
|
||||
|
||||
// Copy all the strings into data.
|
||||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(data),
|
||||
Len: n,
|
||||
Cap: n,
|
||||
}))
|
||||
css := make([]*uint8, len(strs)) // Populated with pointers to each string.
|
||||
offset := 0
|
||||
for i := range strs {
|
||||
copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location.
|
||||
css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it.
|
||||
offset += len(strs[i])
|
||||
}
|
||||
|
||||
return (**uint8)(&css[0]), func() { C.free(data) }
|
||||
}
|
31
vendor/github.com/go-gl/gl/v2.1/gl/debug.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type DebugProc func(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message string,
|
||||
userParam unsafe.Pointer)
|
||||
|
||||
var userDebugCallback DebugProc
|
||||
|
||||
//export glowDebugCallback_gl21
|
||||
func glowDebugCallback_gl21(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message *uint8,
|
||||
userParam unsafe.Pointer) {
|
||||
if userDebugCallback != nil {
|
||||
userDebugCallback(source, gltype, id, severity, length, GoStr(message), userParam)
|
||||
}
|
||||
}
|
31094
vendor/github.com/go-gl/gl/v2.1/gl/package.go
generated
vendored
Normal file
65
vendor/github.com/go-gl/gl/v2.1/gl/procaddr.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// This file implements GlowGetProcAddress for every supported platform. The
|
||||
// correct version is chosen automatically based on build tags:
|
||||
// windows: WGL
|
||||
// darwin: CGL
|
||||
// linux freebsd: GLX
|
||||
// Use of EGL instead of the platform's default (listed above) is made possible
|
||||
// via the "egl" build tag.
|
||||
// It is also possible to install your own function outside this package for
|
||||
// retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc.
|
||||
package gl
|
||||
|
||||
/*
|
||||
#cgo windows CFLAGS: -DTAG_WINDOWS
|
||||
#cgo windows LDFLAGS: -lopengl32
|
||||
#cgo darwin CFLAGS: -DTAG_DARWIN
|
||||
#cgo darwin LDFLAGS: -framework OpenGL
|
||||
#cgo linux freebsd CFLAGS: -DTAG_POSIX
|
||||
#cgo linux freebsd LDFLAGS: -lGL
|
||||
#cgo egl CFLAGS: -DTAG_EGL
|
||||
#cgo egl LDFLAGS: -lEGL
|
||||
// Check the EGL tag first as it takes priority over the platform's default
|
||||
// configuration of WGL/GLX/CGL.
|
||||
#if defined(TAG_EGL)
|
||||
#include <stdlib.h>
|
||||
#include <EGL/egl.h>
|
||||
void* GlowGetProcAddress_gl21(const char* name) {
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
#elif defined(TAG_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
static HMODULE ogl32dll = NULL;
|
||||
void* GlowGetProcAddress_gl21(const char* name) {
|
||||
void* pf = wglGetProcAddress((LPCSTR) name);
|
||||
if (pf) {
|
||||
return pf;
|
||||
}
|
||||
if (ogl32dll == NULL) {
|
||||
ogl32dll = LoadLibraryA("opengl32.dll");
|
||||
}
|
||||
return GetProcAddress(ogl32dll, (LPCSTR) name);
|
||||
}
|
||||
#elif defined(TAG_DARWIN)
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
void* GlowGetProcAddress_gl21(const char* name) {
|
||||
return dlsym(RTLD_DEFAULT, name);
|
||||
}
|
||||
#elif defined(TAG_POSIX)
|
||||
#include <stdlib.h>
|
||||
#include <GL/glx.h>
|
||||
void* GlowGetProcAddress_gl21(const char* name) {
|
||||
return glXGetProcAddress(name);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func getProcAddress(namea string) unsafe.Pointer {
|
||||
cname := C.CString(namea)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
return C.GlowGetProcAddress_gl21(cname)
|
||||
}
|
109
vendor/github.com/go-gl/gl/v3.1/gles2/conversions.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gles2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
// Ptr takes a slice or pointer (to a singular scalar value or the first
|
||||
// element of an array or slice) and returns its GL-compatible address.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var data []uint8
|
||||
// ...
|
||||
// gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
|
||||
func Ptr(data interface{}) unsafe.Pointer {
|
||||
if data == nil {
|
||||
return unsafe.Pointer(nil)
|
||||
}
|
||||
var addr unsafe.Pointer
|
||||
v := reflect.ValueOf(data)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
switch e.Kind() {
|
||||
case
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
addr = unsafe.Pointer(e.UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
addr = unsafe.Pointer(v.Pointer())
|
||||
case reflect.Slice:
|
||||
addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// PtrOffset takes a pointer offset and returns a GL-compatible pointer.
|
||||
// Useful for functions such as glVertexAttribPointer that take pointer
|
||||
// parameters indicating an offset rather than an absolute memory address.
|
||||
func PtrOffset(offset int) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(offset))
|
||||
}
|
||||
|
||||
// Str takes a null-terminated Go string and returns its GL-compatible address.
|
||||
// This function reaches into Go string storage in an unsafe way so the caller
|
||||
// must ensure the string is not garbage collected.
|
||||
func Str(str string) *uint8 {
|
||||
if !strings.HasSuffix(str, "\x00") {
|
||||
panic("str argument missing null terminator: " + str)
|
||||
}
|
||||
header := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
return (*uint8)(unsafe.Pointer(header.Data))
|
||||
}
|
||||
|
||||
// GoStr takes a null-terminated string returned by OpenGL and constructs a
|
||||
// corresponding Go string.
|
||||
func GoStr(cstr *uint8) string {
|
||||
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
|
||||
}
|
||||
|
||||
// Strs takes a list of Go strings (with or without null-termination) and
|
||||
// returns their C counterpart.
|
||||
//
|
||||
// The returned free function must be called once you are done using the strings
|
||||
// in order to free the memory.
|
||||
//
|
||||
// If no strings are provided as a parameter this function will panic.
|
||||
func Strs(strs ...string) (cstrs **uint8, free func()) {
|
||||
if len(strs) == 0 {
|
||||
panic("Strs: expected at least 1 string")
|
||||
}
|
||||
|
||||
// Allocate a contiguous array large enough to hold all the strings' contents.
|
||||
n := 0
|
||||
for i := range strs {
|
||||
n += len(strs[i])
|
||||
}
|
||||
data := C.malloc(C.size_t(n))
|
||||
|
||||
// Copy all the strings into data.
|
||||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(data),
|
||||
Len: n,
|
||||
Cap: n,
|
||||
}))
|
||||
css := make([]*uint8, len(strs)) // Populated with pointers to each string.
|
||||
offset := 0
|
||||
for i := range strs {
|
||||
copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location.
|
||||
css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it.
|
||||
offset += len(strs[i])
|
||||
}
|
||||
|
||||
return (**uint8)(&css[0]), func() { C.free(data) }
|
||||
}
|
31
vendor/github.com/go-gl/gl/v3.1/gles2/debug.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gles2
|
||||
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type DebugProc func(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message string,
|
||||
userParam unsafe.Pointer)
|
||||
|
||||
var userDebugCallback DebugProc
|
||||
|
||||
//export glowDebugCallback_gles231
|
||||
func glowDebugCallback_gles231(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message *uint8,
|
||||
userParam unsafe.Pointer) {
|
||||
if userDebugCallback != nil {
|
||||
userDebugCallback(source, gltype, id, severity, length, GoStr(message), userParam)
|
||||
}
|
||||
}
|
8216
vendor/github.com/go-gl/gl/v3.1/gles2/package.go
generated
vendored
Normal file
65
vendor/github.com/go-gl/gl/v3.1/gles2/procaddr.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// This file implements GlowGetProcAddress for every supported platform. The
|
||||
// correct version is chosen automatically based on build tags:
|
||||
// windows: WGL
|
||||
// darwin: CGL
|
||||
// linux freebsd: GLX
|
||||
// Use of EGL instead of the platform's default (listed above) is made possible
|
||||
// via the "egl" build tag.
|
||||
// It is also possible to install your own function outside this package for
|
||||
// retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc.
|
||||
package gles2
|
||||
|
||||
/*
|
||||
#cgo windows CFLAGS: -DTAG_WINDOWS
|
||||
#cgo windows LDFLAGS: -lopengl32
|
||||
#cgo darwin CFLAGS: -DTAG_DARWIN
|
||||
#cgo darwin LDFLAGS: -framework OpenGL
|
||||
#cgo linux freebsd CFLAGS: -DTAG_POSIX
|
||||
#cgo linux freebsd LDFLAGS: -lGL
|
||||
#cgo egl CFLAGS: -DTAG_EGL
|
||||
#cgo egl LDFLAGS: -lEGL
|
||||
// Check the EGL tag first as it takes priority over the platform's default
|
||||
// configuration of WGL/GLX/CGL.
|
||||
#if defined(TAG_EGL)
|
||||
#include <stdlib.h>
|
||||
#include <EGL/egl.h>
|
||||
void* GlowGetProcAddress_gles231(const char* name) {
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
#elif defined(TAG_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
static HMODULE ogl32dll = NULL;
|
||||
void* GlowGetProcAddress_gles231(const char* name) {
|
||||
void* pf = wglGetProcAddress((LPCSTR) name);
|
||||
if (pf) {
|
||||
return pf;
|
||||
}
|
||||
if (ogl32dll == NULL) {
|
||||
ogl32dll = LoadLibraryA("opengl32.dll");
|
||||
}
|
||||
return GetProcAddress(ogl32dll, (LPCSTR) name);
|
||||
}
|
||||
#elif defined(TAG_DARWIN)
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
void* GlowGetProcAddress_gles231(const char* name) {
|
||||
return dlsym(RTLD_DEFAULT, name);
|
||||
}
|
||||
#elif defined(TAG_POSIX)
|
||||
#include <stdlib.h>
|
||||
#include <GL/glx.h>
|
||||
void* GlowGetProcAddress_gles231(const char* name) {
|
||||
return glXGetProcAddress(name);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func getProcAddress(namea string) unsafe.Pointer {
|
||||
cname := C.CString(namea)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
return C.GlowGetProcAddress_gles231(cname)
|
||||
}
|
109
vendor/github.com/go-gl/gl/v3.2-compatibility/gl/conversions.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
// Ptr takes a slice or pointer (to a singular scalar value or the first
|
||||
// element of an array or slice) and returns its GL-compatible address.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var data []uint8
|
||||
// ...
|
||||
// gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
|
||||
func Ptr(data interface{}) unsafe.Pointer {
|
||||
if data == nil {
|
||||
return unsafe.Pointer(nil)
|
||||
}
|
||||
var addr unsafe.Pointer
|
||||
v := reflect.ValueOf(data)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
switch e.Kind() {
|
||||
case
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
addr = unsafe.Pointer(e.UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
addr = unsafe.Pointer(v.Pointer())
|
||||
case reflect.Slice:
|
||||
addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// PtrOffset takes a pointer offset and returns a GL-compatible pointer.
|
||||
// Useful for functions such as glVertexAttribPointer that take pointer
|
||||
// parameters indicating an offset rather than an absolute memory address.
|
||||
func PtrOffset(offset int) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(offset))
|
||||
}
|
||||
|
||||
// Str takes a null-terminated Go string and returns its GL-compatible address.
|
||||
// This function reaches into Go string storage in an unsafe way so the caller
|
||||
// must ensure the string is not garbage collected.
|
||||
func Str(str string) *uint8 {
|
||||
if !strings.HasSuffix(str, "\x00") {
|
||||
panic("str argument missing null terminator: " + str)
|
||||
}
|
||||
header := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
return (*uint8)(unsafe.Pointer(header.Data))
|
||||
}
|
||||
|
||||
// GoStr takes a null-terminated string returned by OpenGL and constructs a
|
||||
// corresponding Go string.
|
||||
func GoStr(cstr *uint8) string {
|
||||
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
|
||||
}
|
||||
|
||||
// Strs takes a list of Go strings (with or without null-termination) and
|
||||
// returns their C counterpart.
|
||||
//
|
||||
// The returned free function must be called once you are done using the strings
|
||||
// in order to free the memory.
|
||||
//
|
||||
// If no strings are provided as a parameter this function will panic.
|
||||
func Strs(strs ...string) (cstrs **uint8, free func()) {
|
||||
if len(strs) == 0 {
|
||||
panic("Strs: expected at least 1 string")
|
||||
}
|
||||
|
||||
// Allocate a contiguous array large enough to hold all the strings' contents.
|
||||
n := 0
|
||||
for i := range strs {
|
||||
n += len(strs[i])
|
||||
}
|
||||
data := C.malloc(C.size_t(n))
|
||||
|
||||
// Copy all the strings into data.
|
||||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(data),
|
||||
Len: n,
|
||||
Cap: n,
|
||||
}))
|
||||
css := make([]*uint8, len(strs)) // Populated with pointers to each string.
|
||||
offset := 0
|
||||
for i := range strs {
|
||||
copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location.
|
||||
css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it.
|
||||
offset += len(strs[i])
|
||||
}
|
||||
|
||||
return (**uint8)(&css[0]), func() { C.free(data) }
|
||||
}
|
31
vendor/github.com/go-gl/gl/v3.2-compatibility/gl/debug.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type DebugProc func(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message string,
|
||||
userParam unsafe.Pointer)
|
||||
|
||||
var userDebugCallback DebugProc
|
||||
|
||||
//export glowDebugCallback_glcompatibility32
|
||||
func glowDebugCallback_glcompatibility32(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message *uint8,
|
||||
userParam unsafe.Pointer) {
|
||||
if userDebugCallback != nil {
|
||||
userDebugCallback(source, gltype, id, severity, length, GoStr(message), userParam)
|
||||
}
|
||||
}
|
32980
vendor/github.com/go-gl/gl/v3.2-compatibility/gl/package.go
generated
vendored
Normal file
65
vendor/github.com/go-gl/gl/v3.2-compatibility/gl/procaddr.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// This file implements GlowGetProcAddress for every supported platform. The
|
||||
// correct version is chosen automatically based on build tags:
|
||||
// windows: WGL
|
||||
// darwin: CGL
|
||||
// linux freebsd: GLX
|
||||
// Use of EGL instead of the platform's default (listed above) is made possible
|
||||
// via the "egl" build tag.
|
||||
// It is also possible to install your own function outside this package for
|
||||
// retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc.
|
||||
package gl
|
||||
|
||||
/*
|
||||
#cgo windows CFLAGS: -DTAG_WINDOWS
|
||||
#cgo windows LDFLAGS: -lopengl32
|
||||
#cgo darwin CFLAGS: -DTAG_DARWIN
|
||||
#cgo darwin LDFLAGS: -framework OpenGL
|
||||
#cgo linux freebsd CFLAGS: -DTAG_POSIX
|
||||
#cgo linux freebsd LDFLAGS: -lGL
|
||||
#cgo egl CFLAGS: -DTAG_EGL
|
||||
#cgo egl LDFLAGS: -lEGL
|
||||
// Check the EGL tag first as it takes priority over the platform's default
|
||||
// configuration of WGL/GLX/CGL.
|
||||
#if defined(TAG_EGL)
|
||||
#include <stdlib.h>
|
||||
#include <EGL/egl.h>
|
||||
void* GlowGetProcAddress_glcompatibility32(const char* name) {
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
#elif defined(TAG_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
static HMODULE ogl32dll = NULL;
|
||||
void* GlowGetProcAddress_glcompatibility32(const char* name) {
|
||||
void* pf = wglGetProcAddress((LPCSTR) name);
|
||||
if (pf) {
|
||||
return pf;
|
||||
}
|
||||
if (ogl32dll == NULL) {
|
||||
ogl32dll = LoadLibraryA("opengl32.dll");
|
||||
}
|
||||
return GetProcAddress(ogl32dll, (LPCSTR) name);
|
||||
}
|
||||
#elif defined(TAG_DARWIN)
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
void* GlowGetProcAddress_glcompatibility32(const char* name) {
|
||||
return dlsym(RTLD_DEFAULT, name);
|
||||
}
|
||||
#elif defined(TAG_POSIX)
|
||||
#include <stdlib.h>
|
||||
#include <GL/glx.h>
|
||||
void* GlowGetProcAddress_glcompatibility32(const char* name) {
|
||||
return glXGetProcAddress(name);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func getProcAddress(namea string) unsafe.Pointer {
|
||||
cname := C.CString(namea)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
return C.GlowGetProcAddress_glcompatibility32(cname)
|
||||
}
|
109
vendor/github.com/go-gl/gl/v3.2-core/gl/conversions.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
// Ptr takes a slice or pointer (to a singular scalar value or the first
|
||||
// element of an array or slice) and returns its GL-compatible address.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var data []uint8
|
||||
// ...
|
||||
// gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
|
||||
func Ptr(data interface{}) unsafe.Pointer {
|
||||
if data == nil {
|
||||
return unsafe.Pointer(nil)
|
||||
}
|
||||
var addr unsafe.Pointer
|
||||
v := reflect.ValueOf(data)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
switch e.Kind() {
|
||||
case
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
addr = unsafe.Pointer(e.UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
addr = unsafe.Pointer(v.Pointer())
|
||||
case reflect.Slice:
|
||||
addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// PtrOffset takes a pointer offset and returns a GL-compatible pointer.
|
||||
// Useful for functions such as glVertexAttribPointer that take pointer
|
||||
// parameters indicating an offset rather than an absolute memory address.
|
||||
func PtrOffset(offset int) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(offset))
|
||||
}
|
||||
|
||||
// Str takes a null-terminated Go string and returns its GL-compatible address.
|
||||
// This function reaches into Go string storage in an unsafe way so the caller
|
||||
// must ensure the string is not garbage collected.
|
||||
func Str(str string) *uint8 {
|
||||
if !strings.HasSuffix(str, "\x00") {
|
||||
panic("str argument missing null terminator: " + str)
|
||||
}
|
||||
header := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
return (*uint8)(unsafe.Pointer(header.Data))
|
||||
}
|
||||
|
||||
// GoStr takes a null-terminated string returned by OpenGL and constructs a
|
||||
// corresponding Go string.
|
||||
func GoStr(cstr *uint8) string {
|
||||
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
|
||||
}
|
||||
|
||||
// Strs takes a list of Go strings (with or without null-termination) and
|
||||
// returns their C counterpart.
|
||||
//
|
||||
// The returned free function must be called once you are done using the strings
|
||||
// in order to free the memory.
|
||||
//
|
||||
// If no strings are provided as a parameter this function will panic.
|
||||
func Strs(strs ...string) (cstrs **uint8, free func()) {
|
||||
if len(strs) == 0 {
|
||||
panic("Strs: expected at least 1 string")
|
||||
}
|
||||
|
||||
// Allocate a contiguous array large enough to hold all the strings' contents.
|
||||
n := 0
|
||||
for i := range strs {
|
||||
n += len(strs[i])
|
||||
}
|
||||
data := C.malloc(C.size_t(n))
|
||||
|
||||
// Copy all the strings into data.
|
||||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(data),
|
||||
Len: n,
|
||||
Cap: n,
|
||||
}))
|
||||
css := make([]*uint8, len(strs)) // Populated with pointers to each string.
|
||||
offset := 0
|
||||
for i := range strs {
|
||||
copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location.
|
||||
css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it.
|
||||
offset += len(strs[i])
|
||||
}
|
||||
|
||||
return (**uint8)(&css[0]), func() { C.free(data) }
|
||||
}
|
31
vendor/github.com/go-gl/gl/v3.2-core/gl/debug.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type DebugProc func(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message string,
|
||||
userParam unsafe.Pointer)
|
||||
|
||||
var userDebugCallback DebugProc
|
||||
|
||||
//export glowDebugCallback_glcore32
|
||||
func glowDebugCallback_glcore32(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message *uint8,
|
||||
userParam unsafe.Pointer) {
|
||||
if userDebugCallback != nil {
|
||||
userDebugCallback(source, gltype, id, severity, length, GoStr(message), userParam)
|
||||
}
|
||||
}
|
9786
vendor/github.com/go-gl/gl/v3.2-core/gl/package.go
generated
vendored
Normal file
65
vendor/github.com/go-gl/gl/v3.2-core/gl/procaddr.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// This file implements GlowGetProcAddress for every supported platform. The
|
||||
// correct version is chosen automatically based on build tags:
|
||||
// windows: WGL
|
||||
// darwin: CGL
|
||||
// linux freebsd: GLX
|
||||
// Use of EGL instead of the platform's default (listed above) is made possible
|
||||
// via the "egl" build tag.
|
||||
// It is also possible to install your own function outside this package for
|
||||
// retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc.
|
||||
package gl
|
||||
|
||||
/*
|
||||
#cgo windows CFLAGS: -DTAG_WINDOWS
|
||||
#cgo windows LDFLAGS: -lopengl32
|
||||
#cgo darwin CFLAGS: -DTAG_DARWIN
|
||||
#cgo darwin LDFLAGS: -framework OpenGL
|
||||
#cgo linux freebsd CFLAGS: -DTAG_POSIX
|
||||
#cgo linux freebsd LDFLAGS: -lGL
|
||||
#cgo egl CFLAGS: -DTAG_EGL
|
||||
#cgo egl LDFLAGS: -lEGL
|
||||
// Check the EGL tag first as it takes priority over the platform's default
|
||||
// configuration of WGL/GLX/CGL.
|
||||
#if defined(TAG_EGL)
|
||||
#include <stdlib.h>
|
||||
#include <EGL/egl.h>
|
||||
void* GlowGetProcAddress_glcore32(const char* name) {
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
#elif defined(TAG_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
static HMODULE ogl32dll = NULL;
|
||||
void* GlowGetProcAddress_glcore32(const char* name) {
|
||||
void* pf = wglGetProcAddress((LPCSTR) name);
|
||||
if (pf) {
|
||||
return pf;
|
||||
}
|
||||
if (ogl32dll == NULL) {
|
||||
ogl32dll = LoadLibraryA("opengl32.dll");
|
||||
}
|
||||
return GetProcAddress(ogl32dll, (LPCSTR) name);
|
||||
}
|
||||
#elif defined(TAG_DARWIN)
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
void* GlowGetProcAddress_glcore32(const char* name) {
|
||||
return dlsym(RTLD_DEFAULT, name);
|
||||
}
|
||||
#elif defined(TAG_POSIX)
|
||||
#include <stdlib.h>
|
||||
#include <GL/glx.h>
|
||||
void* GlowGetProcAddress_glcore32(const char* name) {
|
||||
return glXGetProcAddress(name);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func getProcAddress(namea string) unsafe.Pointer {
|
||||
cname := C.CString(namea)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
return C.GlowGetProcAddress_glcore32(cname)
|
||||
}
|
109
vendor/github.com/go-gl/gl/v3.3-compatibility/gl/conversions.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
// Ptr takes a slice or pointer (to a singular scalar value or the first
|
||||
// element of an array or slice) and returns its GL-compatible address.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var data []uint8
|
||||
// ...
|
||||
// gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
|
||||
func Ptr(data interface{}) unsafe.Pointer {
|
||||
if data == nil {
|
||||
return unsafe.Pointer(nil)
|
||||
}
|
||||
var addr unsafe.Pointer
|
||||
v := reflect.ValueOf(data)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
switch e.Kind() {
|
||||
case
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
addr = unsafe.Pointer(e.UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
addr = unsafe.Pointer(v.Pointer())
|
||||
case reflect.Slice:
|
||||
addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// PtrOffset takes a pointer offset and returns a GL-compatible pointer.
|
||||
// Useful for functions such as glVertexAttribPointer that take pointer
|
||||
// parameters indicating an offset rather than an absolute memory address.
|
||||
func PtrOffset(offset int) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(offset))
|
||||
}
|
||||
|
||||
// Str takes a null-terminated Go string and returns its GL-compatible address.
|
||||
// This function reaches into Go string storage in an unsafe way so the caller
|
||||
// must ensure the string is not garbage collected.
|
||||
func Str(str string) *uint8 {
|
||||
if !strings.HasSuffix(str, "\x00") {
|
||||
panic("str argument missing null terminator: " + str)
|
||||
}
|
||||
header := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
return (*uint8)(unsafe.Pointer(header.Data))
|
||||
}
|
||||
|
||||
// GoStr takes a null-terminated string returned by OpenGL and constructs a
|
||||
// corresponding Go string.
|
||||
func GoStr(cstr *uint8) string {
|
||||
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
|
||||
}
|
||||
|
||||
// Strs takes a list of Go strings (with or without null-termination) and
|
||||
// returns their C counterpart.
|
||||
//
|
||||
// The returned free function must be called once you are done using the strings
|
||||
// in order to free the memory.
|
||||
//
|
||||
// If no strings are provided as a parameter this function will panic.
|
||||
func Strs(strs ...string) (cstrs **uint8, free func()) {
|
||||
if len(strs) == 0 {
|
||||
panic("Strs: expected at least 1 string")
|
||||
}
|
||||
|
||||
// Allocate a contiguous array large enough to hold all the strings' contents.
|
||||
n := 0
|
||||
for i := range strs {
|
||||
n += len(strs[i])
|
||||
}
|
||||
data := C.malloc(C.size_t(n))
|
||||
|
||||
// Copy all the strings into data.
|
||||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(data),
|
||||
Len: n,
|
||||
Cap: n,
|
||||
}))
|
||||
css := make([]*uint8, len(strs)) // Populated with pointers to each string.
|
||||
offset := 0
|
||||
for i := range strs {
|
||||
copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location.
|
||||
css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it.
|
||||
offset += len(strs[i])
|
||||
}
|
||||
|
||||
return (**uint8)(&css[0]), func() { C.free(data) }
|
||||
}
|