Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Created September 16, 2019 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterhellberg/10167ecca35d6f4eef8bd2304a55a7fa to your computer and use it in GitHub Desktop.
Save peterhellberg/10167ecca35d6f4eef8bd2304a55a7fa to your computer and use it in GitHub Desktop.
Submarine SDF with fake 3D effect, rendered by Ebiten
package main
import (
"github.com/hajimehoshi/ebiten"
"github.com/peterhellberg/gfx"
)
func main() {
s := NewSubmarine(112, 112, gfx.PaletteAmmo8)
ebiten.SetFullscreen(false)
ebiten.SetWindowDecorated(false)
ebiten.Run(s.run, s.w, s.h, 5, "Ebiten GFX Submarine")
}
func NewSubmarine(w, h int, p gfx.Palette) *Submarine {
c := gfx.BoundsCenter(gfx.IR(0, 0, -w, -h))
return &Submarine{w: w, h: h, c: c, p: p, m: gfx.IM.Moved(c)}
}
type Submarine struct {
w int
h int
t float64
c gfx.Vec
p gfx.Palette
m gfx.Matrix
deg float64
}
func (s *Submarine) run(screen *ebiten.Image) error {
if err := s.update(); err != nil {
return err
}
if ebiten.IsDrawingSkipped() {
return nil
}
return screen.ReplacePixels(s.draw().Pixels())
}
func (s *Submarine) update() error {
switch {
case ebiten.IsKeyPressed(ebiten.KeyEscape) || ebiten.IsKeyPressed(ebiten.KeyQ):
return gfx.ErrDone
case ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyRight):
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
if s.deg += 1; s.deg > 360 {
s.deg = 0
}
if s.t < 9 {
s.t += 0.1
}
}
if ebiten.IsKeyPressed(ebiten.KeyRight) {
if s.deg -= 1; s.deg < 0 {
s.deg = 360
}
if s.t > -9 {
s.t -= 0.1
}
}
s.m = gfx.IM.Moved(s.c).RotatedDegrees(gfx.ZV, s.deg)
default:
if gfx.MathAbs(s.t) >= 0.1 {
if s.t < 0 {
s.t += 0.6
} else {
s.t -= 0.6
}
} else {
s.t = 0
}
}
return nil
}
func (s *Submarine) draw() *gfx.Paletted {
m := gfx.NewPaletted(s.w, s.h, s.p, s.p[3])
gfx.EachPixel(m.Bounds(), func(x, y int) {
pm := s.m.Project(gfx.IV(x, y))
sd := gfx.SignedDistance{pm}
b := gfx.V(23-gfx.MathAbs(s.t), 8)
d := sd.OpSubtraction(
sd.OpMoved(gfx.V(-s.t, 22), sd.CircleFunc(6)),
sd.OpUnion(
sd.OpMoved(gfx.V(0, 26), sd.RectangleFunc(b)),
sd.OpUnion(
sd.OpMoved(gfx.V(0, -40), sd.CircleFunc(10)),
sd.Rectangle(gfx.V(10, 37)),
),
),
)
if d < 2 {
m.Set(x, y, s.p[1])
}
if d < 0 {
m.Set(x, y, s.p[2])
}
})
return m
}
@peterhellberg
Copy link
Author

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