Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Last active April 2, 2019 21:08
Show Gist options
  • Save peterhellberg/80df53fa909a2012f5acc00e2b908fc0 to your computer and use it in GitHub Desktop.
Save peterhellberg/80df53fa909a2012f5acc00e2b908fc0 to your computer and use it in GitHub Desktop.
Tunnel effects in Go
package main
import (
"image"
"math"
"time"
"github.com/faiface/pixel"
"github.com/faiface/pixel/pixelgl"
"github.com/peterhellberg/plasma"
"github.com/peterhellberg/plasma/palette"
)
const (
size = 256
fsize = float64(size)
w = 640
fw = float64(w)
h = 480
fh = float64(h)
)
func run() {
win, err := pixelgl.NewWindow(pixelgl.WindowConfig{
Bounds: pixel.R(0, 0, float64(w), float64(h)),
VSync: true,
Undecorated: true,
Resizable: false,
})
if err != nil {
panic(err)
}
win.SetSmooth(true)
texture := plasmaImage(size, size)
buffer := image.NewRGBA(image.Rect(0, 0, w, h))
bufferPicture := pixel.PictureDataFromImage(buffer)
distanceTable := [h][w]int{}
angleTable := [h][w]int{}
ratio := 32.0
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
fx, fy := float64(x), float64(y)
distance := int(ratio*size/math.Sqrt((fx-fw/2.0)*(fx-fw/2.0)+(fy-fh/2.0)*(fy-fh/2.0))) % size
angle := int(0.5 * size * math.Atan2(fy-fh/2.0, fx-fw/2.0) / math.Pi)
distanceTable[y][x] = distance
angleTable[y][x] = angle
}
}
centerMatrix := pixel.IM.Moved(win.Bounds().Center()).Scaled(
win.Bounds().Center(), 1,
)
start := time.Now()
go func() {
for range time.Tick(32 * time.Millisecond) {
animation := time.Since(start).Seconds()
shiftX := int(fsize * 1.2 * animation)
shiftY := int(fsize * 0.10 * animation)
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
buffer.Set(x, y, texture.At(
int(uint(distanceTable[y][x]+shiftX)%size),
int(uint(angleTable[y][x]+shiftY)%size),
))
}
}
bufferPicture = pixel.PictureDataFromImage(buffer)
}
}()
for !win.Closed() {
win.SetClosed(win.JustPressed(pixelgl.KeyEscape) || win.JustPressed(pixelgl.KeyQ))
bs := pixel.NewSprite(bufferPicture, bufferPicture.Bounds())
bs.SetMatrix(centerMatrix)
bs.Draw(win)
win.Update()
}
}
func plasmaImage(w, h int) image.Image {
return plasma.New(w, h, 64).Image(w, h, 12, palette.DefaultGradient)
}
func main() {
pixelgl.Run(run)
}
package main
import (
"image"
"image/color"
"math"
"time"
"github.com/faiface/pixel"
"github.com/faiface/pixel/pixelgl"
"github.com/peterhellberg/plasma"
"github.com/peterhellberg/plasma/palette"
)
const (
size = 256
fsize = float64(size)
w = 640
fw = float64(w)
h = 480
fh = float64(h)
)
func run() {
win, err := pixelgl.NewWindow(pixelgl.WindowConfig{
Bounds: pixel.R(0, 0, float64(w), float64(h)),
VSync: true,
Undecorated: true,
Resizable: false,
})
if err != nil {
panic(err)
}
win.SetSmooth(true)
texture1 := xorImage(size, size)
texture2 := plasmaImage(size, size)
buffer := image.NewRGBA(image.Rect(0, 0, w, h))
bufferPicture := pixel.PictureDataFromImage(buffer)
distanceTable := [h][w]int{}
angleTable := [h][w]int{}
ratio := 32.0
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
fx, fy := float64(x), float64(y)
distance := int(ratio*size/math.Sqrt((fx-fw/2.0)*(fx-fw/2.0)+(fy-fh/2.0)*(fy-fh/2.0))) % size
angle := int(0.5 * size * math.Atan2(fy-fh/2.0, fx-fw/2.0) / math.Pi)
distanceTable[y][x] = distance
angleTable[y][x] = angle
}
}
centerMatrix := pixel.IM.Moved(win.Bounds().Center()).Scaled(
win.Bounds().Center(), 1,
)
start := time.Now()
go func() {
for range time.Tick(32 * time.Millisecond) {
animation := time.Since(start).Seconds()
shiftX := int(fsize * 1.2 * animation)
shiftY := int(fsize * 0.10 * animation)
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
texture := texture1
if int(animation)%2 == 0 {
texture = texture2
}
buffer.Set(x, y, texture.At(
int(uint(distanceTable[y][x]+shiftX)%size),
int(uint(angleTable[y][x]+shiftY)%size),
))
}
}
bufferPicture = pixel.PictureDataFromImage(buffer)
}
}()
for !win.Closed() {
win.SetClosed(win.JustPressed(pixelgl.KeyEscape) || win.JustPressed(pixelgl.KeyQ))
bs := pixel.NewSprite(bufferPicture, bufferPicture.Bounds())
bs.SetMatrix(centerMatrix)
bs.Draw(win)
win.Update()
}
}
func plasmaImage(w, h int) image.Image {
return plasma.New(w, h, 64).Image(w, h, 12, palette.DefaultGradient)
}
func xorImage(w, h int) image.Image {
m := image.NewRGBA(image.Rect(0, 0, w, h))
for x := 0; x < w; x++ {
for y := 0; y < h; y++ {
u := uint8(x ^ y)
c := color.RGBA{
(u) % 192,
24,
(u & uint8(y)) % 128,
200,
}
m.Set(x, y, c)
}
}
return m
}
func main() {
pixelgl.Run(run)
}
package main
import (
"image"
"image/color"
"math"
"time"
"github.com/faiface/pixel"
"github.com/faiface/pixel/pixelgl"
)
const (
size = 256
fsize = float64(size)
w = 640
fw = float64(w)
h = 480
fh = float64(h)
)
func run() {
win, err := pixelgl.NewWindow(pixelgl.WindowConfig{
Bounds: pixel.R(0, 0, float64(w), float64(h)),
VSync: true,
Undecorated: true,
Resizable: false,
})
if err != nil {
panic(err)
}
win.SetSmooth(true)
texture := xorImage(size, size)
buffer := image.NewRGBA(image.Rect(0, 0, w, h))
bufferPicture := pixel.PictureDataFromImage(buffer)
distanceTable := [h][w]int{}
angleTable := [h][w]int{}
ratio := 32.0
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
fx, fy := float64(x), float64(y)
distance := int(ratio*size/math.Sqrt((fx-fw/2.0)*(fx-fw/2.0)+(fy-fh/2.0)*(fy-fh/2.0))) % size
angle := int(0.5 * size * math.Atan2(fy-fh/2.0, fx-fw/2.0) / math.Pi)
distanceTable[y][x] = distance
angleTable[y][x] = angle
}
}
centerMatrix := pixel.IM.Moved(win.Bounds().Center()).Scaled(
win.Bounds().Center(), 1,
)
start := time.Now()
go func() {
for range time.Tick(32 * time.Millisecond) {
animation := time.Since(start).Seconds()
shiftX := int(fsize * 1.2 * animation)
shiftY := int(fsize * 0.10 * animation)
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
buffer.Set(x, y, texture.At(
int(uint(distanceTable[y][x]+shiftX)%size),
int(uint(angleTable[y][x]+shiftY)%size),
))
}
}
bufferPicture = pixel.PictureDataFromImage(buffer)
}
}()
for !win.Closed() {
win.SetClosed(win.JustPressed(pixelgl.KeyEscape) || win.JustPressed(pixelgl.KeyQ))
bs := pixel.NewSprite(bufferPicture, bufferPicture.Bounds())
bs.SetMatrix(centerMatrix)
bs.Draw(win)
win.Update()
}
}
func xorImage(w, h int) image.Image {
m := image.NewRGBA(image.Rect(0, 0, w, h))
for x := 0; x < w; x++ {
for y := 0; y < h; y++ {
u := uint8(x ^ y)
c := color.RGBA{
(u) % 192,
24,
(u & uint8(y)) % 128,
200,
}
m.Set(x, y, c)
}
}
return m
}
func main() {
pixelgl.Run(run)
}
@peterhellberg
Copy link
Author

Smaller animation:

looking-around-plasma-tunnel-small

@peterhellberg
Copy link
Author

This code is heavily based on http://lodev.org/cgtutor/tunnel.html#The_code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment