| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- use fourteen_screws::{ Camera, Scene };
- use fourteen_screws::maths;
- use fourteen_screws::maths::{ ToFixedPoint, FromFixedPoint };
- use fourteen_screws::trig;
- use fourteen_screws::Tile;
- use wasm_bindgen::prelude::*;
- use web_sys;
- macro_rules! log {
- ( $( $t:tt )* ) => {
- web_sys::console::log_1(&format!( $( $t )* ).into());
- }
- }
- #[derive(PartialEq)]
- pub enum HitResult {
- Nothing,
- SlideX,
- SlideY,
- WallX,
- WallY,
- }
- pub struct Player {
- pub camera: Camera,
- move_speed: i32,
- rotate_speed: i32,
- margin: i32,
- }
- impl Player {
- pub fn new(camera: Camera, move_speed: i32, rotate_speed: i32, margin: i32) -> Player {
- Player { camera, move_speed, rotate_speed, margin }
- }
- fn translate(&mut self, mut direction: i32, amount: i32, scene: &Scene) -> HitResult {
- while direction >= trig::ANGLE_360 { direction -= trig::ANGLE_360; }
- while direction < trig::ANGLE_0 { direction += trig::ANGLE_360; }
- let xp = self.camera.x();
- let yp = self.camera.y();
- let half_tile = fourteen_screws::TILE_SIZE >> 1;
- // get bounds of the tile player currently occupies
- let x_left = xp & 0xFFC0;
- let y_top = yp & 0xFFC0;
- let x_right = x_left + fourteen_screws::TILE_SIZE;
- let y_bottom = y_top + fourteen_screws::TILE_SIZE;
- let mut hit_result = HitResult::Nothing;
- let mut x1 = xp + maths::mul(trig::cos(direction), amount.to_fp()).to_i32();
- let mut y1 = yp + maths::mul(trig::sin(direction), amount.to_fp()).to_i32();
-
- let grid_x = x_left / fourteen_screws::TILE_SIZE;
- let grid_y = y_top / fourteen_screws::TILE_SIZE;
- if x1 < xp { // are we moving left
- if let Tile::Wall(wall) = scene.x_wall(grid_x, grid_y) {
- if !wall.passable && (x1 < x_left || (x1 - x_left).abs() < self.margin) { // we crossed the wall or we're too close
- log!("Blocked Left");
- x1 = xp;
- hit_result = HitResult::SlideX;
- }
- }
- }
- if x1 > xp { // are we moving right
- if let Tile::Wall(wall) = scene.x_wall(grid_x + 1, grid_y) { // wall found in current square (right edge)
- if !wall.passable && (x1 > x_right || (x_right - x1).abs() < self.margin) { // we crossed the wall or we're too close
- x1 = xp;
- hit_result = HitResult::SlideX;
- }
- } else if let Tile::OutOfBounds = scene.x_wall(grid_x + 1, grid_y) {
- log!("TILE IS OUT OF BOUNDS");
- }
- }
- if y1 < yp { // are we moving up
- if let Tile::Wall(wall) = scene.y_wall(grid_x, grid_y) {
- if !wall.passable && (y1 < y_top || (y1 - y_top).abs() < self.margin) {
- log!("Blocked Up");
- y1 = yp;
- hit_result = HitResult::SlideY;
- }
- }
- }
- if y1 > yp { // are we moving down
- if let Tile::Wall(wall) = scene.y_wall(grid_x, grid_y + 1) {
- if !wall.passable && (y1 > y_bottom || (y_bottom - y1).abs() < self.margin) {
- log!("Blocked Down");
- y1 = yp;
- hit_result = HitResult::SlideY;
- }
- }
- }
- // A wall or object hasn't been hit yet. We must look further.
- // The current grid square will be divided into four regions:
- // A = top left; B = top right; C = bottom left; D = bottom right
- // Each of these regions will be checked to see if the player's new position
- // (x1, y1) is close to a wall or object that borders one of these regions.
- // Each grid square is 64x64 units, so each region to check is 32x32 units
- if hit_result == HitResult::Nothing {
- if y1 < (y_top + half_tile) { // new y position falls in top half
-
- // check region A-top left area of grid
- if x1 < x_left + half_tile { // new x position falls in left half
- // check adjacent x wall (to left)
- if let Tile::Wall(wall) = scene.x_wall(grid_x, grid_y - 1) {
- if !wall.passable && y1 < (y_top + self.margin) { // adjacent x wall found and new y coord is within 28 units
- if x1 < x_left + self.margin {
- if xp > x_left + (self.margin - 1) {
- x1 = xp;
- hit_result = HitResult::SlideX;
- } else {
- y1 = yp;
- hit_result = HitResult::SlideY;
- }
- }
- }
- }
- // check adjacent y wall (above)
- if let Tile::Wall(wall) = scene.y_wall(grid_x - 1, grid_y) {
- if !wall.passable && x1 < x_left + self.margin {
- if y1 < y_top + self.margin {
- if yp > y_top + (self.margin - 1) {
- y1 = yp;
- hit_result = HitResult::SlideY;
- } else {
- x1 = xp;
- hit_result = HitResult::SlideX;
- }
- }
- }
- }
- }
- // check region B-top right area
- if x1 > x_right - half_tile && hit_result == HitResult::Nothing {
-
- // check adjacent x wall (to right)
- if let Tile::Wall(wall) = scene.x_wall(grid_x + 1, grid_y - 1) {
- if !wall.passable && y1 < y_top + self.margin {
- if x1 > x_right - self.margin {
- if xp < x_right - (self.margin - 1) {
- x1 = xp;
- hit_result = HitResult::SlideX;
- } else {
- y1 = yp;
- hit_result = HitResult::SlideY;
- }
- }
- }
- }
- // check adjacent y wall (above)
- if let Tile::Wall(wall) = scene.y_wall(grid_x + 1, grid_y) {
- if !wall.passable && x1 > x_right - self.margin {
- if y1 < y_top + self.margin {
- if yp < y_top + (self.margin - 1) {
- y1 = yp;
- hit_result = HitResult::SlideY;
- } else {
- x1 = xp;
- hit_result = HitResult::SlideX;
- }
- }
- }
- }
- }
- }
- // check region C-bottom left area
- if y1 > y_top + half_tile && hit_result == HitResult::Nothing {
- if x1 < x_left + half_tile {
-
- // check adjacent x wall (to left)
- if let Tile::Wall(wall) = scene.x_wall(grid_x, grid_y + 1) {
- if !wall.passable && y1 > y_bottom - self.margin {
- if x1 < x_left + self.margin {
- if xp > x_left + (self.margin - 1) {
- x1 = xp;
- hit_result = HitResult::SlideX;
- } else {
- y1 = yp;
- hit_result = HitResult::SlideY;
- }
- }
- }
- }
-
- // check adjacent y wall (below)
- if let Tile::Wall(wall) = scene.y_wall(grid_x - 1, grid_y + 1) {
- if !wall.passable && x1 < x_left + self.margin {
- if y1 > y_bottom - self.margin {
- if yp < y_bottom - (self.margin - 1) {
- y1 = yp;
- hit_result = HitResult::SlideY;
- } else {
- x1 = xp;
- hit_result = HitResult::SlideX;
- }
- }
- }
- }
- }
- // check region D-bottom right area
- if x1 > x_right - half_tile && hit_result == HitResult::Nothing {
-
- // check adjacent x wall (to right)
- if let Tile::Wall(wall) = scene.x_wall(grid_x + 1, grid_y + 1) {
- if !wall.passable && y1 > y_bottom - self.margin {
- if x1 > x_right - self.margin {
- if xp < x_right - (self.margin - 1) {
- x1 = xp;
- hit_result = HitResult::SlideX;
- } else {
- y1 = yp;
- hit_result = HitResult::SlideY;
- }
- }
- }
- }
- // check adjacent y wall (below)
- if let Tile::Wall(wall) = scene.y_wall(grid_x + 1, grid_y + 1) {
- if !wall.passable && x1 > x_right - self.margin {
- if y1 > y_bottom - self.margin {
- if yp < y_bottom - (self.margin - 1) {
- y1 = yp;
- hit_result = HitResult::SlideY;
- } else {
- x1 = xp;
- hit_result = HitResult::SlideX;
- }
- }
- }
- }
- }
- }
- }
-
- if hit_result == HitResult::SlideX && y1 == yp {
- hit_result = HitResult::WallX;
- }
- if hit_result == HitResult::SlideY && x1 == xp {
- hit_result = HitResult::WallY;
- }
- self.camera.move_to(x1, y1);
- hit_result
- }
- pub fn forward(&mut self, scene: &Scene) -> HitResult {
- return self.translate(self.camera.angle(), self.move_speed, scene);
- }
- pub fn back(&mut self, scene: &Scene) -> HitResult {
- return self.translate(self.camera.angle() + trig::ANGLE_180, self.move_speed, scene);
- }
- pub fn strafe_left(&mut self, scene: &Scene) -> HitResult {
- return self.translate(self.camera.angle() - trig::ANGLE_90, self.move_speed, scene);
- }
- pub fn strafe_right(&mut self, scene: &Scene) -> HitResult {
- return self.translate(self.camera.angle() + trig::ANGLE_90, self.move_speed, scene);
- }
- pub fn turn_left(&mut self) {
- self.camera.rotate(-self.rotate_speed);
- log!("{}", self.camera.angle());
- }
- pub fn turn_right(&mut self) {
- self.camera.rotate(self.rotate_speed);
- log!("{}", self.camera.angle());
- }
- }
|