blob: 14341092a4cb7eb5612963a609a451da03ea7e65 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
package demonchime
import "core:math"
import "core:math/linalg"
import rl "vendor:raylib"
import "phys"
VERLET_STEPS :: 50
VERLET_MIN_DIST_TO_PLAYER :: 8
Verlet_Node :: struct {
pos: Vec2,
prev_pos: Vec2,
accel: Vec2,
is_static: bool,
}
Verlet_Rope :: struct {
nodes: []Verlet_Node,
node_length: f32,
}
create_verlet_node :: proc(pos: Vec2, is_static := false) -> Verlet_Node {
return Verlet_Node{
pos = pos,
prev_pos = pos,
is_static = is_static,
}
}
update_verlet_node :: proc(node: ^Verlet_Node) {
if node.is_static {
return
}
dt: f32 = FIXED_UPDATE_RATE
node.accel.y += GRAVITY
player_pos := phys.get_position(player.body)
player_dist := linalg.distance(node.pos, player_pos)
if player_dist < VERLET_MIN_DIST_TO_PLAYER {
dir := linalg.normalize(node.pos - player_pos)
node.pos = player_pos + dir * VERLET_MIN_DIST_TO_PLAYER
}
prev_pos := node.pos
node.pos = (node.pos * 2 - node.prev_pos) + node.accel * (dt*dt)
node.prev_pos = prev_pos
node.accel = {}
}
update_verlet_rope :: proc(rope: ^Verlet_Rope) {
for &node in rope.nodes {
update_verlet_node(&node)
}
for _ in 0..<VERLET_STEPS {
for i in 0..<len(rope.nodes) - 1 {
cur := &rope.nodes[i]
nex := &rope.nodes[i + 1]
dist := linalg.distance(cur.pos, nex.pos)
err := dist - rope.node_length
dir := linalg.normalize(nex.pos - cur.pos)
if cur.is_static && !nex.is_static {
nex.pos -= dir * err
} else if !cur.is_static && nex.is_static {
cur.pos += dir * err
} else if !cur.is_static && !nex.is_static {
cur.pos += dir * err * 0.5
nex.pos -= dir * err * 0.5
}
}
}
}
|