js实现射箭
使用 Canvas 实现射箭动画
通过 HTML5 Canvas 和 JavaScript 可以模拟射箭效果,核心包括绘制弓箭、箭矢轨迹和物理运动逻辑。
HTML 结构
<canvas id="gameCanvas" width="800" height="500"></canvas>
JavaScript 实现
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// 弓箭参数
let bow = {
x: 100,
y: 250,
angle: 0,
power: 0,
maxPower: 50
};
// 箭矢参数
let arrow = {
x: 0,
y: 0,
speedX: 0,
speedY: 0,
flying: false
};
// 绘制弓箭
function drawBow() {
ctx.save();
ctx.translate(bow.x, bow.y);
ctx.rotate(bow.angle);
// 弓身
ctx.beginPath();
ctx.moveTo(0, -20);
ctx.quadraticCurveTo(30, 0, 0, 20);
ctx.strokeStyle = '#8B4513';
ctx.lineWidth = 8;
ctx.stroke();
// 弓弦
if (!arrow.flying) {
ctx.beginPath();
ctx.moveTo(0, -15);
ctx.lineTo(40 + bow.power/2, 0);
ctx.lineTo(0, 15);
ctx.strokeStyle = '#FFF';
ctx.lineWidth = 2;
ctx.stroke();
}
ctx.restore();
}
// 绘制箭矢
function drawArrow() {
if (!arrow.flying) {
arrow.x = bow.x + Math.cos(bow.angle) * (40 + bow.power/2);
arrow.y = bow.y + Math.sin(bow.angle) * (40 + bow.power/2);
}
ctx.save();
ctx.translate(arrow.x, arrow.y);
ctx.rotate(Math.atan2(arrow.speedY, arrow.speedX));
// 箭杆
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(-30, 0);
ctx.strokeStyle = '#A9A9A9';
ctx.lineWidth = 3;
ctx.stroke();
// 箭尾
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(-10, -5);
ctx.lineTo(-10, 5);
ctx.closePath();
ctx.fillStyle = '#FF6347';
ctx.fill();
ctx.restore();
}
// 更新箭矢位置
function updateArrow() {
if (arrow.flying) {
arrow.x += arrow.speedX;
arrow.y += arrow.speedY;
arrow.speedY += 0.2; // 重力
// 边界检测
if (arrow.x > canvas.width || arrow.y > canvas.height || arrow.x < 0) {
arrow.flying = false;
}
}
}
// 鼠标控制
canvas.addEventListener('mousemove', (e) => {
if (!arrow.flying) {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
bow.angle = Math.atan2(mouseY - bow.y, mouseX - bow.x);
}
});
canvas.addEventListener('mousedown', () => {
if (!arrow.flying) {
bow.power = 0;
const powerInterval = setInterval(() => {
if (bow.power < bow.maxPower) {
bow.power += 1;
}
}, 50);
const mouseUpHandler = () => {
clearInterval(powerInterval);
arrow.flying = true;
arrow.speedX = Math.cos(bow.angle) * bow.power;
arrow.speedY = Math.sin(bow.angle) * bow.power;
canvas.removeEventListener('mouseup', mouseUpHandler);
};
canvas.addEventListener('mouseup', mouseUpHandler);
}
});
// 动画循环
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
updateArrow();
drawBow();
drawArrow();
requestAnimationFrame(gameLoop);
}
gameLoop();
实现要点说明
弓箭控制逻辑
- 通过鼠标移动控制弓箭角度(
Math.atan2计算角度) - 鼠标按下时蓄力(
bow.power递增) - 鼠标释放时根据蓄力值计算箭矢初速度
物理运动模拟
- 箭矢飞行时受重力影响(
arrow.speedY += 0.2) - 使用三角函数分解速度分量:
arrow.speedX = Math.cos(bow.angle) * bow.power arrow.speedY = Math.sin(bow.angle) * bow.power
绘制技巧
- 使用
ctx.translate和ctx.rotate实现对象旋转 - 箭矢方向始终与速度方向一致(
Math.atan2(arrow.speedY, arrow.speedX))
扩展建议
-
添加目标检测功能:
function checkHit() { const targets = [{x: 700, y: 300, radius: 30}]; targets.forEach(target => { const dx = arrow.x - target.x; const dy = arrow.y - target.y; if (Math.sqrt(dx*dx + dy*dy) < target.radius) { // 命中处理 } }); } -
加入风阻效果:
// 在updateArrow中添加 arrow.speedX *= 0.99; // 空气阻力 -
使用粒子系统实现尾迹效果:
const particles = []; function createParticles() { particles.push({ x: arrow.x, y: arrow.y, size: Math.random() * 3 + 1, alpha: 1 }); }
完整实现可通过调整物理参数(重力、阻力等)来改变游戏难度,添加碰撞检测和得分系统可扩展为完整小游戏。







