tangled
alpha
login
or
join now
voigt.tngl.sh
/
firefly-zero-playground
0
fork
atom
this repo has no description
0
fork
atom
overview
issues
pulls
2
pipelines
add circle points
voigt.tngl.sh
2 months ago
00a81d34
bf9e4d46
verified
This commit was signed with the committer's
known signature
.
voigt.tngl.sh
SSH Key Fingerprint:
SHA256:6ShT3iHt6IpCPJtT9Ndevva6c3xzr4RI2LrvKeOXH2U=
+248
4 changed files
expand all
collapse all
unified
split
coordinates
main.go
tmp
go.mod
go.sum
main.go
+33
coordinates/main.go
reviewed
···
2
2
3
3
import (
4
4
"github.com/firefly-zero/firefly-go/firefly"
5
5
+
"github.com/orsinium-labs/tinymath"
5
6
)
6
7
7
8
var (
···
39
40
firefly.ClearScreen(firefly.ColorNone)
40
41
}
41
42
43
43
+
// draw 10 points in a circular way
44
44
+
ps := CirclePointsInt(10, 5)
45
45
+
for _, p := range ps {
46
46
+
firefly.DrawPoint(translatePoint(p), firefly.ColorRed)
47
47
+
}
48
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
61
+
}
62
62
+
63
63
+
func CirclePointsInt(radius float32, n int) []firefly.Point {
64
64
+
points := make([]firefly.Point, 0, n)
65
65
+
seen := make(map[firefly.Point]struct{}, n)
66
66
+
67
67
+
// Wir samplen mit höherer Auflösung und sammeln eindeutige gerundete Punkte,
68
68
+
// bis wir n Stück haben.
69
69
+
// Oversample-Faktor dynamisch hochdrehen, falls nötig.
70
70
+
for oversample := n * 2; len(points) < n; oversample *= 2 {
71
71
+
for i := 0; i < oversample && len(points) < n; i++ {
72
72
+
angle := 2 * tinymath.Pi * float32(i) / float32(oversample)
73
73
+
74
74
+
x := int(tinymath.Round(radius * tinymath.Cos(angle)))
75
75
+
y := int(tinymath.Round(radius * tinymath.Sin(angle)))
76
76
+
77
77
+
p := firefly.Point{X: x, Y: y}
78
78
+
if _, ok := seen[p]; ok {
79
79
+
continue
80
80
+
}
81
81
+
seen[p] = struct{}{}
82
82
+
points = append(points, p)
83
83
+
}
84
84
+
}
85
85
+
86
86
+
return points
54
87
}
55
88
56
89
func drawCoordinateSystem() {
+11
tmp/go.mod
reviewed
···
1
1
+
module github.com/voigt/firefly-zero-playground/tmp
2
2
+
3
3
+
go 1.25.0
4
4
+
5
5
+
require github.com/gen2brain/raylib-go/raylib v0.55.1
6
6
+
7
7
+
require (
8
8
+
github.com/ebitengine/purego v0.7.1 // indirect
9
9
+
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
10
10
+
golang.org/x/sys v0.20.0 // indirect
11
11
+
)
+8
tmp/go.sum
reviewed
···
1
1
+
github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
2
2
+
github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
3
3
+
github.com/gen2brain/raylib-go/raylib v0.55.1 h1:1rdc10WvvYjtj7qijHnV9T38/WuvlT6IIL+PaZ6cNA8=
4
4
+
github.com/gen2brain/raylib-go/raylib v0.55.1/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q=
5
5
+
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
6
6
+
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
7
7
+
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
8
8
+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+196
tmp/main.go
reviewed
···
1
1
+
package main
2
2
+
3
3
+
import (
4
4
+
rl "github.com/gen2brain/raylib-go/raylib"
5
5
+
)
6
6
+
7
7
+
type Player struct {
8
8
+
Pos rl.Vector2
9
9
+
Vel rl.Vector2
10
10
+
Size rl.Vector2
11
11
+
OnGround bool
12
12
+
13
13
+
// Timers (seconds)
14
14
+
CoyoteTimer float32
15
15
+
JumpBuffer float32
16
16
+
Jumping bool // true after jump start until we land
17
17
+
}
18
18
+
19
19
+
func clamp(v, min, max float32) float32 {
20
20
+
if v < min {
21
21
+
return min
22
22
+
}
23
23
+
if v > max {
24
24
+
return max
25
25
+
}
26
26
+
return v
27
27
+
}
28
28
+
29
29
+
func approach(current, target, delta float32) float32 {
30
30
+
if current < target {
31
31
+
current += delta
32
32
+
if current > target {
33
33
+
return target
34
34
+
}
35
35
+
return current
36
36
+
}
37
37
+
if current > target {
38
38
+
current -= delta
39
39
+
if current < target {
40
40
+
return target
41
41
+
}
42
42
+
return current
43
43
+
}
44
44
+
return current
45
45
+
}
46
46
+
47
47
+
func main() {
48
48
+
const screenW, screenH int32 = 960, 540
49
49
+
rl.InitWindow(screenW, screenH, "raylib-go: platformer feel (accel/decel + buffer/coyote + variable jump + fast-fall)")
50
50
+
defer rl.CloseWindow()
51
51
+
rl.SetTargetFPS(60)
52
52
+
53
53
+
groundY := float32(screenH - 80)
54
54
+
groundThickness := float32(80)
55
55
+
56
56
+
p := Player{
57
57
+
Pos: rl.NewVector2(120, groundY-60),
58
58
+
Vel: rl.NewVector2(0, 0),
59
59
+
Size: rl.NewVector2(50, 60),
60
60
+
}
61
61
+
62
62
+
// ---------- Tuning ----------
63
63
+
maxRunSpeed := float32(380)
64
64
+
65
65
+
// Separate accel/decel
66
66
+
groundAccel := float32(2600)
67
67
+
groundDecel := float32(3200)
68
68
+
airAccel := float32(1400)
69
69
+
airDecel := float32(300)
70
70
+
71
71
+
// Jump
72
72
+
jumpSpeed := float32(640)
73
73
+
74
74
+
// Variable jump height: cut velocity when releasing jump while going up
75
75
+
jumpCutMultiplier := float32(0.35)
76
76
+
77
77
+
// Coyote time + jump buffer (seconds)
78
78
+
coyoteTime := float32(0.10)
79
79
+
jumpBufferTime := float32(0.12)
80
80
+
81
81
+
// --- Fast-fall tuning ---
82
82
+
// Base gravity is used when rising (Vel.Y < 0) and jump is held.
83
83
+
// When falling (Vel.Y > 0) we apply higher gravity (fallMultiplier).
84
84
+
// When jump is released early during rise, we apply higher gravity too (lowJumpMultiplier).
85
85
+
gravity := float32(1200) // "floatier" base on the way up
86
86
+
fallMultiplier := float32(2.2) // faster fall
87
87
+
lowJumpMultiplier := float32(2.6) // stronger pull-down if jump released early
88
88
+
maxFallSpeed := float32(2200) // higher terminal velocity for snappy fall
89
89
+
90
90
+
for !rl.WindowShouldClose() {
91
91
+
dt := rl.GetFrameTime()
92
92
+
93
93
+
// ---- Input ----
94
94
+
var dir float32 = 0
95
95
+
if rl.IsKeyDown(rl.KeyA) || rl.IsKeyDown(rl.KeyLeft) {
96
96
+
dir -= 1
97
97
+
}
98
98
+
if rl.IsKeyDown(rl.KeyD) || rl.IsKeyDown(rl.KeyRight) {
99
99
+
dir += 1
100
100
+
}
101
101
+
102
102
+
jumpPressed := rl.IsKeyPressed(rl.KeySpace)
103
103
+
jumpHeld := rl.IsKeyDown(rl.KeySpace)
104
104
+
jumpReleased := rl.IsKeyReleased(rl.KeySpace)
105
105
+
106
106
+
// ---- Timers ----
107
107
+
if p.OnGround {
108
108
+
p.CoyoteTimer = coyoteTime
109
109
+
} else {
110
110
+
p.CoyoteTimer = clamp(p.CoyoteTimer-dt, 0, 999)
111
111
+
}
112
112
+
113
113
+
if jumpPressed {
114
114
+
p.JumpBuffer = jumpBufferTime
115
115
+
} else {
116
116
+
p.JumpBuffer = clamp(p.JumpBuffer-dt, 0, 999)
117
117
+
}
118
118
+
119
119
+
// ---- Horizontal movement (accel/decel) ----
120
120
+
if p.OnGround {
121
121
+
if dir != 0 {
122
122
+
target := dir * maxRunSpeed
123
123
+
p.Vel.X = approach(p.Vel.X, target, groundAccel*dt)
124
124
+
} else {
125
125
+
p.Vel.X = approach(p.Vel.X, 0, groundDecel*dt)
126
126
+
}
127
127
+
} else {
128
128
+
if dir != 0 {
129
129
+
target := dir * maxRunSpeed
130
130
+
p.Vel.X = approach(p.Vel.X, target, airAccel*dt)
131
131
+
} else {
132
132
+
p.Vel.X = approach(p.Vel.X, 0, airDecel*dt)
133
133
+
}
134
134
+
}
135
135
+
p.Vel.X = clamp(p.Vel.X, -maxRunSpeed, maxRunSpeed)
136
136
+
137
137
+
// ---- Jump using buffer + coyote ----
138
138
+
if p.JumpBuffer > 0 && p.CoyoteTimer > 0 {
139
139
+
p.Vel.Y = -jumpSpeed
140
140
+
p.OnGround = false
141
141
+
p.CoyoteTimer = 0
142
142
+
p.JumpBuffer = 0
143
143
+
p.Jumping = true
144
144
+
}
145
145
+
146
146
+
// ---- Variable jump height (jump cut) ----
147
147
+
// Optional: keep it, feels good in addition to lowJumpMultiplier gravity.
148
148
+
if jumpReleased && p.Jumping && p.Vel.Y < 0 {
149
149
+
p.Vel.Y *= jumpCutMultiplier
150
150
+
}
151
151
+
152
152
+
// ---- Fast-fall gravity ----
153
153
+
// If falling: stronger gravity.
154
154
+
// If rising but jump not held: stronger gravity (low jump).
155
155
+
g := gravity
156
156
+
if p.Vel.Y > 0 {
157
157
+
g *= fallMultiplier
158
158
+
} else if p.Vel.Y < 0 && !jumpHeld {
159
159
+
g *= lowJumpMultiplier
160
160
+
}
161
161
+
p.Vel.Y += g * dt
162
162
+
p.Vel.Y = clamp(p.Vel.Y, -100000, maxFallSpeed)
163
163
+
164
164
+
// ---- Integrate ----
165
165
+
p.Pos.X += p.Vel.X * dt
166
166
+
p.Pos.Y += p.Vel.Y * dt
167
167
+
168
168
+
// ---- Ground collision ----
169
169
+
playerBottom := p.Pos.Y + p.Size.Y
170
170
+
if playerBottom >= groundY {
171
171
+
p.Pos.Y = groundY - p.Size.Y
172
172
+
p.Vel.Y = 0
173
173
+
p.OnGround = true
174
174
+
p.Jumping = false
175
175
+
} else {
176
176
+
p.OnGround = false
177
177
+
}
178
178
+
179
179
+
// ---- Screen bounds (X) ----
180
180
+
p.Pos.X = clamp(p.Pos.X, 0, float32(screenW)-p.Size.X)
181
181
+
if p.Pos.X == 0 || p.Pos.X == float32(screenW)-p.Size.X {
182
182
+
p.Vel.X = 0
183
183
+
}
184
184
+
185
185
+
// ---- Render ----
186
186
+
rl.BeginDrawing()
187
187
+
rl.ClearBackground(rl.RayWhite)
188
188
+
189
189
+
rl.DrawRectangle(0, int32(groundY), screenW, int32(groundThickness), rl.LightGray)
190
190
+
rl.DrawRectangleV(p.Pos, p.Size, rl.DarkBlue)
191
191
+
192
192
+
rl.DrawText("Move: A/D or Left/Right Jump: Space (buffer+coyote+variable+fast-fall)", 20, 20, 20, rl.Black)
193
193
+
194
194
+
rl.EndDrawing()
195
195
+
}
196
196
+
}