Merge pull request #83 from peterhellberg/add-pixel-experiments-to-community-examples
Add pixel experiments to community examples
This commit is contained in:
commit
97f07acd5e
|
@ -0,0 +1,16 @@
|
||||||
|
# bouncing
|
||||||
|
|
||||||
|
Bouncing particles using the [imdraw](https://godoc.org/github.com/faiface/pixel/imdraw) package.
|
||||||
|
|
||||||
|
Made by [Peter Hellberg](https://github.com/peterhellberg/) as part of his [pixel-experiments](https://github.com/peterhellberg/pixel-experiments)
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- https://github.com/peterhellberg/pixel-experiments/tree/master/bouncing
|
||||||
|
- https://gist.github.com/peterhellberg/674f32a15a7d2d249e634ce781f333e8
|
|
@ -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 |
|
@ -0,0 +1,22 @@
|
||||||
|
# raycaster
|
||||||
|
|
||||||
|
A raycaster made by [Peter Hellberg](https://github.com/peterhellberg/) as part of his [pixel-experiments](https://github.com/peterhellberg/pixel-experiments).
|
||||||
|
|
||||||
|
Based on Lode’s article on [raycasting](http://lodev.org/cgtutor/raycasting.html).
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
WASD for strafing and arrow keys for rotation.
|
||||||
|
|
||||||
|
Place blocks using the number keys.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- https://github.com/peterhellberg/pixel-experiments/tree/master/raycaster
|
||||||
|
- https://gist.github.com/peterhellberg/835eccabf95800555120cc8f0c9e16c2
|
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
|
@ -0,0 +1,20 @@
|
||||||
|
# starfield
|
||||||
|
|
||||||
|
Classic starfield… with [supposedly accurate stellar colors](http://www.vendian.org/mncharity/dir3/starcolor/)
|
||||||
|
|
||||||
|
Made by [Peter Hellberg](https://github.com/peterhellberg/) as part of his [pixel-experiments](https://github.com/peterhellberg/pixel-experiments)
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
Arrow up and down to change speed. Space bar to almost stop.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- https://github.com/peterhellberg/pixel-experiments/tree/master/starfield
|
||||||
|
- https://gist.github.com/peterhellberg/4018e228cced61a0bb26991e49299c96
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -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},
|
||||||
|
}
|
Loading…
Reference in New Issue