dep -> govendor

This commit is contained in:
2018-03-18 05:53:01 +00:00
parent 93fb27403b
commit 88acc05085
1033 changed files with 754817 additions and 113 deletions

73
Gopkg.lock generated
View File

@@ -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

View File

@@ -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

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

189
vendor/github.com/faiface/glhf/examples/demo/main.go generated vendored Normal file
View 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);
}
`

View 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
![bouncing animation](https://user-images.githubusercontent.com/565124/32401910-7cd87fb2-c119-11e7-8121-7fb46e5e11a8.gif)
![bouncing screenshot](screenshot.png)
## Links
- https://github.com/peterhellberg/pixel-experiments/tree/master/bouncing
- https://gist.github.com/peterhellberg/674f32a15a7d2d249e634ce781f333e8

View 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},
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View 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)
![life](life.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View 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)
}

View 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
}

View 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()
}
}

View 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/).
![Result](result.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View 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
![Screenshot](screenshot.png)

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View 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
}

View 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.
![Parallax scrolling background](result.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View 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
}

View 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).
![Randomly generated 1D terrain](result.png)

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 759 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

View 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 Lodes 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
![raycaster animation](https://user-images.githubusercontent.com/565124/31828029-798e6620-b5b9-11e7-96b7-fda540755745.gif)
![raycaster screenshot](screenshot.png)
## Links
- https://github.com/peterhellberg/pixel-experiments/tree/master/raycaster
- https://gist.github.com/peterhellberg/835eccabf95800555120cc8f0c9e16c2

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View 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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View 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)
}

View 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
![starfield animation](https://user-images.githubusercontent.com/565124/32411599-a5fcba72-c1df-11e7-8730-a570470a4eee.gif)
![starfield screenshot](screenshot.png)
## Links
- https://github.com/peterhellberg/pixel-experiments/tree/master/starfield
- https://gist.github.com/peterhellberg/4018e228cced61a0bb26991e49299c96

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View 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},
}

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View 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)
}

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View 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)
}

View 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)
}

View 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).
![Screenshot](screenshot.png)

195
vendor/github.com/faiface/pixel/examples/lights/main.go generated vendored Normal file
View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View 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).
![Screenshot](screenshot.png)

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View 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
1 Front 0 0
2 FrontBlink 1 1
3 LookUp 2 2
4 Left 3 7
5 LeftRight 4 6
6 LeftBlink 7 7
7 Walk 8 15
8 Run 16 23
9 Jump 24 26

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

View 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/).
![Screenshot](screenshot.png)

View 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
1 1543 1146 362 336
2 396 0 398 364
3 761 1535 386 342
4 795 794 351 367
5 394 1163 386 364
6 1120 1163 377 348
7 795 0 368 407
8 0 0 395 397
9 1164 0 378 415
10 781 1163 338 360
11 1543 0 372 370
12 1148 1535 393 327
13 387 1535 373 364
14 396 365 371 388
15 0 758 378 404
16 379 758 378 371
17 1543 774 360 371
18 1543 1483 350 398
19 0 398 382 359
20 1164 416 356 382
21 1164 799 369 350
22 0 1535 386 394
23 795 408 366 385
24 1543 371 367 402
25 0 1163 393 371

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

230
vendor/github.com/faiface/pixel/examples/smoke/main.go generated vendored Normal file
View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

View 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.
![Screenshot](screenshot.png)

View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

View 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.
![Screenshot](screenshot.png)

76
vendor/github.com/faiface/pixel/examples/xor/main.go generated vendored Normal file
View 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)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

248
vendor/github.com/faiface/pixel/text/atlas.go generated vendored Normal file
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,65 @@
# gl [![Build Status](https://travis-ci.org/go-gl/gl.svg?branch=master)](https://travis-ci.org/go-gl/gl) [![GoDoc](https://godoc.org/github.com/go-gl/gl?status.svg)](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
View 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
View 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

File diff suppressed because it is too large Load Diff

65
vendor/github.com/go-gl/gl/all-core/gl/procaddr.go generated vendored Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

65
vendor/github.com/go-gl/gl/v2.1/gl/procaddr.go generated vendored Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

65
vendor/github.com/go-gl/gl/v3.1/gles2/procaddr.go generated vendored Normal file
View 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)
}

View 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) }
}

View 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)
}
}

File diff suppressed because it is too large Load Diff

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

65
vendor/github.com/go-gl/gl/v3.2-core/gl/procaddr.go generated vendored Normal file
View 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)
}

View 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) }
}

Some files were not shown because too many files have changed in this diff Show More