From 7ce791036510c40d2a04215de3580434b36bb84e Mon Sep 17 00:00:00 2001 From: Dietrich Featherston Date: Sun, 14 Dec 2025 01:04:00 -0600 Subject: [PATCH] initial working sketch in go on raylib --- .gitignore | 1 + flake.lock | 61 ++++++++++++++++++++++++++++++ flake.nix | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 14 +++++++ go.sum | 10 +++++ main.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 294 insertions(+) create mode 100644 .gitignore create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48b8bf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor/ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..5a7111f --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1765363881, + "narHash": "sha256-3C3xWn8/2Zzr7sxVBmpc1H1QfxjNfta5IMFe3O9ZEPw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d2b1213bf5ec5e62d96b003ab4b5cbc42abfc0d0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..b30842d --- /dev/null +++ b/flake.nix @@ -0,0 +1,100 @@ +{ + description = "Go + raylib-go sketch project"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { inherit system; }; + + # Your Go module name (optional; buildGoModule can infer from go.mod) + pname = "sumi"; + version = "0.1.0"; + + # Common native deps for raylib + windowing/audio. + # raylib itself in nixpkgs already brings many deps, but being explicit + # here makes devShell + builds more predictable. + nativeDeps = with pkgs; [ + pkg-config + ]; + + raylibDeps = with pkgs; [ + raylib + + # X11 stack (works under XWayland too) + xorg.libX11 + xorg.libXcursor + xorg.libXi + xorg.libXinerama + xorg.libXrandr + + # Wayland stack (raylib/glfw can use this depending on build/options) + wayland + libxkbcommon + + # GL + audio + mesa + alsa-lib + pulseaudio + ]; + in + { + packages.default = pkgs.buildGoModule { + inherit pname version; + + src = self; + + # raylib-go uses CGO to link against libraylib + env.CGO_ENABLED = 1; + + # GOFLAGS = [ "-mod=mod" ]; + # proxyVendor = true; + + nativeBuildInputs = nativeDeps; + buildInputs = raylibDeps; + + # If your main package isn’t at repo root, set this (examples): + # subPackages = [ "./cmd/sketch" ]; + + # First build will fail with a message containing the correct hash. + vendorHash = "sha256-pcNGzxHripkn9lX2R9O29nYvR+hWLxIev4KJmEhQwC8="; + + # Optional: strip for smaller binaries + ldflags = [ + "-s" + "-w" + ]; + + doCheck = false; + }; + + devShells.default = pkgs.mkShell { + # Tools you want while hacking + packages = with pkgs; [ + go + gopls + delve + gotools + ]; + + nativeBuildInputs = nativeDeps; + buildInputs = raylibDeps; + + # Helps CGO find headers/libs + shellHook = '' + export CGO_ENABLED=1 + ''; + }; + } + ); +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..39f4da8 --- /dev/null +++ b/go.mod @@ -0,0 +1,14 @@ +module github.com/d2fn/sumi + +go 1.22 + +require ( + github.com/gen2brain/raylib-go/raylib v0.55.1 + github.com/ojrac/opensimplex-go v1.0.2 +) + +require ( + github.com/ebitengine/purego v0.7.1 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect + golang.org/x/sys v0.20.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b1ddf72 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA= +github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= +github.com/gen2brain/raylib-go/raylib v0.55.1 h1:1rdc10WvvYjtj7qijHnV9T38/WuvlT6IIL+PaZ6cNA8= +github.com/gen2brain/raylib-go/raylib v0.55.1/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q= +github.com/ojrac/opensimplex-go v1.0.2 h1:l4vs0D+JCakcu5OV0kJ99oEaWJfggSc9jiLpxaWvSzs= +github.com/ojrac/opensimplex-go v1.0.2/go.mod h1:NwbXFFbXcdGgIFdiA7/REME+7n/lOf1TuEbLiZYOWnM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/main.go b/main.go new file mode 100644 index 0000000..a512140 --- /dev/null +++ b/main.go @@ -0,0 +1,108 @@ +package main + +import ( + "fmt" + "github.com/gen2brain/raylib-go/raylib" + "github.com/ojrac/opensimplex-go" +) + +func main() { + + const ( + screenWidth = 2200 + screenHeight = 1200 + ) + + rl.InitWindow(screenWidth, screenHeight, "sumi sierpinski arrow") + + var camera rl.Camera2D + camera.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.0001, 0.00)) * 2 - 1 + fmt.Printf("angles[%d] = %.2f\n", i, angles[i]) + } + + 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() + rl.Translatef(screenWidth/2, screenHeight/2, 0); + + // 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(250*initAngle, 0, 0, 1) + rl.Translatef(100*initAngle, 100*initAngle, 0) + + for range 1000 { + rl.DrawLine(0, 0, 10, 0, rl.Black) + rl.Translatef(10, 0, 0) + rl.Rotatef(angle, 0, 0, 1) + angleIndex++ + angleIndex = angleIndex%len(angles) + angle += angles[angleIndex] + } + rl.PopMatrix() + + /* + rl.PushMatrix() + rl.Translatef(0, 25*50, 0) + rl.Rotatef(90, 1, 0, 0) + rl.DrawGrid(100, 50) + rl.PopMatrix() + */ + + rl.EndMode2D() + + rl.DrawText("Mouse right button drag to move, mouse wheel to zoom", 10, 10, 20, rl.White) + + rl.EndDrawing() + } + + rl.CloseWindow() +} +