package main import ( "log" "os" "github.com/gen2brain/raylib-go/raylib" "github.com/ojrac/opensimplex-go" "math" ) func clamp01(v float64) float64 { if v < 0 { return 0 } if v > 1 { return 1 } return v } func GrayCurve(v, k float64) rl.Color { v = math.Pow(clamp01(v), k) // k < 1 boosts highlights, k > 1 boosts shadows c := uint8(v * 255) return rl.Color{R: c, G: c, B: c, A: 255} } func sierpinskiArrow(order int, length float64) { rl.Scalef(1, -1, 1) //rl.Rotatef(180, 0, 0, 1) if order == 0 { curve(order, length, 60) } else { rl.Rotatef(60, 0, 0, 1) curve(order, length, -60) } } func curve(order int, length float64, angle float64) { if order == 0 { len := int32(length) rl.DrawLine(0, 0, len, 0, rl.Black) rl.Translatef(float32(len), 0, 0) } else { curve(order-1, length/2, -angle) rl.Rotatef(float32(angle), 0, 0, 1) curve(order-1, length/2, angle) rl.Rotatef(float32(angle), 0, 0, 1) curve(order-1, length/2, -angle) } } func main() { const ( screenWidth = 1200 screenHeight = 700 snapshotsDir = "snapshots" ) os.MkdirAll(snapshotsDir, 0755) log := log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile) storage, err := NewStorage(snapshotsDir) if err != nil { log.Printf("Error loading storage: %v\n", err) os.Exit(1) } rl.InitWindow(screenWidth, screenHeight, "sumi sierpinski arrow") var camera = rl.Camera2D{ Target: rl.Vector2{X: 0, Y: 0}, Offset: rl.Vector2{X: float32(screenWidth) / 2, Y: float32(screenHeight) / 2}, Rotation: 0, Zoom: 1.0, } rl.SetTargetFPS(60) angles := make([]float32, 1000) noise := opensimplex.NewNormalized(0) for i := range len(angles) { angles[i] = float32(noise.Eval2(float64(i)*0.05, 0.00))*0.1 - 0.05 } frameNum := 0 for !rl.WindowShouldClose() { frameNum++ if rl.IsMouseButtonDown(rl.MouseRightButton) { delta := rl.GetMouseDelta() delta = rl.Vector2Scale(delta, -1.0/camera.Zoom) camera.Target = rl.Vector2Add(camera.Target, delta) } // Zoom based on mouse wheel wheel := rl.GetMouseWheelMove() if wheel != 0 { // Get the world point that is under the mouse mouseWorldPos := rl.GetScreenToWorld2D(rl.GetMousePosition(), camera) // Set the offset to where the mouse is camera.Offset = rl.GetMousePosition() // Set the target to match, so that the camera maps the world space point // under the cursor to the screen space point under the cursor at any zoom camera.Target = mouseWorldPos // Zoom increment const zoomIncrement float32 = 0.125 camera.Zoom += (wheel * zoomIncrement) if camera.Zoom < zoomIncrement { camera.Zoom = zoomIncrement } } rl.BeginDrawing() rl.ClearBackground(rl.RayWhite) rl.BeginMode2D(camera) rl.PushMatrix() /** for x := range screenWidth { for y := range screenHeight { sp := rl.Vector2 { X: float32(x), Y: float32(y) }; wp := rl.GetScreenToWorld2D(sp, camera); normVal := noise.Eval2(float64(wp.X), float64(wp.Y)) rl.DrawPixelV(wp, GrayCurve(normVal, 0.8)); } } **/ // initial transform by halfway again through angle array angleIndex := frameNum % len(angles) angle := angles[angleIndex] initAngle := angles[(angleIndex+len(angles)/2)%len(angles)] rl.Rotatef(2500*initAngle, 0, 0, 1) rl.Translatef(100*initAngle, 100*initAngle, 0) stepSize := int32(1) for range 1000 { rl.DrawLine(0, 0, stepSize, 0, rl.Black) rl.Translatef(float32(stepSize), 0, 0) rl.Rotatef(angle, 0, 0, 1) angleIndex++ angleIndex = angleIndex % len(angles) angle += angles[angleIndex] } rl.PopMatrix() rl.PushMatrix() //rl.Translatef(-screenWidth/2, screenHeight/2, 0) sierpinskiArrow(9, 800) rl.PopMatrix() /* rl.PushMatrix() rl.Translatef(0, 25*50, 0) rl.Rotatef(90, 1, 0, 0) rl.DrawGrid(100, 50) rl.PopMatrix() */ rl.EndMode2D() if rl.IsKeyDown(rl.KeySpace) { img := rl.LoadImageFromScreen() defer rl.UnloadImage(img) if _, err := storage.Save(img); err != nil { log.Printf("Error saving snapshot: %v\n", err) } } rl.DrawText("Mouse right button drag to move, mouse wheel to zoom", 10, 10, 20, rl.White) rl.EndDrawing() } rl.CloseWindow() }