多个小球碰撞功能(原生js实现)

如何实现下图功能

 下面代码可以随意增加小球的数量和速度

只需要在html重加入<div class="ball"></div>

和改变

wrap.children[i].x = 1;

wrap.children[i].y = 1;

的值即可

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">

    <title>多个小球碰撞</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #wrap {
            width: 1000px;
            height: 600px;
            border: 1px solid black;
            margin: 30px auto;
            position: relative;
        }

        .ball {
            width: 50px;
            height: 50px;
            background-color: red;
            border-radius: 50%;
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <div id="wrap">
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>

    </div>
</body>
<script>
    var wrap = document.getElementById('wrap');
    // 获取外部容器的可视宽度(不包括边框)
    var wrapWidth = wrap.clientWidth;
    // 获取外部容器的可视高度(不包括边框)
    var wrapHeight = wrap.clientHeight;
    // 定义随意生成一个整数的函数
    function randomNum(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    }

    for (var i = 0; i < wrap.children.length; i++) {
        // 定义自定义属性小球的水平方向的一次移动的距离
        wrap.children[i].x = 1;
        // 定义自定义属性小球的水平方向的一次移动的距离
        wrap.children[i].y = 1;
        // 定义一个自定义属性,来存储小球是否为反方向运动 正方向为true,反方向为false 方向随机生成
        wrap.children[i].flagX = randomNum(0,1)?true:false;
        wrap.children[i].flagY = randomNum(0,1)?true:false;
        // 定义每个小球的大小(随机生成)
        wrap.children[i].style.width = randomNum(10, 80) + 'px';
        wrap.children[i].style.height = wrap.children[i].offsetWidth + 'px';
        //小球在随机的高度创建(随机生成)
        wrap.children[i].style.top = randomNum(0, wrapHeight - wrap.children[i].offsetWidth) + 'px';
        //小球在随机的left创建(随机生成)
        wrap.children[i].style.left = randomNum(0, wrapWidth - wrap.children[i].offsetWidth) + 'px';
        // 随机生成每个小球的颜色
        wrap.children[i].style.backgroundColor = `rgb(${randomNum(0,255)},${randomNum(0,255)},${randomNum(0,255)})`;
       

    }
    // 定义x轴运动函数
    function moveX() {
        // for循环遍历每一个小球
        for (var i = 0; i < wrap.children.length; i++) {
            // 判断该flagX是否为TRUE,为真则正方向运动,否则方方向运动
            if (wrap.children[i].flagX) {
                // 正方向运动
                //将每次的小球的距离父盒子左侧的距离加上每次移动的距离赋值给left值
                wrap.children[i].style.left = wrap.children[i].offsetLeft + wrap.children[i].x + 'px';
                // 判断是否小球的运动距离超过盒子外
                if (wrap.children[i].offsetLeft >= wrap.offsetWidth - wrap.children[i].offsetWidth) {
                    // 将其flagX的值变成false,进行反方向运动
                    wrap.children[i].flagX = false;
                }
            } else {
                // 反方向运动
                //将每次的小球的距离父盒子左侧的距离减去每次移动的距离赋值给left值
                wrap.children[i].style.left = wrap.children[i].offsetLeft - wrap.children[i].x + 'px';
                //判断是否触壁
                if (wrap.children[i].offsetLeft <= 0) {
                    wrap.children[i].flagX = true;
                }
            }
        }
    }
    // 定义y轴运动函数
    function moveY() {
        // for循环遍历每一个小球
        for (var i = 0; i < wrap.children.length; i++) {
            // 判断该flagX是否为TRUE,为真则正方向运动,否则方方向运动
            if (wrap.children[i].flagY) {
                // 正方向运动
                //将每次的小球的距离父盒子左上侧的距离加上每次移动的距离赋值给top值
                wrap.children[i].style.top = wrap.children[i].offsetTop + wrap.children[i].y + 'px';
                // 判断是否小球的运动距离超过盒子外
                if (wrap.children[i].offsetTop >= wrap.offsetHeight - wrap.children[i].offsetHeight) {
                    // 将其flagY的值变成false,进行反方向运动
                    wrap.children[i].flagY = false;
                }
            } else {
                // 反方向运动
                //将每次的小球的距离父盒子上侧的距离减去每次移动的距离赋值给top值
                wrap.children[i].style.top = wrap.children[i].offsetTop - wrap.children[i].y + 'px';
                //判断是否触壁
                if (wrap.children[i].offsetTop <= 0) {
                    wrap.children[i].flagY = true;
                }
            }
        }
    }
    setInterval(function () {
        moveX();
        moveY();
    }, 1);
</script>

</html>

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Vue 中实现多个小球碰撞,可以按照以下步骤进行: 1. 创建一个 Ball 组件,用于显示单个小球的界面。这个组件需要包含小球的位置、速度等信息,并且需要实现小球的移动和碰撞检测等功能。 ``` <template> <div :style="{ left: x + 'px', top: y + 'px' }"></div> </template> <script> export default { props: { x: Number, y: Number, speedX: Number, speedY: Number, radius: Number, color: String, bounds: Object }, data() { return { timerId: null } }, created() { this.timerId = setInterval(this.move, 10); }, methods: { move() { let x = this.x + this.speedX; let y = this.y + this.speedY; if (x - this.radius < this.bounds.left || x + this.radius > this.bounds.right) { this.speedX = -this.speedX; } if (y - this.radius < this.bounds.top || y + this.radius > this.bounds.bottom) { this.speedY = -this.speedY; } this.$emit('update:x', x); this.$emit('update:y', y); } } } </script> <style> div { position: absolute; width: 20px; height: 20px; border-radius: 50%; } </style> ``` 2. 在父组件中,创建多个 Ball 组件,并为每个组件设置不同的位置、速度等信息。同时,还需要为每个组件设置边框信息,用于碰撞检测。 ``` <template> <div ref="container" style="position: relative; width: 400px; height: 400px; border: 1px solid black;"> <Ball v-for="(ball, index) in balls" :key="index" :x.sync="ball.x" :y.sync="ball.y" :speedX="ball.speedX" :speedY="ball.speedY" :radius="ball.radius" :color="ball.color" :bounds="bounds" /> </div> </template> <script> import Ball from './Ball.vue'; export default { components: { Ball }, data() { return { balls: [ { x: 50, y: 50, speedX: 5, speedY: 3, radius: 10, color: 'red' }, { x: 100, y: 100, speedX: -3, speedY: 4, radius: 15, color: 'blue' }, { x: 150, y: 150, speedX: 4, speedY: -5, radius: 20, color: 'green' } ], bounds: { left: 0, top: 0, right: 400, bottom: 400 } } } } </script> ``` 3. 在 Ball 组件中,实现碰撞检测的功能。可以在 move 方法中,遍历所有其他的 Ball 组件,检测当前小球是否与其他小球相交。如果相交了,就需要计算当前小球的新速度,并更新位置。 ``` move() { let x = this.x + this.speedX; let y = this.y + this.speedY; let radius = this.radius; if (x - radius < this.bounds.left || x + radius > this.bounds.right) { this.speedX = -this.speedX; } if (y - radius < this.bounds.top || y + radius > this.bounds.bottom) { this.speedY = -this.speedY; } this.balls.forEach(ball => { if (ball !== this) { let dx = ball.x - x; let dy = ball.y - y; let distance = Math.sqrt(dx * dx + dy * dy); if (distance < radius + ball.radius) { let angle = Math.atan2(dy, dx); let sin = Math.sin(angle); let cos = Math.cos(angle); // 旋转坐标系 let vx1 = this.speedX * cos + this.speedY * sin; let vy1 = this.speedY * cos - this.speedX * sin; let vx2 = ball.speedX * cos + ball.speedY * sin; let vy2 = ball.speedY * cos - ball.speedX * sin; // 碰撞后的新速度 let vx1Final = ((this.radius - ball.radius) * vx1 + (2 * ball.radius) * vx2) / (this.radius + ball.radius); let vx2Final = ((2 * this.radius) * vx1 + (ball.radius - this.radius) * vx2) / (this.radius + ball.radius); // 更新速度 this.speedX = vx1Final * cos - vy1 * sin; this.speedY = vy1 * cos + vx1Final * sin; ball.speedX = vx2Final * cos - vy2 * sin; ball.speedY = vy2 * cos + vx2Final * sin; // 更新位置 x += this.speedX; y += this.speedY; ball.x += ball.speedX; ball.y += ball.speedY; } } }); this.$emit('update:x', x); this.$emit('update:y', y); } ``` 通过以上步骤,就可以实现多个小球碰撞,并且在 Vue 中动态更新小球的位置和速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值