如何解决使用 JS 画布创建轨道武器精灵会产生动画错误/故障
我正在尝试制作一款玩家拥有可装备武器的游戏。截至目前,我已将此武器设置为弓的图像,并且我希望该武器在面对鼠标时可以在玩家周围移动。这类似于 buildroyale.io,玩家随着他的武器旋转以面对鼠标。
截至目前,在@Justin 的帮助下,我的弓在屏幕上旋转(有点)。它仅在按需要按下左键单击时显示,但不会按预期旋转。这是一个展示它如何移动的剪辑:clip
这是我使用的代码:
class EventHandler {
equip_weapon() {
if (holding) {
player.weapon = player.bag.slot_1;
canv.globalAlpha = 1;
player.weapon.equip();
player.weapon.update();
}
}
}
class Weapon {
image_path;
constructor(image_path) {
this.x = player.x + 30;
this.y = player.y + 30;
this.width = 120;
this.height = 120;
this.angle = 0;
this.distance = 50;
this.image = image_path;
}
equip() {
this.angle = Math.atan2(mouse.y - this.y,mouse.x - this.x)
canv.save();
canv.translate(this.x,this.y);
canv.rotate(this.angle);
canv.drawImage(this.image,this.distance,-this.height/2,this.width,this.height);
canv.restore();
}
update() {
this.x = player.x + player.width / 2;
this.y = player.y + player.height / 2;
}
}
bow = new Weapon(bow_image);
player.bag.slot_1 = bow;
aim_bounds = document.documentElement.getBoundingClientRect();
类播放器{
constructor() {
this.name = null;
this.speed = 5;
this.skin = player_sheet;
this.can_move = true;
this.is_moving = false;
this.width = 68;
this.height = 68;
this.scale = 1;
this.x = 566;
this.y = 316;
this.direction = facing.down;
this.frame = 0;
this.shadow_offset = 25;
this.frame_rate = 10;
this.health = 100;
this.clip_amount = 10;
this.weapon = null;
// Player inventory
this.bag = {
slot_1 : null,slot_2 : null,slot_3 : null,slot_4 : null,slot_5 : null,offhand : null,armor : null
}
this.is_menu_open = false;
console.log("Player constructed!");
}
update() {
// Animation updates
if (game.tick % this.frame_rate == 0 && this.is_moving && !this.is_menu_open) {
this.frame += 68;
if (this.frame >= 272) { this.frame = 0; }
} else if (!this.is_moving) { this.frame = 0; }
// Movement updates
if (this.can_move) {
if (controller.up) { this.direction = facing.up; this.y -= this.speed; this.is_moving = true; }
else if (controller.down) { this.direction = facing.down; this.y += this.speed; this.is_moving = true; }
else if (controller.left) { this.direction = facing.left; this.x -= this.speed; this.is_moving = true; }
else if (controller.right) { this.direction = facing.right; this.x += this.speed; this.is_moving = true; }
if (!controller.up && !controller.down && !controller.left && !controller.right) { this.is_moving = false; }
}
// Checks
if (this.is_menu_open) { this.can_move = false; } else { this.can_move = true; }
document.getElementById("health_bar").value = this.health;
if (this.is_menu_open) { menu.style.display = "block"; } else { menu.style.display = "none"; }
}
animate() {
// Player shadow
canv.drawImage(player_shadow,this.x,this.y + this.shadow_offset);
// Player
canv.globalAlpha = 1;
canv.drawImage(player_sheet,(sprite.x + this.frame),(sprite.y * this.direction),sprite.width,sprite.height,this.y,this.height);
}
}
这里是我当前代码的下载,以防您需要更多调试:game.zip
解决方法
我处理这个问题的方法是确保我的图像首先正确定向。在我的情况下,我的弓形图像看起来像这样(忽略质量)。只要看到它朝右。
在绘制函数中,我使用 translate()
来定位图像,并使用 x
内的 y
和 drawImage(img,x,y,w,h)
来绘制沿顶部边缘居中的图像画布。 x
(在本例中设置为 50)位置本质上是图像旋转的半径,而 y
只是为了使我的弓箭在画布的 y 轴上居中。
使用 Math.atan2()
我可以旋转图像
this.angle = Math.atan2(mouse.y - this.y,mouse.x - this.x)
在这个片段中,我有两行被注释掉了。如果您取消注释它们,您将更好地了解正在发生的事情。
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 600;
canvas.height = 600;
let mouse = {x: 10,y: 10}
let canvasBounds = canvas.getBoundingClientRect();
canvas.addEventListener('mousemove',e => {
mouse.x = e.x - canvasBounds.x
mouse.y = e.y - canvasBounds.y
})
let bow = new Image();
bow.src = "https://lh3.googleusercontent.com/g5Sr3HmGZgWx07sRQMvgvtxZ-ErhWNT0_asFdhLIlw-EQMTuUq3BV3YY8d5rrIrZBiJ-Uo2l836Qlmr8dmaCi-dcCCqN6veS6xnE8jSrmdtRtZKnmF5FQ5aTxuVBgB28n6ICoxSlpA=w2400";
class Weapon {
constructor() {
this.x = 200;
this.y = 200;
this.w = 60;
this.h = 60;
this.angle = 0
}
draw() {
this.angle = Math.atan2(mouse.y - this.y,mouse.x - this.x)
ctx.save();
ctx.translate(this.x,this.y);
ctx.rotate(this.angle);
//ctx.fillStyle = 'lightgrey';
//ctx.fillRect(0,canvas.width,canvas.height);
ctx.drawImage(bow,50,-this.h/2,this.w,this.h)
ctx.restore();
}
}
let bowArrow = new Weapon();
function animate() {
ctx.clearRect(0,canvas.height);
bowArrow.draw();
requestAnimationFrame(animate)
}
animate();
<canvas id="canvas"></canvas>
更新:
以下是我在您的文件中更改的内容,并且在我这边效果很好。
engine.controller.js
更改 mousemove
并添加监听器以调整大小。我也很确定有一种方法可以摆脱 getMouse
函数,因为下面的侦听器会为您获取鼠标坐标。
canvas.addEventListener("mousemove",function (event) {
mouse_position = event
mouse.x = event.x - canvas_bounds.x;
mouse.y = event.y - canvas_bounds.y;
})
window.addEventListener('resize',() => {
canvas_bounds = canvas.getBoundingClientRect();
})
engine.eventhandler.js
class Weapon {
image_path;
constructor(image_path) {
this.x = player.x + player.width/2;
this.y = player.y + player.height/2;
this.w = 60;
this.h = 60;
this.angle = 0;
this.image = image_path;
}
equip() {
this.x = player.x + player.width/2;
this.y = player.y + player.height/2;
this.angle = Math.atan2(mouse.y - this.y,mouse.x - this.x)
canv.save();
canv.translate(this.x,this.y);
canv.rotate(this.angle);
canv.drawImage(this.image,this.h);
canv.restore();
}
}
engine.main.js
function setup() {
game = new Game;
player = new Player;
controller = new Controller;
event_handler = new EventHandler;
canvas.width = 1200;
canvas.height = 700;
canvas_bounds = canvas.getBoundingClientRect();
// REMOVE LATER
bow = new Weapon(bow_image);
player.bag.slot_1 = bow;
document.getElementById("bag").style.display = "block";
}
engine.setup.js
// Weapon stuff
var weapon_equiped = false;
var canvas = document.getElementById("canvas");
let mouse = {
x : 10,y : 10
}
let canvas_bound;
var mouse_position,holding;
var rect,mouse_x,mouse_y;
...and
//you have a space between canvas. height in both fillRect
canv.fillRect(0,canvas. height);
我想这就是我改变的全部。很确定您可以使用 mouse_x 或 mouse.x,但您的代码中可能不需要这两者。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。