this repo has no description

add init for coordinates #4

closed opened by voigt.tngl.sh targeting main from add-gamepad-demo
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:6q572hlx7omtsszji5w2fyw3/sh.tangled.repo.pull/3mbx4exjkzy22
+446
Diff #0
README.md

This is a binary file and will not be displayed.

+33
coordinates/main.go
··· 2 2 3 3 import ( 4 4 "github.com/firefly-zero/firefly-go/firefly" 5 + "github.com/orsinium-labs/tinymath" 5 6 ) 6 7 7 8 var ( ··· 39 40 firefly.ClearScreen(firefly.ColorNone) 40 41 } 41 42 43 + // draw 10 points in a circular way 44 + ps := CirclePointsInt(10, 5) 45 + for _, p := range ps { 46 + firefly.DrawPoint(translatePoint(p), firefly.ColorRed) 47 + } 48 + 42 49 // points in 4 quadrants 43 50 firefly.DrawPoint(translatePoint(firefly.Point{X: 10, Y: 10}), firefly.ColorCyan) 44 51 firefly.DrawPoint(translatePoint(firefly.Point{X: 10, Y: -10}), firefly.ColorGreen) ··· 51 58 y := -p.Y + SCREENHEIGHT/2 52 59 // firefly.LogDebug(strings.Join([]string{"x: ", strconv.Itoa(x), ", y: ", strconv.Itoa(y)}, " ")) 53 60 return firefly.Point{X: x, Y: y} 61 + } 62 + 63 + func CirclePointsInt(radius float32, n int) []firefly.Point { 64 + points := make([]firefly.Point, 0, n) 65 + seen := make(map[firefly.Point]struct{}, n) 66 + 67 + // Wir samplen mit höherer Auflösung und sammeln eindeutige gerundete Punkte, 68 + // bis wir n Stück haben. 69 + // Oversample-Faktor dynamisch hochdrehen, falls nötig. 70 + for oversample := n * 2; len(points) < n; oversample *= 2 { 71 + for i := 0; i < oversample && len(points) < n; i++ { 72 + angle := 2 * tinymath.Pi * float32(i) / float32(oversample) 73 + 74 + x := int(tinymath.Round(radius * tinymath.Cos(angle))) 75 + y := int(tinymath.Round(radius * tinymath.Sin(angle))) 76 + 77 + p := firefly.Point{X: x, Y: y} 78 + if _, ok := seen[p]; ok { 79 + continue 80 + } 81 + seen[p] = struct{}{} 82 + points = append(points, p) 83 + } 84 + } 85 + 86 + return points 54 87 } 55 88 56 89 func drawCoordinateSystem() {
+11
tmp/go.mod
··· 1 + module github.com/voigt/firefly-zero-playground/tmp 2 + 3 + go 1.25.0 4 + 5 + require github.com/gen2brain/raylib-go/raylib v0.55.1 6 + 7 + require ( 8 + github.com/ebitengine/purego v0.7.1 // indirect 9 + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect 10 + golang.org/x/sys v0.20.0 // indirect 11 + )
+8
tmp/go.sum
··· 1 + github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA= 2 + github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= 3 + github.com/gen2brain/raylib-go/raylib v0.55.1 h1:1rdc10WvvYjtj7qijHnV9T38/WuvlT6IIL+PaZ6cNA8= 4 + github.com/gen2brain/raylib-go/raylib v0.55.1/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q= 5 + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= 6 + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= 7 + golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= 8 + golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+196
tmp/main.go
··· 1 + package main 2 + 3 + import ( 4 + rl "github.com/gen2brain/raylib-go/raylib" 5 + ) 6 + 7 + type Player struct { 8 + Pos rl.Vector2 9 + Vel rl.Vector2 10 + Size rl.Vector2 11 + OnGround bool 12 + 13 + // Timers (seconds) 14 + CoyoteTimer float32 15 + JumpBuffer float32 16 + Jumping bool // true after jump start until we land 17 + } 18 + 19 + func clamp(v, min, max float32) float32 { 20 + if v < min { 21 + return min 22 + } 23 + if v > max { 24 + return max 25 + } 26 + return v 27 + } 28 + 29 + func approach(current, target, delta float32) float32 { 30 + if current < target { 31 + current += delta 32 + if current > target { 33 + return target 34 + } 35 + return current 36 + } 37 + if current > target { 38 + current -= delta 39 + if current < target { 40 + return target 41 + } 42 + return current 43 + } 44 + return current 45 + } 46 + 47 + func main() { 48 + const screenW, screenH int32 = 960, 540 49 + rl.InitWindow(screenW, screenH, "raylib-go: platformer feel (accel/decel + buffer/coyote + variable jump + fast-fall)") 50 + defer rl.CloseWindow() 51 + rl.SetTargetFPS(60) 52 + 53 + groundY := float32(screenH - 80) 54 + groundThickness := float32(80) 55 + 56 + p := Player{ 57 + Pos: rl.NewVector2(120, groundY-60), 58 + Vel: rl.NewVector2(0, 0), 59 + Size: rl.NewVector2(50, 60), 60 + } 61 + 62 + // ---------- Tuning ---------- 63 + maxRunSpeed := float32(380) 64 + 65 + // Separate accel/decel 66 + groundAccel := float32(2600) 67 + groundDecel := float32(3200) 68 + airAccel := float32(1400) 69 + airDecel := float32(300) 70 + 71 + // Jump 72 + jumpSpeed := float32(640) 73 + 74 + // Variable jump height: cut velocity when releasing jump while going up 75 + jumpCutMultiplier := float32(0.35) 76 + 77 + // Coyote time + jump buffer (seconds) 78 + coyoteTime := float32(0.10) 79 + jumpBufferTime := float32(0.12) 80 + 81 + // --- Fast-fall tuning --- 82 + // Base gravity is used when rising (Vel.Y < 0) and jump is held. 83 + // When falling (Vel.Y > 0) we apply higher gravity (fallMultiplier). 84 + // When jump is released early during rise, we apply higher gravity too (lowJumpMultiplier). 85 + gravity := float32(1200) // "floatier" base on the way up 86 + fallMultiplier := float32(2.2) // faster fall 87 + lowJumpMultiplier := float32(2.6) // stronger pull-down if jump released early 88 + maxFallSpeed := float32(2200) // higher terminal velocity for snappy fall 89 + 90 + for !rl.WindowShouldClose() { 91 + dt := rl.GetFrameTime() 92 + 93 + // ---- Input ---- 94 + var dir float32 = 0 95 + if rl.IsKeyDown(rl.KeyA) || rl.IsKeyDown(rl.KeyLeft) { 96 + dir -= 1 97 + } 98 + if rl.IsKeyDown(rl.KeyD) || rl.IsKeyDown(rl.KeyRight) { 99 + dir += 1 100 + } 101 + 102 + jumpPressed := rl.IsKeyPressed(rl.KeySpace) 103 + jumpHeld := rl.IsKeyDown(rl.KeySpace) 104 + jumpReleased := rl.IsKeyReleased(rl.KeySpace) 105 + 106 + // ---- Timers ---- 107 + if p.OnGround { 108 + p.CoyoteTimer = coyoteTime 109 + } else { 110 + p.CoyoteTimer = clamp(p.CoyoteTimer-dt, 0, 999) 111 + } 112 + 113 + if jumpPressed { 114 + p.JumpBuffer = jumpBufferTime 115 + } else { 116 + p.JumpBuffer = clamp(p.JumpBuffer-dt, 0, 999) 117 + } 118 + 119 + // ---- Horizontal movement (accel/decel) ---- 120 + if p.OnGround { 121 + if dir != 0 { 122 + target := dir * maxRunSpeed 123 + p.Vel.X = approach(p.Vel.X, target, groundAccel*dt) 124 + } else { 125 + p.Vel.X = approach(p.Vel.X, 0, groundDecel*dt) 126 + } 127 + } else { 128 + if dir != 0 { 129 + target := dir * maxRunSpeed 130 + p.Vel.X = approach(p.Vel.X, target, airAccel*dt) 131 + } else { 132 + p.Vel.X = approach(p.Vel.X, 0, airDecel*dt) 133 + } 134 + } 135 + p.Vel.X = clamp(p.Vel.X, -maxRunSpeed, maxRunSpeed) 136 + 137 + // ---- Jump using buffer + coyote ---- 138 + if p.JumpBuffer > 0 && p.CoyoteTimer > 0 { 139 + p.Vel.Y = -jumpSpeed 140 + p.OnGround = false 141 + p.CoyoteTimer = 0 142 + p.JumpBuffer = 0 143 + p.Jumping = true 144 + } 145 + 146 + // ---- Variable jump height (jump cut) ---- 147 + // Optional: keep it, feels good in addition to lowJumpMultiplier gravity. 148 + if jumpReleased && p.Jumping && p.Vel.Y < 0 { 149 + p.Vel.Y *= jumpCutMultiplier 150 + } 151 + 152 + // ---- Fast-fall gravity ---- 153 + // If falling: stronger gravity. 154 + // If rising but jump not held: stronger gravity (low jump). 155 + g := gravity 156 + if p.Vel.Y > 0 { 157 + g *= fallMultiplier 158 + } else if p.Vel.Y < 0 && !jumpHeld { 159 + g *= lowJumpMultiplier 160 + } 161 + p.Vel.Y += g * dt 162 + p.Vel.Y = clamp(p.Vel.Y, -100000, maxFallSpeed) 163 + 164 + // ---- Integrate ---- 165 + p.Pos.X += p.Vel.X * dt 166 + p.Pos.Y += p.Vel.Y * dt 167 + 168 + // ---- Ground collision ---- 169 + playerBottom := p.Pos.Y + p.Size.Y 170 + if playerBottom >= groundY { 171 + p.Pos.Y = groundY - p.Size.Y 172 + p.Vel.Y = 0 173 + p.OnGround = true 174 + p.Jumping = false 175 + } else { 176 + p.OnGround = false 177 + } 178 + 179 + // ---- Screen bounds (X) ---- 180 + p.Pos.X = clamp(p.Pos.X, 0, float32(screenW)-p.Size.X) 181 + if p.Pos.X == 0 || p.Pos.X == float32(screenW)-p.Size.X { 182 + p.Vel.X = 0 183 + } 184 + 185 + // ---- Render ---- 186 + rl.BeginDrawing() 187 + rl.ClearBackground(rl.RayWhite) 188 + 189 + rl.DrawRectangle(0, int32(groundY), screenW, int32(groundThickness), rl.LightGray) 190 + rl.DrawRectangleV(p.Pos, p.Size, rl.DarkBlue) 191 + 192 + rl.DrawText("Move: A/D or Left/Right Jump: Space (buffer+coyote+variable+fast-fall)", 20, 20, 20, rl.Black) 193 + 194 + rl.EndDrawing() 195 + } 196 + }
+47
touchpad/.zed/tasks.json
··· 1 + [ 2 + { 3 + "label": "Build & Run Firefly Emulator", 4 + "command": "firefly_cli build && firefly-emulator --id voigt.go-gamepad", 5 + //"args": [], 6 + // Env overrides for the command, will be appended to the terminal's environment from the settings. 7 + // "env": { "foo": "bar" }, 8 + // Current working directory to spawn the command into, defaults to current project root. 9 + //"cwd": "/path/to/working/directory", 10 + // Whether to use a new terminal tab or reuse the existing one to spawn the process, defaults to `false`. 11 + "use_new_terminal": false, 12 + // Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish, defaults to `false`. 13 + // "allow_concurrent_runs": false, 14 + // What to do with the terminal pane and tab, after the command was started: 15 + // * `always` — always show the task's pane, and focus the corresponding tab in it (default) 16 + // * `no_focus` — always show the task's pane, add the task's tab in it, but don't focus it 17 + // * `never` — do not alter focus, but still add/reuse the task's tab in its pane 18 + "reveal": "always", 19 + // What to do with the terminal pane and tab, after the command has finished: 20 + // * `never` — Do nothing when the command finishes (default) 21 + // * `always` — always hide the terminal tab, hide the pane also if it was the last tab in it 22 + // * `on_success` — hide the terminal tab on task success only, otherwise behaves similar to `always` 23 + "hide": "never", 24 + // Which shell to use when running a task inside the terminal. 25 + // May take 3 values: 26 + // 1. (default) Use the system's default terminal configuration in /etc/passwd 27 + // "shell": "system" 28 + // 2. A program: 29 + // "shell": { 30 + // "program": "sh" 31 + // } 32 + // 3. A program with arguments: 33 + // "shell": { 34 + // "with_arguments": { 35 + // "program": "/bin/bash", 36 + // "args": ["--login"] 37 + // } 38 + // } 39 + "shell": "system", 40 + // Whether to show the task line in the output of the spawned task, defaults to `true`. 41 + "show_summary": true, 42 + // Whether to show the command line in the output of the spawned task, defaults to `true`. 43 + "show_command": true, 44 + // Represents the tags for inline runnable indicators, or spawning multiple tasks at once. 45 + // "tags": [] 46 + }, 47 + ]
+4
touchpad/firefly.toml
··· 1 + author_id = "voigt" 2 + app_id = "go-gamepad" 3 + author_name = "Christoph Voigt" 4 + app_name = "Gamepad Demo (Go)"
+132
touchpad/gamepad.go
··· 1 + package main 2 + 3 + import ff "github.com/firefly-zero/firefly-go/firefly" 4 + 5 + var ( 6 + point *ff.Point 7 + center ff.Point 8 + 9 + buttonN bool 10 + buttonE bool 11 + buttonS bool 12 + buttonW bool 13 + ) 14 + 15 + const ( 16 + radius = 26 17 + third = ff.Width / 3 18 + 19 + touchYcenter = third 20 + touchXcenter = ff.Height/2 - radius/2 21 + buttonYcenter = third * 2 22 + buttonXcenter = ff.Height/2 - radius/2 23 + ) 24 + 25 + func init() { 26 + ff.Render = render 27 + ff.Update = update 28 + } 29 + 30 + func update() { 31 + // Buttons 32 + buttons := ff.ReadButtons(ff.Combined) 33 + 34 + if buttons.N { 35 + buttonN = true 36 + } else { 37 + buttonN = false 38 + } 39 + if buttons.E { 40 + buttonE = true 41 + } else { 42 + buttonE = false 43 + } 44 + if buttons.S { 45 + buttonS = true 46 + } else { 47 + buttonS = false 48 + } 49 + if buttons.W { 50 + buttonW = true 51 + } else { 52 + buttonW = false 53 + } 54 + 55 + // Touchpad 56 + center = ff.Point{ 57 + X: touchXcenter, 58 + Y: touchYcenter, 59 + // X: ff.Width/2 - 45, 60 + // Y: ff.Height / 2, 61 + } 62 + 63 + input, pressed := ff.ReadPad(ff.Combined) 64 + if pressed { 65 + point = &ff.Point{ 66 + X: center.X + input.X/20 - radius, 67 + Y: center.Y - input.Y/20 - radius, 68 + } 69 + } else { 70 + point = nil 71 + } 72 + } 73 + 74 + func render() { 75 + ff.ClearScreen(ff.ColorWhite) 76 + 77 + // ff.DrawCircle(ff.Point{X: buttonYcenter - radius, Y: buttonXcenter - radius}, radius*3, ff.Style{FillColor: ff.ColorWhite, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1}) 78 + // ff.DrawCircle(ff.Point{X: touchYcenter - radius*2, Y: touchXcenter - radius}, radius*3, ff.Style{FillColor: ff.ColorWhite, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1}) 79 + ff.DrawLine(ff.Point{buttonYcenter, 0}, ff.Point{buttonYcenter, ff.Height}, ff.LineStyle{ff.ColorGray, 1}) 80 + ff.DrawLine(ff.Point{touchYcenter, 0}, ff.Point{touchYcenter, ff.Height}, ff.LineStyle{ff.ColorGray, 1}) 81 + ff.DrawLine(ff.Point{0, ff.Height / 2}, ff.Point{ff.Width, ff.Height / 2}, ff.LineStyle{ff.ColorGray, 1}) 82 + 83 + // Buttons 84 + // B 85 + styleE := ff.Style{FillColor: ff.ColorWhite, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1} 86 + if buttonE { 87 + styleE = ff.Style{FillColor: ff.ColorRed, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1} 88 + } 89 + ff.DrawCircle(ff.Point{X: buttonYcenter + radius, Y: buttonXcenter}, radius, styleE) 90 + 91 + // A 92 + styleS := ff.Style{FillColor: ff.ColorWhite, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1} 93 + if buttonS { 94 + styleS = ff.Style{FillColor: ff.ColorGreen, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1} 95 + } 96 + ff.DrawCircle(ff.Point{X: buttonYcenter, Y: buttonXcenter + radius}, radius, styleS) 97 + 98 + // Y 99 + styleN := ff.Style{FillColor: ff.ColorWhite, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1} 100 + if buttonN { 101 + styleN = ff.Style{FillColor: ff.ColorYellow, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1} 102 + } 103 + ff.DrawCircle(ff.Point{X: buttonYcenter, Y: buttonXcenter - radius}, radius, styleN) 104 + 105 + // X 106 + styleW := ff.Style{FillColor: ff.ColorWhite, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1} 107 + if buttonW { 108 + styleW = ff.Style{FillColor: ff.ColorBlue, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1} 109 + } 110 + ff.DrawCircle(ff.Point{X: buttonYcenter - radius, Y: buttonXcenter}, radius, styleW) 111 + 112 + // Touchpad 113 + style := ff.Style{ 114 + FillColor: ff.ColorWhite, 115 + StrokeColor: ff.ColorDarkBlue, 116 + StrokeWidth: 1, 117 + } 118 + 119 + ff.DrawCircle(ff.Point{ 120 + X: touchYcenter - radius*2, 121 + Y: touchXcenter - radius, 122 + }, radius*3, style) 123 + 124 + style = ff.Style{ 125 + FillColor: ff.ColorBlue, 126 + StrokeColor: ff.ColorDarkBlue, 127 + StrokeWidth: 1, 128 + } 129 + if point != nil { 130 + ff.DrawCircle(*point, radius, style) 131 + } 132 + }
+7
touchpad/go.mod
··· 1 + module touchpad 2 + 3 + go 1.24.0 4 + 5 + require github.com/firefly-zero/firefly-go v0.9.5 6 + 7 + require github.com/orsinium-labs/tinymath v1.0.0 // indirect
+8
touchpad/go.sum
··· 1 + github.com/firefly-zero/firefly-go v0.8.1 h1:evb25qj7ELM0wy20IIHtW8+4MI1i+wqVOiCsYdTuh3M= 2 + github.com/firefly-zero/firefly-go v0.8.1/go.mod h1:+X/XGyPdES51OESkV8NSf1mszEBZionoROM7x2pBofw= 3 + github.com/firefly-zero/firefly-go v0.9.5 h1:BzBr4t76bDVVFwNaWJixs1XasqLNBIdg0k9JXblBfU4= 4 + github.com/firefly-zero/firefly-go v0.9.5/go.mod h1:+X/XGyPdES51OESkV8NSf1mszEBZionoROM7x2pBofw= 5 + github.com/orsinium-labs/tinymath v1.0.0 h1:Uzp3GmjWIBxMObx4MQi9ACDu4Q8WKjSRakB1OMo9Bu0= 6 + github.com/orsinium-labs/tinymath v1.0.0/go.mod h1:WPXX6ei3KSXG7JfA03a+ekCYaY9SWN4I+JRl2p6ck+A= 7 + github.com/orsinium-labs/tinymath v1.1.0 h1:KomdsyLHB7vE3f1nRAJF2dyf1m/gnM2HxfTeV1vS5UA= 8 + github.com/orsinium-labs/tinymath v1.1.0/go.mod h1:WPXX6ei3KSXG7JfA03a+ekCYaY9SWN4I+JRl2p6ck+A=

History

2 rounds 0 comments
sign up or login to add to the discussion
3 commits
expand
add init for coordinates
add coordinate system
add points to the coordinate system
expand 0 comments
closed without merging
voigt.tngl.sh submitted #0
5 commits
expand
add init for coordinates
add coordinate system
add points to the coordinate system
add circle points
add gamepad demo
expand 0 comments