[First commit]

This commit is contained in:
xoy 2024-10-22 20:34:39 +02:00
commit 885373889b
9 changed files with 274 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
img/*

13
config.go Normal file
View File

@ -0,0 +1,13 @@
package main
const (
screenWidth int = 500
screenHeight int = 500
windowWidth int = 1000
windowHeight int = 1000
layerCount int = 3
)
var (
function Function = &X1{}
)

19
functions.go Normal file
View File

@ -0,0 +1,19 @@
package main
import (
"math"
)
type X1 struct{}
func (x *X1) Func(f float64) uint16 {
v := (65535 / 2) * (float64(screenHeight+screenWidth) / 2) / f
return ToUint16(v)
}
type X2 struct{}
func (x *X2) Func(f float64) uint16 {
v := (math.Sin((float64(screenWidth)*float64(screenHeight))/f) + 1) / 2 * 65535
return ToUint16(v)
}

14
go.mod Normal file
View File

@ -0,0 +1,14 @@
module git.ctdo.de/xoy/xvisuals
go 1.23.2
require github.com/hajimehoshi/ebiten/v2 v2.8.1
require (
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325 // indirect
github.com/ebitengine/hideconsole v1.0.0 // indirect
github.com/ebitengine/purego v0.8.0 // indirect
github.com/jezek/xgb v1.1.1 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
)

16
go.sum Normal file
View File

@ -0,0 +1,16 @@
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325 h1:Gk1XUEttOk0/hb6Tq3WkmutWa0ZLhNn/6fc6XZpM7tM=
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325/go.mod h1:ulhSQcbPioQrallSuIzF8l1NKQoD7xmMZc5NxzibUMY=
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
github.com/ebitengine/hideconsole v1.0.0/go.mod h1:hTTBTvVYWKBuxPr7peweneWdkUwEuHuB3C1R/ielR1A=
github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE=
github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/hajimehoshi/ebiten/v2 v2.8.1 h1:6n6ZXnbeSCZccdqrH7s9Ut+dll9TEostUqbc72Tis/g=
github.com/hajimehoshi/ebiten/v2 v2.8.1/go.mod h1:SXx/whkvpfsavGo6lvZykprerakl+8Uo1X8d2U5aAnA=
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

133
main.go Normal file
View File

@ -0,0 +1,133 @@
package main
import (
"image/color"
"image/png"
"log"
"math"
"math/rand"
"os"
"strconv"
"time"
"github.com/hajimehoshi/ebiten/v2"
)
type Game struct {
points []*Position
preScreens []*ColorArray
screen *ebiten.Image
pressCountEnter int
pressCountSpace int
}
func (g *Game) NewImage() {
image := NewColorArray()
for i := 0; i < 3; i++ {
x, y := rand.Intn(screenHeight), rand.Intn(screenWidth)
g.points[i] = &Position{x, y}
}
for x := 0; x < screenWidth; x++ {
for y := 0; y < screenHeight; y++ {
c := make([]uint16, 3)
for i := 0; i < 3; i++ {
p := g.points[i]
if p.X != x || p.Y != y {
v := math.Abs(p.Dist(&Position{x, y}))
c[i] = function.Func(v)
} else {
c[0] = 65535
c[1] = 65535
c[2] = 65535
break
}
}
image.Set(x, y, color.RGBA64{c[0], c[1], c[2], 255})
}
}
g.preScreens = append(g.preScreens, image)
}
func (gm *Game) Init() {
for i := 0; i < layerCount; i++ {
gm.NewImage()
}
for x := 0; x < screenWidth; x++ {
for y := 0; y < screenHeight; y++ {
var r, g, b int64 = 0, 0, 0
for i := 0; i < layerCount; i++ {
R, G, B, _ := gm.preScreens[i].At(x, y).RGBA()
r += int64(R)
g += int64(G)
b += int64(B)
}
r /= int64(layerCount)
g /= int64(layerCount)
b /= int64(layerCount)
gm.screen.Set(x, y, color.RGBA64{uint16(r), uint16(g), uint16(b), 65535})
}
}
}
func (g *Game) ReInit() {
g.points = make([]*Position, 3)
g.preScreens = make([]*ColorArray, 0)
g.screen = ebiten.NewImage(screenWidth, screenHeight)
g.Init()
}
func NewGame() *Game {
gm := &Game{
make([]*Position, 3),
make([]*ColorArray, 0),
ebiten.NewImage(screenWidth, screenHeight),
0,
0,
}
gm.Init()
return gm
}
func (g *Game) Update() error {
if ebiten.IsKeyPressed(ebiten.KeyEnter) && g.pressCountEnter == 0 {
file, err := os.Create(strconv.FormatInt(time.Now().Unix(), 10) + ".png")
if err != nil {
return err
}
defer file.Close()
err = png.Encode(file, g.screen)
if err != nil {
return err
}
g.pressCountEnter++
} else if !ebiten.IsKeyPressed(ebiten.KeyEnter) && g.pressCountEnter > 0 {
g.pressCountEnter = 0
}
if ebiten.IsKeyPressed(ebiten.KeySpace) && g.pressCountSpace == 0 {
g.ReInit()
g.pressCountSpace++
} else if !ebiten.IsKeyPressed(ebiten.KeySpace) && g.pressCountSpace > 0 {
g.pressCountSpace = 0
}
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
screen.DrawImage(g.screen, nil)
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
g := NewGame()
ebiten.SetWindowSize(windowWidth, windowHeight)
ebiten.SetWindowTitle("XVisuals")
if err := ebiten.RunGame(g); err != nil {
log.Fatal(err)
}
}

10
readme.md Normal file
View File

@ -0,0 +1,10 @@
# XVisuals
Visualization of mathematical formulas.
## Controls
| Key | Action |
| ----- | ------------------ |
| Space | Generate new image |
| Enter | Save current image |

55
types.go Normal file
View File

@ -0,0 +1,55 @@
package main
import (
"image/color"
"math"
)
type Function interface {
Func(float64) uint16
}
type ColorArray struct {
img []color.Color
}
func NewColorArray() *ColorArray {
ca := &ColorArray{make([]color.Color, screenWidth*screenHeight)}
ca.Clear(color.Black)
return ca
}
func (ca *ColorArray) Clear(c color.Color) {
for i := 0; i < len(ca.img); i++ {
ca.img[i] = c
}
}
func (ca *ColorArray) At(x, y int) color.Color {
position := x + (y * screenHeight)
if position > len(ca.img) || position < 0 {
return color.Black
} else {
return ca.img[position]
}
}
func (ca *ColorArray) Set(x, y int, c color.Color) {
position := x + (y * screenHeight)
if position < len(ca.img) && position >= 0 {
ca.img[position] = c
}
}
type Position struct {
X int
Y int
}
func (p *Position) Length() float64 {
return math.Sqrt(float64(p.X)*float64(p.X) + float64(p.Y)*float64(p.Y))
}
func (p *Position) Dist(P *Position) float64 {
return (&Position{p.X - P.X, p.Y - P.Y}).Length()
}

13
utility.go Normal file
View File

@ -0,0 +1,13 @@
package main
import (
"math"
)
func ToUint16(f float64) uint16 {
if f > 65535 {
return uint16(math.Mod(f, 65535))
} else {
return uint16(f)
}
}