javascript - 目标平稳跟随

标签 javascript html canvas

今天我想知道如何使一个 Canvas 元素顺利地跟随另一个 Canvas 元素。例如,我正在尝试制作一款 Canvas 元素连续平滑地跟随玩家(可以使用 W、A、S 和 D 移动)的游戏。我有一个想法,使用毕达哥拉斯定理来检查从 A 点( Canvas 元素)移动到 B 点(玩家)的最接近且最快的方法。但是,我没有物理方法可以做到这一点。有谁知道如何让 Canvas 元素尽可能顺利地持续跟随玩家,以便以最快的速度到达玩家手中?

这里我有一个非常糟糕的遵循方式的例子:

<!DOCTYPE html>

<html>

<head>
  <title>Target Following Test</title>
</head>

<body>
  <script src="https://code.jquery.com/jquery-2.1.0.js"></script>
  <center>
    <canvas id="canvas" width="800" height="500"></canvas>
  </center>
  <script>
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  var width = canvas.width;
  var height = canvas.height;
  var circle = function(x, y, radius, fillCircle, color) {
    ctx.beginPath();
    ctx.fillStyle = color;
    ctx.arc(x, y, radius, 0, Math.PI * 2, false);
    if (fillCircle) {
      ctx.fill();
    } else {
      ctx.stroke();
    }
  };
  var drawRect = function(x, y, color) {
    ctx.fillStyle = color;
    ctx.fillRect(x, y, 20, 20)
  }
  //Moving Obstacle
  var Obstacle = function(x, y) {
    this.x = x;
    this.y = y;
    this.vSpeed = 0;
    this.hSpeed = 0;
  }
  Obstacle.prototype.drawOb = function(color) {
    drawRect(this.x, this.y, "Red")
  }
  Obstacle.prototype.follow = function() {
    this.y += this.vSpeed
    this.x += this.hSpeed
    if (this.x < ball.x - 9) {
      this.hSpeed = 1;
    }
    if (this.x > ball.x - 10) {
      this.hSpeed = -1;
    }
    if (this.y > ball.y - 10) {
      this.vSpeed = -1;
    }
    if (this.y < ball.y - 9) {
      this.vSpeed = 1;
    }
  }
  Obstacle.prototype.checkCollision = function(direction) {
    return (ball.x - ball.radius < this.x + 20) &&
      (ball.x + ball.radius > this.x) &&
      (ball.y - ball.radius < this.y + 20) &&
      (ball.y + ball.radius > this.y);
  }
  // The Ball constructor
  var Ball = function() {
    this.x = 20
    this.y = 20
    this.xSpeed = 0;
    this.ySpeed = 0;
    this.radius = 10;
  };
  // Draw the ball at its current position
  Ball.prototype.draw = function() {
    circle(this.x, this.y, 10, true, "Black");
  };
  Ball.prototype.reposition = function(reX, reY) {
    this.x = reX;
    this.y = reY;
  }
  // Update the ball's position based on its speed
  Ball.prototype.move = function() {
    this.x += this.xSpeed;
    this.y += this.ySpeed;
    if (this.x < 11) {
      this.x = 11;
    } else if (this.x > width - 11) {
      this.x = width - 11;
    } else if (this.y < 11) {
      this.y = 11;
    } else if (this.y > height - 11) {
      this.y = height - 11;
    }
  };
  // Set the ball's direction based on a string
  Ball.prototype.setDirection = function(direction) {
    if (direction === "up") {
      this.xSpeed = 0;
      this.ySpeed = -2;
    } else if (direction === "down") {
      this.xSpeed = 0;
      this.ySpeed = 2;
    } else if (direction === "left") {
      this.xSpeed = -2;
      this.ySpeed = 0;
    } else if (direction === "right") {
      this.xSpeed = 2;
      this.ySpeed = 0;
    } else if (direction === "stop") {
      this.xSpeed = 0;
      this.ySpeed = 0;
    }
  };

  function simulate() {
    var prev_ball_x = ball.x;
    var prev_ball_y = ball.y;
    var prev_fol_x = follower.x;
    var prev_fol_y = follower.y;
    ball.move();
    follower.follow()
    if (follower.checkCollision()) {
      ball.setDirection('stop');
      follower.vSpeed = 0;
      follower.hSpeed = 0;
      follower.x = prev_fol_x;
      follower.y = prev_fol_y;
      ball.x = prev_ball_x;
      ball.y = prev_ball_y;
    }
  }

  function draw() {
    ctx.clearRect(0, 0, width, height);
    ball.draw();
    follower.drawOb();
    ctx.strokeRect(0, 0, width, height);
  }
  // An object to convert keycodes into action names
  var keyActions = {
    37: "left",
    38: "up",
    39: "right",
    40: "down"
  };
  // The keydown handler that will be called for every keypress
  $("body").keydown(function(event) {
    var direction = keyActions[event.keyCode];
    ball.setDirection(direction);
  });
  $("body").keyup(function(event) {
    ball.setDirection('stop');
  })
  setInterval(function() {
    // separate drawing and simulating phases
    simulate();
    draw();
  }, 10);
  // Create all the Objects!
  var ball = new Ball();
  var follower = new Obstacle(400, 100);
  </script>
</body>

</html>

最佳答案

注意:我还没有真正检查过你的代码...... 但希望我正确理解你的问题。如果我这样做,解决方案可能会非常简单。

最简单、快速的方法是将 Canvas 元素沿直线移动到播放器,无需毕达哥拉斯先生的帮助。为此,您需要知道玩家的位置 (x, y),您确实这样做了。

我从 AS3 问题中获取了缓动函数,但对于 JS 来说是相同的:AS 3 simple ease

每次更新时,将跟随者移动到玩家的位置:

follower.x += (player.x - follower.x) / delay;
follower.y += (player.y - follower.y) / delay;

示例:Fiddle

这不是对您的脚本的直接修复,但希望它有帮助

关于javascript - 目标平稳跟随,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37548099/

相关文章:

javascript - Jquery 数据表标题与正文不对齐

javascript - 如何使用jquery像excel一样显示负整数的括号

Javascript Canvas 没有显示任何内容

c# - 如何在windows窗体上更快地画圆?

javascript - 为什么我不通过 javascript 从 Object.key 获取值

javascript - CSV/TSV 注释行 d3

php - 如何在 javascript 中获取表单元素值并使用这些值创建 url

javascript - jQuery .submit() 成功或失败触发器

html - xPath/HTML : Select node based on related node

javascript - clearRect 不清除