aboutsummaryrefslogtreecommitdiff
path: root/src/verlet.odin
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
      }
    }
  }
}