本文旨在解决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