aboutsummaryrefslogtreecommitdiff
path: root/src/player.zig
blob: 44488c5447fc2e801d5f3e879ebb5367b372141f (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
// This file is part of ZiRC
//
// Copyright (C) 2021, tslil clingman
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

const std = @import("std");

const level = @import("level.zig");
const constants = @import("constants.zig");

pub const Player = struct {
    pos_x: f32,
    pos_y: f32,
    ang: f32,
    vel_x: f32 = 0,
    vel_y: f32 = 0,
    acc_x: f32 = 0,
    acc_y: f32 = 0,
    height: f32 = 2.0 * (1.8 / 2.5), // TODO
    anim_step: f32 = 0,

    // standing still at the given location, looking in direction ang
    pub fn new(pos_x: f32, pos_y: f32, ang: f32) @This() {
        return Player{
            .pos_x = pos_x,
            .pos_y = pos_y,
            .ang = ang,
        };
    }

    pub fn tick(self: *Player, map: level.Map) void {
        const dt = 1 / 30.0;
        const v_min = 0.8;
        const v_decay = 1 / 1.25;

        var next_x = self.pos_x + self.vel_x * dt;
        var next_y = self.pos_y + self.vel_y * dt;

        // Collision detection
        const min_dist: f32 = 0.1;
        const fx = std.math.floor(self.pos_x);
        const fy = std.math.floor(self.pos_y);
        const ix = @floatToInt(i32, fx);
        const iy = @floatToInt(i32, fy);
        const nix = @floatToInt(i32, std.math.floor(next_x + if (self.vel_x > 0) min_dist else -min_dist));
        const niy = @floatToInt(i32, std.math.floor(next_y + if (self.vel_y > 0) min_dist else -min_dist));

        if (!map.inBounds(nix, iy) or
            blk: {
            // const cell = map.lookup(nix, iy);
            // if (cell.floor_height > 0) break :blk true;
            // if (cell.ceiling_height < self.height) break :blk true;
            break :blk false;
        }) {
            next_x = fx + if (self.vel_x > 0) 1 - min_dist else min_dist;
            self.vel_x = 0;
            self.acc_x = 0;
        }

        if (!map.inBounds(ix, niy)) { // or map.lookup(ix, niy).floor_height > 0
            next_y = fy + if (self.vel_y > 0) 1 - min_dist else min_dist;
            self.vel_y = 0;
            self.acc_y = 0;
        }

        // Update position
        self.pos_x = next_x;
        self.pos_y = next_y;

        // Update velocity
        self.vel_x += self.acc_x * dt;
        self.vel_y += self.acc_y * dt;

        const vd = v_decay * std.math.sqrt(self.vel_x * self.vel_x + self.vel_y * self.vel_y);
        if (vd < v_min) {
            self.vel_x = 0;
            self.vel_y = 0;
        } else {
            // If we're moving update our animation state
            self.anim_step += 1;
            self.height -= std.math.sin(self.anim_step / 10 * std.math.pi) * 0.015;

            self.vel_x *= v_decay;
            self.vel_y *= v_decay;
        }
    }
};