Путаница между астероидом и компьютерным пространством в JavaScript

#javascript

#javascript

Вопрос:

Я делал проект кодирования, в котором я просто создаю шутер для 2 игроков с астероидами. По какой-то причине мои астероиды иногда исчезают, и я не могу найти способ остановить это. Я попробовал несколько стратегий отладки, которые я нашел в Интернете. Простите меня за беспорядочный код, потому что я относительно новичок в программировании и хотел бы получить некоторую помощь. Это весь мой код —

 const FPS = 60;
const FRICTION = 0.7;
const PROJ_DIST = 0.6;
const PROJ_EXPLODE_DUR = 0.3;
const PROJ_MAX = 3;
const PROJ_SPEED = 600;
const ROIDS_JAG = 0.4;
const ROIDS_NUM = 5;
const ROIDS_SPEED = 50;
const ROIDS_SIZE = 100;
const ROIDS_VERT = 10;
const PLAYER_SIZE = 30;
const ROT_SPEED = 250;
const PLAYER_THRUST = 5;
const PLAYER_MAX_SPEED = 12;
const SHOW_BOUNDING = false;
const SHOW_CENTER = false;

const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");

canvas.width = innerWidth;
canvas.height = innerHeight;
addEventListener("resize", () => {
  canvas.width = innerWidth
  canvas.height = innerHeight
})

class Player {
  constructor(x, y, r, c, a, pc, p, scoreEl) {
    this.x = x;
    this.y = y;
    this.or = r;
    this.r = r;
    this.p = p
    this.c = c;
    this.a = a
    this.rot = 0
    this.pc = pc
    this.v = {
      x: 0,
      y: 0
    }
    this.thrusting = false
    this.projectiles = []
    this.destroy = []
    this.top = {
      x: this.x   4 / 3 * this.r * Math.cos(this.a),
      y: this.y - 4 / 3 * this.r * Math.sin(this.a)
    }
    this.left = {
      x: this.x - this.r * (2 / 3 * Math.cos(this.a)   Math.sin(this.a)),
      y: this.y   this.r * (2 / 3 * Math.sin(this.a) - Math.cos(this.a))
    }

    this.right = {
      x: this.x - this.r * (2 / 3 * Math.cos(this.a) - Math.sin(this.a)),
      y: this.y   this.r * (2 / 3 * Math.sin(this.a)   Math.cos(this.a))
    }
    this.thrustdir = 0
    this.canShoot = false
    this.scoreEl = scoreEl
    this.score = 0
    this.exploding = false;
  }

  draw() {
    ctx.fillStyle = this.c
    ctx.beginPath();
    ctx.moveTo(this.top.x, this.top.y);
    ctx.lineTo(this.left.x, this.left.y);
    ctx.lineTo(this.right.x, this.right.y);
    ctx.closePath();
    ctx.fill();
  }

  update() {
    this.setPoints();
    this.move();
    this.edge()
    this.Update();
    this.scoreEl.innerHTML = this.score
    this.draw()
  }

  rotate(dir) {
    this.rot = toRadians(ROT_SPEED * dir) / FPS
  }

  move() {
    if (!this.exploding) {
      if (this.thrusting) {
        this.v.x  = (Math.abs(this.v.x) < PLAYER_MAX_SPEED) ? PLAYER_THRUST * this.thrustdir * Math.cos(this.a) / FPS : 0;
        this.v.y -= (Math.abs(this.v.y) < PLAYER_MAX_SPEED) ? PLAYER_THRUST * this.thrustdir * Math.sin(this.a) / FPS : 0;
      } else {
        this.v.x -= FRICTION * this.v.x / FPS
        this.v.y -= FRICTION * this.v.y / FPS
      }
      this.a  = this.rot
      this.x  = this.v.x
      this.y  = this.v.y
    }
  }

  thrust(dir) {
    this.thrustdir = dir;
    this.thrusting = (dir == 0) ? false : true
  }

  edge() {
    if (this.x < 0 - this.r) {
      this.x = canvas.width   this.r
    } else if (this.x > canvas.width   this.r) {
      this.x = 0 - this.r
    }

    if (this.y < 0 - this.r) {
      this.y = canvas.height   this.r
    } else if (this.y > canvas.height   this.r) {
      this.y = 0 - this.r
    }
  }

  setPoints() {
    this.top = {
      x: this.x   4 / 3 * this.r * Math.cos(this.a),
      y: this.y - 4 / 3 * this.r * Math.sin(this.a)
    }
    this.left = {
      x: this.x - this.r * (2 / 3 * Math.cos(this.a)   Math.sin(this.a)),
      y: this.y   this.r * (2 / 3 * Math.sin(this.a) - Math.cos(this.a))
    }

    this.right = {
      x: this.x - this.r * (2 / 3 * Math.cos(this.a) - Math.sin(this.a)),
      y: this.y   this.r * (2 / 3 * Math.sin(this.a)   Math.cos(this.a))
    }
  }

  Update() {
    this.projectiles.forEach((projectile, index) => {
      projectile.update();
      if (projectile.kill()) {
        this.projectiles.splice(index, 1)
      }
      asteroids.forEach((asteroid, index2) => {
        this.explode(asteroid, projectile, false, () => {
            asteroids.splice(index2, 1)
            var radius = Math.random() * (ROIDS_SIZE - 4)   4
            if (Math.random() < 0.5) {
              var x = Math.random() < 0.5 ? 0 - radius * 2 : canvas.width   radius * 2
              var y = Math.random() * canvas.height
            } else {
              var x = Math.random() * canvas.width
              var y = Math.random() < 0.5 ? 0 - radius * 2 : canvas.height   radius * 2
            }
            asteroids.push(new Asteroid(x, y, radius, {
              x: Math.random() * ROIDS_SPEED / FPS * (Math.random() < 0.5 ? 1 : -1),
              y: Math.random() * ROIDS_SPEED / FPS * (Math.random() < 0.5 ? 1 : -1)
            }))
          },
          (asteroid) => {
            if (!this.exploding) {
              this.score  = 5
            }
            this.projectiles.splice(index, 1)
            if (asteroid.r > 35) {
              gsap.to(asteroid, 0.5, {
                r: asteroid.r - 30
              }).then(asteroid.or = asteroid.r)
              return false;
            }
            return true;

          })
      })
    });

    asteroids.forEach((asteroid, index) => {
      this.explode(this, asteroid, true, () => {
        this.respawn(this);
      }, () => {
        this.v = {
          x: 0,
          y: 0
        }
      })
    })

    this.projectiles.forEach((projectile, index) => {
      this.explode(players[this.p == 0 ? 1 : 0], projectile, false, () => {
        this.respawn(players[this.p == 0 ? 1 : 0]);
        console.log("hit")
      }, () => {
        if (!players[this.p == 0 ? 1 : 0].exploding) {
          this.score  = 10
        };
        players[this.p == 0 ? 1 : 0].v = {
          x: 0,
          y: 0
        };
        this.projectiles.splice(index, 1);
        return true
      })
    })

  }

  shoot() {
    if (this.canShoot amp;amp; this.projectiles.length < PROJ_MAX) {
      this.projectiles.push(new Projectile(this.top.x, this.top.y, 5, this.pc, {
        x: PROJ_SPEED * Math.cos(this.a) / FPS,
        y: -PROJ_SPEED * Math.sin(this.a) / FPS,
      }));
      this.canShoot = false
    }
  }

  respawn(object) {
    if (object.exploding) {
      object.v = {
        x: 0,
        y: 0
      }
      do {
        var x = Math.random() < 0.5
        var y = Math.random() < 0.5
        object.x = x ? object.or * 2 : canvas.width - object.or * 2
        object.y = y ? object.or * 4 : canvas.height - object.or * 2
      } while (this.hitAsteroid(object.x, object.y))
      object.a = this.getStartAngle(x, y)
      gsap.to(object, {
        r: object.or
      })
      object.exploding = false
    }
  }

  explode(object1, object2, place, t = function() {}, f = function(object1 = null, object2 = null, object3 = null) {
    return false
  }) {
    if (this.hit(object1, object2)) {
      var x = place ? object1.x : object2.x
      var y = place ? object1.y : object2.y
      for (var i = 0; i < object1.r * 2; i  ) {
        particles.push(new Particle(x, y, Math.random() * 2, object1.c, {
          x: (Math.random() - 0.5) * object1.r / 15,
          y: (Math.random() - 0.5) * object1.r / 15
        }))
      }
      if (f(object1, object2, this)) {
        gsap.to(object1, 0.5, {
          r: 0
        }).then(t)
      }
      object1.exploding = true
    }
  }

  hit(object1, object2) {
    return Math.hypot(object2.x - object1.x, object2.y - object1.y) < object2.r   object1.r
  }

  hitAsteroid(x, y) {
    asteroids.forEach((asteroid) => {
      if (this.hit({x: x, y: y}, asteroid)) {
        return true
      }
    })
    return false;
  }

  getStartAngle(x, y) {
    if (x amp;amp; y) {
      return toRadians(315)
    } else if (x) {
      return toRadians(45)
    } else if (y) {
      return toRadians(225)
    } else {
      return toRadians(135)
    }
  }

}

class Projectile {
  constructor(x, y, r, c, v) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.c = c;
    this.v = v;
    this.dist = 0
  }

  draw() {
    ctx.fillStyle = this.c
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
    ctx.closePath();
    ctx.fill();
  }

  update() {
    this.x  = this.v.x
    this.y  = this.v.y
    this.dist  = Math.hypot(this.v.x, this.v.y)
    this.edge();
    this.draw()
  }

  kill() {
    return (this.dist > PROJ_DIST * canvas.width)
  }

  edge() {
    if (this.x < 0 - this.r) {
      this.x = canvas.width   this.r
    } else if (this.x > canvas.width   this.r) {
      this.x = 0 - this.r
    }

    if (this.y < 0 - this.r) {
      this.y = canvas.height   this.r
    } else if (this.y > canvas.height   this.r) {
      this.y = 0 - this.r
    }
  }
}

class Asteroid {
  constructor(x, y, r, v) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.c = `hsl(${Math.random() * 360}, 50%, 50%)`;
    this.v = v;
    this.a = toRadians(Math.random() * 360);
    this.vert = Math.floor(Math.random() * (ROIDS_VERT   1)   ROIDS_VERT / 2);
    this.offset = this.createOffset();
    this.or = r;
  }

  draw() {
    ctx.fillStyle = this.c
    ctx.beginPath();
    ctx.moveTo(
      this.x   this.r * this.offset[0] * Math.cos(this.a),
      this.y   this.r * this.offset[0] * Math.sin(this.a)
    );
    for (var j = 1; j < this.vert; j  ) {
      ctx.lineTo(
        this.x   this.r * this.offset[j] * Math.cos(this.a   j * Math.PI * 2 / this.vert),
        this.y   this.r * this.offset[j] * Math.sin(this.a   j * Math.PI * 2 / this.vert)
      )
    }
    ctx.closePath();
    ctx.fill();
  }

  update() {
    this.x  = this.v.x
    this.y  = this.v.y
    this.edge()
    this.draw()
  }

  edge() {
    if (this.x < 0 - this.r) {
      this.x = canvas.width   this.r
    } else if (this.x > canvas.width   this.r) {
      this.x = 0 - this.r
    }

    if (this.y < 0 - this.r) {
      this.y = canvas.height   this.r
    } else if (this.y > canvas.height   this.r) {
      this.y = 0 - this.r
    }
  }

  createOffset() {
    var off = [];
    for (var i = 0; i < this.vert; i  ) {
      off.push(Math.random() * ROIDS_JAG * 2   1 - ROIDS_JAG)
    }
    return off
  }

  hit(projectile) {
    return (Math.hypot(projectile.x - this.x, projectile.y - this.y) < this.r   projectile.r)
  }


}

class Particle {
  constructor(x, y, r, c, v) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.c = c;
    this.v = v;
    this.al = 1
  }

  draw() {
    ctx.save()
    ctx.globalAlpha = this.al
    ctx.fillStyle = this.c
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
    ctx.closePath();
    ctx.fill();
    ctx.restore();
  }

  update() {
    this.draw()
    this.x  = this.v.x
    this.y  = this.v.y
    this.al -= 0.01
  }
}

const player1 = new Player(canvas.width / 2, canvas.height / 2, PLAYER_SIZE / 2, "blue", toRadians(Math.random() * 360), "blue", 0, document.getElementById("score1"));
const player2 = new Player(canvas.width / 2, canvas.height / 2, PLAYER_SIZE / 2, "red", toRadians(Math.random() * 360), "red", 1, document.getElementById("score2"));
const asteroids = []
for (var i = 0; i < ROIDS_NUM; i  ) {
  var radius = Math.random() * (ROIDS_SIZE - 4)   4
  if (Math.random() < 0.5) {
    var x = Math.random() < 0.5 ? 0 - radius : canvas.width   radius
    var y = Math.random() * canvas.height
  } else {
    var x = Math.random() * canvas.width
    var y = Math.random() < 0.5 ? 0 - radius : canvas.height   radius
  }
  asteroids.push(new Asteroid(x, y, radius, {
    x: Math.random() * ROIDS_SPEED / FPS * (Math.random() < 0.5 ? 1 : -1),
    y: Math.random() * ROIDS_SPEED / FPS * (Math.random() < 0.5 ? 1 : -1)
  }))
}
const particles = []
const players = [player1, player2]


addEventListener("keydown", (event) => {
  switch (event.keyCode) {
    case 32:
      player1.shoot()
      break;
    case 37:
      player1.rotate(1)
      break;
    case 39:
      player1.rotate(-1)
      break;

    case 38:
      player1.thrust(1)
      break;
    case 40:
      player1.thrust(-1)
      break;

    case 69:
      player2.shoot()
      break;
    case 65:
      player2.rotate(1)
      break;
    case 68:
      player2.rotate(-1)
      break;

    case 87:
      player2.thrust(1)
      break;
    case 83:
      player2.thrust(-1)
      break;

  }
});

addEventListener("keyup", (event) => {
  switch (event.keyCode) {
    case 37:
    case 39:
      player1.rot = 0
      break;
    case 38:
    case 40:
      player1.thrust(0);
    case 32:
      player1.canShoot = true;
    case 65:
    case 68:
      player2.rot = 0
      break;
    case 87:
    case 83:
      player2.thrust(0);
    case 69:
      player2.canShoot = true;
  }
});

var animationId;

function animate() {
  animationId = requestAnimationFrame(animate);
  ctx.fillStyle = "rgba(0, 0, 0, 0.1)"
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  asteroids.forEach((asteroid) => {
    asteroid.update()
  })
  particles.forEach((particle, index) => {
    if (particle.al <= 0) {
      particles.splice(index, 1)
    } else {
      particle.update();
    }
  })
  player1.update();
  player2.update()
}

function toRadians(a) {
  return a / 180 * Math.PI
}



animate();  
 body {
  margin: 0;
  height: 100vh;
  width: 100vw;
}

.scores {
  width: 100vw;
}

#score1 {
  display: inline-flex;
  flex: right;
}

#score2 {
  position: absolute;
  top: 0;
  left: calc(100vw - 4rem);
}  
 <!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <link rel="stylesheet" href="./tailwind.min.css">
  <title>Asteroids</title>
</head>

<body>
  <div class="flex scores w-full">
    <div class="fixed text-white ml-4 mt-1 text-4xl text-left" id="score1">0</div>
    <div class="fixed text-white ml-4 mt-1 text-4xl text-right" id="score2">0</div>
  </div>
  <canvas id="gameCanvas"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.5.1/gsap.min.js" integrity="sha512-IQLehpLoVS4fNzl7IfH8Iowfm5 RiMGtHykgZJl9AWMgqx0AmJ6cRWcB GaGVtIsnC4voMfm8f2vwtY 6oPjpQ==" crossorigin="anonymous"></script>
  <script src="./game.js"></script>
</body>

</html>  

Комментарии:

1. Это довольно много кода, который нужно просмотреть. Я думаю, вам, возможно, потребуется более конкретно разобраться в проблеме, прежде чем кто-то сможет помочь.

2. Извините!! Как мне отредактировать свой код. В настоящее время проблема заключается в Javascript, Player. Update(), Player.explode(), Player.respawn(), астероиды, но я не уверен, где именно. Я также подумал, что вам нужно будет просмотреть весь код, чтобы разобраться в нем. Извините!!