Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Last active November 11, 2020 15:23
Show Gist options
  • Save peterhellberg/723946589855dc61fa45df81e3f70bfc to your computer and use it in GitHub Desktop.
Save peterhellberg/723946589855dc61fa45df81e3f70bfc to your computer and use it in GitHub Desktop.
Blocks rendered by Ebiten with gfx.
package main
import (
"github.com/hajimehoshi/ebiten"
"github.com/peterhellberg/gfx"
)
const (
title = "Ebiten GFX Blocks"
scale = 4
w, h = 256, 128
fw, fh = float64(w), float64(h)
fw2, fh2 = fw / 2, fh / 2
)
var (
pix = make([]uint8, w*h*4)
scaler = gfx.NewLinearScaler().Range(6, 0.5).Domain(0, fh)
flipY = gfx.V(1, -1)
bounds = gfx.R(0, 0, fw, fh)
defaultPos = gfx.V3(fw2, fh2, 0)
defaultOrigin = bounds.Center().ScaledXY(flipY).Vec3(1)
origin = defaultOrigin
pos = defaultPos
blocks = createBlocks()
)
func createBlocks() (blocks gfx.Blocks) {
for j := -6.0; j < 6; j++ {
for i := -6.0; i < 6; i++ {
aj, ai := gfx.MathAbs(j), gfx.MathAbs(i)
p := pos.AddXYZ(-fw2+(i*10), -fh2+(j*10), 0)
s := gfx.V3(3+aj, 3+ai, 3*ai+aj)
c := gfx.BlockColors[int(ai+aj)%8]
blocks.AddNewBlock(p, s, c)
blocks.AddNewBlock(p.AddXYZ(0, 0, -7*(ai+aj)), s.AddXYZ(-3, -3, 0), gfx.BlockColorBlack)
}
}
return blocks
}
func render() {
dst := gfx.NewImage(w, h, gfx.BlockColorBlack.Dark)
var drawCount int
for i := len(blocks) - 1; i >= 0; i-- {
b := blocks[i]
if shape, top, left, _ := b.Polygons(origin); bounds.Overlaps(shape.Rect()) {
drawCount += shape.Fill(dst, b.Color.Medium)
drawCount += left.Fill(dst, b.Color.Dark)
drawCount += top.Fill(dst, b.Color.Light)
}
drawCount++
}
gfx.Log("drawCount: %d", drawCount)
pix = dst.Pix
}
func main() {
render()
ebiten.SetWindowDecorated(false)
ebiten.Run(func(screen *ebiten.Image) error {
if ebiten.IsKeyPressed(ebiten.KeyEscape) {
return gfx.ErrDone
}
if ebiten.IsDrawingSkipped() {
return nil
}
if updatePos(pos, origin) {
render()
}
return screen.ReplacePixels(pix)
}, w, h, scale, title)
}
func updatePos(oldPos, oldOrigin gfx.Vec3) bool {
if ebiten.IsKeyPressed(ebiten.KeyH) {
pos.Y += 0.6 // Diagonal up left
}
if ebiten.IsKeyPressed(ebiten.KeyL) {
pos.X += 0.6 // Diagonal up right
}
if ebiten.IsKeyPressed(ebiten.KeyJ) {
pos.X -= 0.6 // Diagonal down left
}
if ebiten.IsKeyPressed(ebiten.KeyK) {
pos.Y -= 0.6 // Diagonal down right
}
if ebiten.IsKeyPressed(ebiten.KeyW) {
pos.Z += 0.5 // Straight up
}
if ebiten.IsKeyPressed(ebiten.KeyS) {
pos.Z -= 0.5 // Straight down
}
if ebiten.IsKeyPressed(ebiten.KeyA) {
origin.X -= 1 // Straight left
}
if ebiten.IsKeyPressed(ebiten.KeyD) {
origin.X += 1 // Straight right
}
if ebiten.IsKeyPressed(ebiten.KeyC) {
pos, origin = defaultPos, defaultOrigin // Reset pos and origin
}
if ebiten.IsKeyPressed(ebiten.KeyX) && origin.Z > 0.5 {
origin.Z -= 0.05 // Scale down
}
if ebiten.IsKeyPressed(ebiten.KeyZ) && origin.Z < 10 {
origin.Z += 0.05 // Scale up
}
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
origin.X, origin.Y = gfx.IV(ebiten.CursorPosition()).ScaledXY(flipY).XY()
}
switch touches := ebiten.Touches(); len(touches) {
case 1:
origin.X, origin.Y = gfx.IV(touches[0].Position()).ScaledXY(flipY).XY()
case 2:
tv := gfx.IV(touches[1].Position())
origin.Z = scaler.ScaleFloat64(tv.Y)
origin.X, origin.Y = gfx.IV(touches[0].Position()).ScaledXY(flipY).XY()
}
return pos != oldPos || origin != oldOrigin
}
@peterhellberg
Copy link
Author

screen shot 2019-02-08 at 18 33 25

@peterhellberg
Copy link
Author

screen shot 2019-02-08 at 20 14 39

@peterhellberg
Copy link
Author

screen shot 2019-02-08 at 20 20 07

@peterhellberg
Copy link
Author

screen shot 2019-02-08 at 23 09 30

@peterhellberg
Copy link
Author

screen shot 2019-02-08 at 23 46 55

@peterhellberg
Copy link
Author

screen shot 2019-02-09 at 05 17 47

screen shot 2019-02-09 at 05 17 57

screen shot 2019-02-09 at 05 18 09

screen shot 2019-02-09 at 05 18 14

screen shot 2019-02-09 at 05 18 18

@peterhellberg
Copy link
Author

Debugging and Optimizing 🚜

screen shot 2019-02-09 at 05 35 40

screen shot 2019-02-09 at 05 35 27

@peterhellberg
Copy link
Author

peterhellberg commented Feb 9, 2019

screen shot 2019-02-09 at 05 59 07

func (t Triangle) Draw(dst draw.Image, c color.Color) {
	b := t.Bounds()

	for x := b.Min.X; x < b.Max.X; x++ {
		for y := b.Min.Y; y < b.Max.Y; y++ {
			dst.Set(x, y, c)
		}
	}
}

@peterhellberg
Copy link
Author

screen shot 2019-02-09 at 06 04 47

screen shot 2019-02-09 at 06 06 31

screen shot 2019-02-09 at 06 13 11

screen shot 2019-02-09 at 06 13 48

screen shot 2019-02-09 at 06 41 12

screen shot 2019-02-09 at 06 42 10

screen shot 2019-02-09 at 06 45 28

screen shot 2019-02-09 at 07 18 34

screen shot 2019-02-09 at 07 18 55

screen shot 2019-02-09 at 07 20 29

screen shot 2019-02-09 at 08 16 09

screen shot 2019-02-09 at 09 12 16

screen shot 2019-02-09 at 09 13 29

@peterhellberg
Copy link
Author

if shape := b.Shape(origin); bounds.Overlaps(shape.Rect()) {
	drawCount += shape.Fill(dst, b.Color.Medium)

	dt := gfx.NewDrawTarget(dst)
	dt.MakeTriangles(b.TrianglesData(origin).Slice(0, 15)).Draw()
}

@peterhellberg
Copy link
Author

screen shot 2019-02-09 at 09 23 48

screen shot 2019-02-09 at 09 50 50

screen shot 2019-02-09 at 10 37 54

@peterhellberg
Copy link
Author

Some more experiments

screen shot 2019-02-09 at 12 38 09

screen shot 2019-02-09 at 13 28 07

screen shot 2019-02-09 at 13 29 15

@peterhellberg
Copy link
Author

gfx-example-many-blocks

@peterhellberg
Copy link
Author

peterhellberg commented Feb 11, 2019

2560x1440 on white background

gfx-example-many-blocks

@peterhellberg
Copy link
Author

2560x1440 with transparent background

gfx-example-many-blocks

@peterhellberg
Copy link
Author

peterhellberg commented Feb 11, 2019

gfx-many-blocks.go

package main

import (
	"flag"

	"github.com/peterhellberg/gfx"
)

func main() {
	var (
		w int
		h int
		z float64
	)

	flag.IntVar(&w, "w", 2560, "Width of image")
	flag.IntVar(&h, "h", 1440, "Height of image")
	flag.Float64Var(&z, "z", 24, "Zoom level")
	flag.Parse()

	var (
		blockColors = gfx.BlockColors
		dst         = gfx.NewImage(w, h)
		rect        = gfx.BoundsToRect(dst.Bounds())
		origin      = rect.Center().ScaledXY(gfx.V(1, -1)).Vec3(z)
	)

	var blocks gfx.Blocks

	sn := gfx.NewSimplexNoise(123)

	for x := -296.0; x < 296; x += 10 {
		for y := -296.0; y < 296; y += 18 {
			n := sn.Noise2D(x, y)
			pos := gfx.V3(x, y, 0)
			size := gfx.V3(8, 6+12*gfx.RandFloat64(), gfx.MathAbs(n)*10)

			bc := blockColors[gfx.RandIntn(len(blockColors)-2)]

			blocks.AddNewBlock(pos, size, bc)
		}
	}

	gfx.SortSlice(blocks, func(i, j int) bool {
		a, b := blocks[i], blocks[j]

		av := a.Shape(origin).Bounds().Max.Y
		bv := b.Shape(origin).Bounds().Max.Y

		return av < bv
	})

	blocks.DrawPolygons(dst, origin)

	gfx.SavePNG(gfx.Sprintf("gfx-many-blocks-%dx%d-z%g.png", w, h, z), dst)
}

@peterhellberg
Copy link
Author

2560x1440-z12

gfx-many-blocks-2560x1440-z12

2560x1440-z24

gfx-many-blocks-2560x1440-z24

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