当前位置:首页 > VUE

vue怎么实现小球碰撞

2026-02-24 23:36:47VUE

Vue 实现小球碰撞的方法

在 Vue 中实现小球碰撞效果,可以通过 Canvas 或 DOM 结合 JavaScript 的物理引擎来实现。以下是一个基于 Canvas 的实现方案。

vue怎么实现小球碰撞

创建 Vue 组件

在 Vue 项目中创建一个组件,用于绘制和更新小球的状态。

vue怎么实现小球碰撞

<template>
  <div>
    <canvas ref="canvas" :width="width" :height="height"></canvas>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: 800,
      height: 600,
      balls: [],
      ctx: null,
    };
  },
  mounted() {
    this.initCanvas();
    this.createBalls();
    this.animate();
  },
  methods: {
    initCanvas() {
      const canvas = this.$refs.canvas;
      this.ctx = canvas.getContext('2d');
    },
    createBalls() {
      for (let i = 0; i < 10; i++) {
        this.balls.push({
          x: Math.random() * this.width,
          y: Math.random() * this.height,
          radius: Math.random() * 20 + 10,
          dx: (Math.random() - 0.5) * 4,
          dy: (Math.random() - 0.5) * 4,
          color: `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255})`,
        });
      }
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.ctx.clearRect(0, 0, this.width, this.height);
      this.updateBalls();
      this.drawBalls();
    },
    updateBalls() {
      this.balls.forEach((ball, index) => {
        ball.x += ball.dx;
        ball.y += ball.dy;

        // 边界碰撞检测
        if (ball.x + ball.radius > this.width || ball.x - ball.radius < 0) {
          ball.dx = -ball.dx;
        }
        if (ball.y + ball.radius > this.height || ball.y - ball.radius < 0) {
          ball.dy = -ball.dy;
        }

        // 小球之间的碰撞检测
        for (let j = index + 1; j < this.balls.length; j++) {
          const otherBall = this.balls[j];
          const dx = ball.x - otherBall.x;
          const dy = ball.y - otherBall.y;
          const distance = Math.sqrt(dx * dx + dy * dy);

          if (distance < ball.radius + otherBall.radius) {
            // 碰撞响应
            const angle = Math.atan2(dy, dx);
            const sin = Math.sin(angle);
            const cos = Math.cos(angle);

            // 旋转坐标系
            const x1 = 0;
            const y1 = 0;
            const x2 = dx * cos + dy * sin;
            const y2 = dy * cos - dx * sin;

            // 旋转速度
            const vx1 = ball.dx * cos + ball.dy * sin;
            const vy1 = ball.dy * cos - ball.dx * sin;
            const vx2 = otherBall.dx * cos + otherBall.dy * sin;
            const vy2 = otherBall.dy * cos - otherBall.dx * sin;

            // 碰撞后的速度(一维弹性碰撞)
            const vx1Final = ((ball.radius - otherBall.radius) * vx1 + 2 * otherBall.radius * vx2) / (ball.radius + otherBall.radius);
            const vx2Final = ((otherBall.radius - ball.radius) * vx2 + 2 * ball.radius * vx1) / (ball.radius + otherBall.radius);

            // 更新速度
            ball.dx = vx1Final * cos - vy1 * sin;
            ball.dy = vy1 * cos + vx1Final * sin;
            otherBall.dx = vx2Final * cos - vy2 * sin;
            otherBall.dy = vy2 * cos + vx2Final * sin;

            // 防止小球重叠
            const overlap = ball.radius + otherBall.radius - distance;
            const moveX = overlap * cos * 0.5;
            const moveY = overlap * sin * 0.5;
            ball.x += moveX;
            ball.y += moveY;
            otherBall.x -= moveX;
            otherBall.y -= moveY;
          }
        }
      });
    },
    drawBalls() {
      this.balls.forEach(ball => {
        this.ctx.beginPath();
        this.ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
        this.ctx.fillStyle = ball.color;
        this.ctx.fill();
        this.ctx.closePath();
      });
    },
  },
};
</script>

<style>
canvas {
  border: 1px solid #000;
}
</style>

物理引擎优化

如果需要更复杂的物理效果,可以引入物理引擎如 Matter.js 或 p5.js。

import Matter from 'matter-js';

export default {
  mounted() {
    const engine = Matter.Engine.create();
    const render = Matter.Render.create({
      element: this.$refs.canvas,
      engine: engine,
      options: {
        width: this.width,
        height: this.height,
        wireframes: false,
      },
    });

    const balls = [];
    for (let i = 0; i < 10; i++) {
      balls.push(Matter.Bodies.circle(
        Math.random() * this.width,
        Math.random() * this.height,
        Math.random() * 20 + 10,
        {
          restitution: 0.8,
          render: {
            fillStyle: `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255})`,
          },
        }
      ));
    }

    Matter.Composite.add(engine.world, balls);
    Matter.Engine.run(engine);
    Matter.Render.run(render);
  },
};

关键点说明

  • 使用 Canvas 绘制小球,并通过 requestAnimationFrame 实现动画循环。
  • 边界碰撞检测通过判断小球是否超出画布边界实现。
  • 小球之间的碰撞检测通过计算距离和半径之和实现。
  • 碰撞响应通过旋转坐标系简化为一维弹性碰撞问题。

通过以上方法,可以在 Vue 中实现小球的碰撞效果。

标签: 小球vue
分享给朋友:

相关文章

vue播放倍速怎么实现

vue播放倍速怎么实现

实现Vue播放倍速的方法 在Vue中实现播放倍速功能通常涉及HTML5的<video>元素或第三方播放器库。以下是几种常见实现方式: 使用原生HTML5 video元素 通过ref获取v…

vue实现走势图

vue实现走势图

Vue 实现走势图的方法 使用 ECharts 库 ECharts 是一个强大的数据可视化库,支持多种图表类型,包括走势图(折线图)。在 Vue 项目中可以通过 vue-echarts 封装库或直接使…

vue实现app

vue实现app

Vue 实现 App 的常见方法 使用 Vue 开发移动端 App 主要有两种主流方案:混合开发(Hybrid)和原生渲染。以下是具体实现方式和工具链: 混合开发方案(WebView 嵌入) 通过…

实现简易vue

实现简易vue

实现简易 Vue 的核心思路 Vue 的核心功能包括数据响应式、模板编译和虚拟 DOM。以下是一个简易实现方案,涵盖核心功能模块。 数据响应式系统 通过 Object.defineProperty…

vue实现图册

vue实现图册

Vue实现图册功能 在Vue中实现图册功能通常涉及图片展示、切换、缩放等交互效果。以下是常见的实现方法和关键代码示例: 基础图册组件结构 使用Vue单文件组件构建基础结构: <templat…

vue实现试卷

vue实现试卷

Vue实现试卷系统的基本思路 使用Vue.js构建试卷系统需要结合组件化开发、状态管理和后端数据交互。核心功能包括题目展示、答题逻辑、计时器和提交答案。 核心功能模块划分 试卷组件结构 试卷容器组…