当前位置:首页 > JavaScript

js实现射箭

2026-02-02 07:21:41JavaScript

使用 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.translatectx.rotate实现对象旋转
  • 箭矢方向始终与速度方向一致(Math.atan2(arrow.speedY, arrow.speedX)

扩展建议

  1. 添加目标检测功能:

    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) {
       // 命中处理
     }
    });
    }
  2. 加入风阻效果:

    // 在updateArrow中添加
    arrow.speedX *= 0.99; // 空气阻力
  3. 使用粒子系统实现尾迹效果:

    js实现射箭

    const particles = [];
    function createParticles() {
    particles.push({
     x: arrow.x,
     y: arrow.y,
     size: Math.random() * 3 + 1,
     alpha: 1
    });
    }

完整实现可通过调整物理参数(重力、阻力等)来改变游戏难度,添加碰撞检测和得分系统可扩展为完整小游戏。

标签: js
分享给朋友:

相关文章

js防抖和节流实现

js防抖和节流实现

防抖(Debounce)的实现 防抖的核心思想是在事件被触发后,延迟执行回调函数。如果在延迟时间内再次触发事件,则重新计时。适用于输入框搜索、窗口大小调整等场景。 function debounce…

js实现预览

js实现预览

文件上传预览实现 使用JavaScript实现文件上传预览功能,可以通过FileReader对象读取文件内容并显示预览。以下代码支持图片、文本和PDF文件的预览: // HTML部分需要包含inpu…

js实现游标

js实现游标

使用JavaScript实现游标 在JavaScript中,可以通过操作DOM元素的cursor样式属性来实现自定义游标效果。以下是几种常见的实现方法: 修改默认鼠标指针样式 通过CSS的curso…

js画图实现

js画图实现

使用Canvas API绘制图形 Canvas是HTML5提供的绘图API,通过JavaScript操作Canvas元素可以绘制各种图形。以下是一个简单的示例: <canvas id="myC…

js实现正交

js实现正交

正交的概念 正交在数学和计算机科学中通常指两个向量垂直或线性无关。在编程中,正交性常被用于设计模块化、低耦合的系统。 向量正交判断 判断两个向量是否正交可以通过点积是否为0来实现: fun…

js实现路由

js实现路由

js实现路由的方法 在JavaScript中实现路由功能可以通过多种方式完成,以下是几种常见的方法: 使用原生JavaScript实现路由 通过监听window.onhashchange事件来实现基…