aboutsummaryrefslogtreecommitdiff
path: root/src/player.odin
blob: 1dd79aee37f89e593570549f317b9acb7c73a65c (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package demonchime

import "core:fmt"
import "core:math"

import sapp "shared:sokol/app"

import "draw"

Player :: struct {
  pos: Vec2,
  vel: Vec2,
  anim: draw.Animation,
  sprite: draw.Sprite,
  on_floor: bool
}

PLAYER_SPEED :: 100
PLAYER_ACCEL :: 10
PLAYER_JUMP_FORCE :: 350

init_player :: proc(p: ^Player) {
  p.pos = Vec2{50, 50}

  anim_ok := draw.init_anim_data(&p.anim, "res/robot2.json")
  if !anim_ok {
    fmt.println("coult not load animation")
    sapp.quit()
    return
  }

  draw.init_sprite(&p.sprite, p.anim.image_path, p.anim)

  p.sprite.offset = Vec2{
    -math.floor(f32(p.sprite.width / 2)),
    -f32(p.sprite.height)
  }
}

deinit_player :: proc(p: ^Player) {
  draw.delete_anim_data(p.anim)
}

update_player :: proc(p: ^Player, dt: f32) {
  input: f32

  if is_keybind_down(state.input, state.input.move_left) {
    input -= 1
  }
  if is_keybind_down(state.input, state.input.move_right) {
    input += 1
  }

  if input != 0 {
    draw.set_sprite_active_tag(&p.sprite, "down_run")
    p.sprite.scale.x = math.sign(input)
  } else {
    draw.set_sprite_active_tag(&p.sprite, "down_idle")
  }

  if is_keybind_down(state.input, state.input.jump) && p.on_floor {
    p.vel.y = -PLAYER_JUMP_FORCE
  }

  p.vel.x = math.lerp(
    p.vel.x,
    input * PLAYER_SPEED,
    math.pow(0.5, dt * PLAYER_ACCEL),
  )
  p.vel.y = math.min(p.vel.y + GRAVITY * dt, TERMINAL_VELOCITY)

  res_pos := p.pos + p.vel * dt

  rect_size := Vec2{f32(p.sprite.width), f32(p.sprite.height)}
  rect_offset := Vec2{-rect_size.x / 2, -rect_size.y}

  rect := Rect{
    res_pos + rect_offset,
    rect_size,
  }

  p.on_floor = false

  iter := iter_entity_list(state.platform_list)
  for plat in entity_list_iter(&iter) {
    if aabb(rect, plat.rect) {
      prev_rect := Rect{
        p.pos + rect_offset,
        rect_size,
      }
      if aabb_hori(prev_rect, plat.rect) {
        if p.vel.y > 0 {
          res_pos.y = plat.rect.start.y - rect.size.y - rect_offset.y
          p.on_floor = true
        } else {
          res_pos.y = plat.rect.start.y + plat.rect.size.y - rect_offset.y
        }
        p.vel.y = 0
      } else if aabb_vert(prev_rect, plat.rect) {
        if p.vel.x > 0 {
          res_pos.x = plat.rect.start.x - rect.size.x - rect_offset.x
        } else {
          res_pos.x = plat.rect.start.x + plat.rect.size.x - rect_offset.x
        }
        p.vel.x = 0
      }
    }
  }

  p.pos = res_pos

  p.sprite.pos = p.pos

  draw.update_sprite(&p.sprite, dt)
}

draw_player :: proc(p: Player) {
  draw.sprite(&state.renderer, p.sprite)
}