// 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 . const std = @import("std"); const RenderWindow = @import("sfml").graphics.RenderWindow; const Sprite = @import("sfml").graphics.Sprite; const Texture = @import("sfml").graphics.Texture; const Image = @import("sfml").graphics.Image; const Colour = @import("sfml").graphics.Color; 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; } } };