获取HTML Canvas中旋转矩形剑的坐标

获取HTML Canvas中旋转矩形剑的坐标

本文旨在解决html canvas中绘制旋转矩形剑,并获取其端点坐标的问题。通过分析现有代码,明确了剑的端点计算方式,并提供了修正后的sword.update()函数,确保剑随角色手臂旋转,同时提供了完整的可运行代码示例,方便开发者直接应用到自己的项目中。

在HTML Canvas中绘制旋转的矩形,特别是像剑这样的武器,涉及到坐标计算和角度旋转。以下是如何获取Canvas中旋转矩形剑的坐标并正确绘制它的步骤:

理解坐标系统

Canvas的坐标系统原点(0, 0)位于左上角。X轴正方向向右,Y轴正方向向下。所有坐标计算都基于这个原点。

关键代码分析与修正

原代码中sword.update()函数计算剑的端点坐标存在问题,导致剑的绘制不正确。正确的逻辑是:

立即学习前端免费学习笔记(深入)”;

  • 左手的位置是剑的一个端点。
  • 右手的位置是剑的另一个端点。
  • 剑的另外两个端点可以通过在右手位置的基础上,增加Player.swordLength来确定。

因此,需要修改sword.update()函数如下:

 update() {     this.draw();     this.Lx = LeftHand.x;     this.Ly = LeftHand.y;     this.Rx = RightHand.x;     this.Ry = RightHand.y;      this.Lsx = LeftHand.x;     this.Lsy = LeftHand.y;     this.Rsx = RightHand.x + Player.swordLength;     this.Rsy = RightHand.y + Player.swordLength;   }

这段代码的关键在于正确设置了Lsx、Lsy、Rsx和Rsy的值,确保剑的形状和旋转与手臂的运动保持一致。

完整代码示例

以下是修正后的完整代码示例,可以直接复制并运行:

var c = document.getElementById("canvas"); var ctx = c.getContext("2d");  c.width = window.innerWidth; c.height = window.innerHeight;  var mouse = { x: c.width / 2, y: c.height / 2 };  window.addEventListener("resize", function (event) {   c.width = window.innerWidth;   c.height = window.innerHeight; });  window.addEventListener("mousemove", function (event) {   mouse.x = event.clientX;   mouse.y = event.clientY; });  class player {   constructor(x, y, r, color, v) {     this.x = x;     this.y = y;     this.r = r;     this.v = v;     this.color = color;     this.swordLength = 200;   }    draw() {     ctx.beginPath();     ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);     ctx.fillStyle = this.color;     ctx.fill();     ctx.closePath();   }    update() {     this.draw();     var dy = mouse.y - this.y;     var dx = mouse.x - this.x;     const angle = Math.atan2(dy, dx);      var vx = Math.cos(angle) * this.v;     var vy = Math.sin(angle) * this.v;      if (Math.abs(vx) > Math.abs(dx)) {       vx = dx;     }      if (Math.abs(vy) > Math.abs(dy)) {       vy = dy;     }     this.x += vx;     this.y += vy;   } }  class leftHand {   constructor(x, y, r, color) {     this.x = x;     this.y = y;     this.color = color;     this.angle = 0;     this.r = r;     this.Area = 40;   }    draw() {     ctx.beginPath();     ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);     ctx.fillStyle = this.color;     ctx.fill();     ctx.closePath();   }    update() {     this.draw();     this.x = Player.x + this.Area * Math.cos(this.angle / 180);     this.y = Player.y + this.Area * Math.sin(this.angle / 180);     this.angle += 30;   } }  class rightHand {   constructor(x, y, r, color) {     this.x = x;     this.y = y;     this.color = color;     this.angle = 90;     this.r = r;     this.Area = 40;   }    draw() {     ctx.beginPath();     ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);     ctx.fillStyle = this.color;     ctx.fill();     ctx.closePath();   }    update() {     this.draw();     this.x = Player.x + this.Area * Math.cos(this.angle / 180);     this.y = Player.y + this.Area * Math.sin(this.angle / 180);     this.angle += 30;   } }  class sword {   constructor(Lx, Ly, Rx, Ry, color, Lsx, Lsy, Rsx, Rsy) {     this.Lx = Lx;     this.Ly = Ly;     this.Rx = Rx;     this.Ry = Ry;     this.Lsx = Lsx;     this.Lsy = Lsy;     this.Rsx = Rsx;     this.Rsy = Rsy;     this.color = color;   }    draw() {     ctx.beginPath();     ctx.moveTo(this.Lx, this.Ly);     ctx.lineTo(this.Rx, this.Ry);     ctx.lineTo(this.Rsx, this.Rsy);     ctx.lineTo(this.Lsx, this.Lsy);     ctx.fillStyle = this.color;     ctx.fill();     ctx.closePath();   }    update() {     this.draw();     this.Lx = LeftHand.x;     this.Ly = LeftHand.y;     this.Rx = RightHand.x;     this.Ry = RightHand.y;      this.Lsx = LeftHand.x;     this.Lsy = LeftHand.y;     this.Rsx = RightHand.x + Player.swordLength;     this.Rsy = RightHand.y + Player.swordLength;   } }  const Player = new player(c.width / 2, c.height / 2, 30, "blue", 10);  const LeftHand = new leftHand(   c.width / 2 + 40 * Math.cos(0 / 180),   c.height / 2 + 40 * Math.sin(0 / 180),   10,   "red" );  const RightHand = new rightHand(   c.width / 2 + 40 * Math.cos(90 / 180),   c.height / 2 + 40 * Math.sin(90 / 180),   10,   "yellow" );  const Sword = new sword(   c.width / 2 + 40 * Math.cos(0 / 180),   c.height / 2 + 40 * Math.sin(0 / 180),   c.width / 2 + 40 * Math.cos(90 / 180),   c.height / 2 + 40 * Math.sin(90 / 180),   "black",   c.width / 2 + 40 * Math.cos(0 / 180),   c.height / 2 + 40 * Math.sin(0 / 180),   c.width / 2 + 40 * Math.cos(90 / 180),   c.height / 2 + 40 * Math.sin(90 / 180) );  function animate() {   requestAnimationFrame(animate);   ctx.clearRect(0, 0, c.width, c.height);   Player.update();   LeftHand.update();   RightHand.update();   Sword.update(); }  animate();

HTML文件:

<!DOCTYPE html> <html lang="en">  <head>   <meta charset="UTF-8">   <meta http-equiv="X-UA-Compatible" content="IE=edge">   <meta name="viewport" content="width=device-width, initial-scale=1.0">   <title>Canvas Sword</title>   <style>     body {       margin: 0;       overflow: hidden; /* Prevent scrollbars */     }      canvas {       display: block; /* Remove extra space below canvas */     }   </style> </head>  <body>   <canvas id="canvas"></canvas>    <script>     // JavaScript code from previous response goes here     var c = document.getElementById("canvas");     var ctx = c.getContext("2d");      c.width = window.innerWidth;     c.height = window.innerHeight;      var mouse = { x: c.width / 2, y: c.height / 2 };      window.addEventListener("resize", function (event) {       c.width = window.innerWidth;       c.height = window.innerHeight;     });      window.addEventListener("mousemove", function (event) {       mouse.x = event.clientX;       mouse.y = event.clientY;     });      class player {       constructor(x, y, r, color, v) {         this.x = x;         this.y = y;         this.r = r;         this.v = v;         this.color = color;         this.swordLength = 200;       }        draw() {         ctx.beginPath();         ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);         ctx.fillStyle = this.color;         ctx.fill();         ctx.closePath();       }        update() {         this.draw();         var dy = mouse.y - this.y;         var dx = mouse.x - this.x;         const angle = Math.atan2(dy, dx);          var vx = Math.cos(angle) * this.v;         var vy = Math.sin(angle) * this.v;          if (Math.abs(vx) > Math.abs(dx)) {           vx = dx;         }          if (Math.abs(vy) > Math.abs(dy)) {           vy = dy;         }         this.x += vx;         this.y += vy;       }     }      class leftHand {       constructor(x, y, r, color) {         this.x = x;         this.y = y;         this.color = color;         this.angle = 0;         this.r = r;         this.Area = 40;       }        draw() {         ctx.beginPath();         ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);         ctx.fillStyle = this.color;         ctx.fill();         ctx.closePath();       }        update() {         this.draw();         this.x = Player.x + this.Area * Math.cos(this.angle / 180);         this.y = Player.y + this.Area * Math.sin(this.angle / 180);         this.angle += 30;       }     }      class rightHand {       constructor(x, y, r, color) {         this.x = x;         this.y = y;         this.color = color;         this.angle = 90;         this.r = r;         this.Area = 40;       }        draw() {         ctx.beginPath();         ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);         ctx.fillStyle = this.color;         ctx.fill();         ctx.closePath();       }        update() {         this.draw();         this.x = Player.x + this.Area * Math.cos(this.angle / 180);         this.y = Player.y + this.Area * Math.sin(this.angle / 180);         this.angle += 30;       }     }      class sword {       constructor(Lx, Ly, Rx, Ry, color, Lsx, Lsy, Rsx, Rsy) {         this.Lx = Lx;         this.Ly = Ly;         this.Rx = Rx;         this.Ry = Ry;         this.Lsx = Lsx;         this.Lsy = Lsy;         this.Rsx = Rsx;         this.Rsy = Rsy;         this.color = color;       }        draw() {         ctx.beginPath();         ctx.moveTo(this.Lx, this.Ly);         ctx.lineTo(this.Rx, this.Ry);         ctx.lineTo(this.Rsx, this.Rsy);         ctx.lineTo(this.Lsx, this.Lsy);         ctx.fillStyle = this.color;         ctx.fill();         ctx.closePath();       }        update() {         this.draw();         this.Lx = LeftHand.x;         this.Ly = LeftHand.y;         this.Rx = RightHand.x;         this.Ry = RightHand.y;          this.Lsx = LeftHand.x;         this.Lsy = LeftHand.y;         this.Rsx = RightHand.x + Player.swordLength;         this.Rsy = RightHand.y + Player.swordLength;       }     }      const Player = new player(c.width / 2, c.height / 2, 30, "blue", 10);      const LeftHand = new leftHand(       c.width / 2 + 40 * Math.cos(0 / 180),       c.height / 2 + 40 * Math.sin(0 / 180),       10,       "red"     );      const RightHand = new rightHand(       c.width / 2 + 40 * Math.cos(90 / 180),       c.height / 2 + 40 * Math.sin(90 / 180),       10,       "yellow"     );      const Sword = new sword(       c.width / 2 + 40 * Math.cos(0 / 180),       c.height / 2 + 40 * Math.sin(0 / 180),       c.width / 2 + 40 * Math.cos(90 / 180),       c.height / 2 + 40 * Math.sin(90 / 180),       "black",       c.width / 2 + 40 * Math.cos(0 / 180),       c.height / 2 + 40 * Math.sin(0 / 180),       c.width / 2 + 40 * Math.cos(90 / 180),       c.height / 2 + 40 * Math.sin(90 / 180)     );      function animate() {       requestAnimationFrame(animate);       ctx.clearRect(0, 0, c.width, c.height);       Player.update();       LeftHand.update();       RightHand.update();       Sword.update();     }      animate();   </script> </body>  </html>

注意事项:

  • 确保HTML文件中引入了JavaScript文件。
  • Canvas元素的width和height属性应设置为窗口的尺寸,以充分利用屏幕空间。
  • 在animate()函数中使用requestAnimationFrame()可以实现更流畅的动画效果。

总结

通过理解Canvas坐标系统,并正确计算和更新剑的端点坐标,可以实现旋转矩形剑的绘制。关键在于sword.update()函数的修正,以及确保所有坐标计算都基于Canvas原点。 此外,代码示例中使用了面向对象的编程思想,将角色、手臂和剑都定义为类,使得代码结构更加清晰易懂。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享