本文旨在帮助开发者理解如何在html canvas中绘制一个旋转的剑,并获取剑的端点坐标。通过分析提供的代码,我们将重点讲解如何正确计算剑的端点坐标,使其能够跟随角色手臂旋转,最终实现一个动态旋转的剑的效果。本文将提供修改后的代码示例,并解释关键部分的逻辑。
理解坐标计算
在Canvas中绘制旋转的物体,关键在于理解坐标系的变换。我们需要确定剑的起点(通常是角色手的位置)和终点。由于剑是旋转的,终点坐标需要根据旋转角度进行计算。
修改 Sword 类的 update 方法
原始代码中,Sword 类的 update 方法在计算剑的端点坐标时存在一些问题。正确的做法是,左手的位置作为剑的一个端点,右手的位置作为剑的另一个端点,然后根据剑的长度计算出另外两个端点。 下面是修改后的 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; }
解释:
立即学习“前端免费学习笔记(深入)”;
- this.Lx, this.Ly: 左手的位置,作为剑的一个端点。
- this.Rx, this.Ry: 右手的位置,作为剑的另一个端点。
- this.Lsx, this.Lsy: 左手位置不变,作为剑的第三个端点。
- this.Rsx, this.Rsy: 右手位置加上剑的长度,作为剑的第四个端点。
完整代码示例
以下是修改后的完整代码示例,包含了player, leftHand, rightHand, 和 sword 类的定义以及 animate 函数。
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 name="viewport" content="width=device-width, initial-scale=1.0"> <title>Rotating Sword</title> </head> <body> <canvas id="canvas"></canvas> <script src="script.JS"></script> </body> </html>
确保将JavaScript代码保存到名为 script.js 的文件中,并在HTML文件中引用它。
总结
通过修改 Sword 类的 update 方法,我们可以正确计算出剑的端点坐标,从而实现剑的旋转效果。 关键在于理解坐标变换和如何根据角色手臂的位置和剑的长度计算出正确的端点坐标。 记住,canvas 坐标计算是实现复杂动画的基础。 掌握这些概念,你就可以创建更丰富的canvas动画效果。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END