原生JS实现多个小球碰撞反弹效果示例


Posted in Javascript onJanuary 31, 2018

本文实例讲述了原生JS实现多个小球碰撞反弹效果。分享给大家供大家参考,具体如下:

实现思路:小球的移动,是通过改变小球的left和top值来改变,坐标分别为(x,y)当x/y值加到最大,即加到父级的宽度或者高度时,使x值或者y值减小,同理当x值或者y值减到最小时,同样的使x值或者y值增加,以上的思路可以实现小球的碰壁反弹

小球与小球之间的碰撞,要判断小球在被撞小球的哪个方向,从而判断小球该向哪个方向移动,同样的改变小球的坐标值,来实现小球的反弹

实现代码:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>小球碰撞</title>
    <style type="text/css">
      * {
        margin: 0;
        padding: 0;
      }
      #wrap {
        height: 800px;
        width: 1300px;
        border: 1px solid red;
        /*小球设置相对定位*/
        position: relative;
        margin: 0 auto;
        overflow: hidden;
      }
      p {
        width: 40px;
        height: 40px;
        border-radius: 50%;
        background-color: red;
        position: absolute;
        top: 0;
        left: 0;
        color: white;
        font-size: 25px;
        text-align: center;
        line-height: 40px;
      }
    </style>
  </head>
  <body>
    <div id="wrap">
    </div>
  </body>
  <!--<script src="js/common.js" type="text/javascript" charset="utf-8"></script>-->
  <script type="text/javascript">
    /**
     * 生成并返回一个从m到n全区间的随机数
     * @param {Object} m
     * @param {Object} n
     */
    function randomNum(m, n) {
      return Math.floor(Math.random() * (n - m + 1) + m);
    }
    /**
     * 生成一个随机颜色,并返回rgb字符串值
     */
    function randomColor() {
      var r = randomNum(0, 255);
      var g = randomNum(0, 255);
      var b = randomNum(0, 255);
      return "rgb(" + r + "," + g + "," + b + ")";
    }
    //获得wrapDiv
    var wrapDiv = document.getElementById("wrap");
    //定义数组存储所有的小球
    var balls = [];
    //生成小球函数
    function createBalls() {
      for (var i = 0; i < 20; i++) {
        var ball = document.createElement("p");
        //随机小球起始的X坐标和小球的Y坐标
        ball.x = randomNum(0, 1200);
        ball.y = randomNum(0, 700);
        //随机小球的移动速度
        ball.speed = randomNum(2, 5);
        //随机小球移动的方向
        if (Math.random() - 0.5 > 0) {
          ball.xflag = true;
        } else {
          ball.xflag = false;
        }
        if (Math.random() - 0.5 > 0) {
          ball.yflag = true;
        } else {
          ball.yflag = false;
        }
        //随机小球的背景颜色
        ball.style.backgroundColor = randomColor();
        ball.innerHTML = i + 1;
        //将小球插入当wrapDiv中
        wrapDiv.appendChild(ball);
        //将所有的小球存储到数组中
        balls.push(ball);
      }
    }
    createBalls();
    //小球移动函数,判断小球的位置
    function moveBalls(ballObj) {
      setInterval(function() {
        ballObj.style.top = ballObj.y + "px";
        ballObj.style.left = ballObj.x + "px";
        //判断小球的标志量,对小球作出相应操作
        if (ballObj.yflag) {
          //小球向下移动
          ballObj.y += ballObj.speed;
          if (ballObj.y >= 800 - ballObj.offsetWidth) {
            ballObj.y = 800 - ballObj.offsetWidth;
            ballObj.yflag = false;
          }
        } else {
          //小球向上移动
          ballObj.y -= ballObj.speed;
          if (ballObj.y <= 0) {
            ballObj.y = 0;
            ballObj.yflag = true;
          }
        }
        if (ballObj.xflag) {
          //小球向右移动
          ballObj.x += ballObj.speed;
          if (ballObj.x >= 1300 - ballObj.offsetHeight) {
            ballObj.x = 1300 - ballObj.offsetHeight;
            ballObj.xflag = false;
          }
        } else {
          //小球向左移动
          ballObj.x -= ballObj.speed;
          if (ballObj.x <= 0) {
            ballObj.x = 0;
            ballObj.xflag = true;
          }
        }
        crash(ballObj);
      }, 10);
    }
    var x1, y1, x2, y2;
    //碰撞函数
    function crash(ballObj) {
      //通过传过来的小球对象来获取小球的X坐标和Y坐标
      x1 = ballObj.x;
      y1 = ballObj.y;
      for (var i = 0; i < balls.length; i++) {
        //确保不和自己对比
        if (ballObj != balls[i]) {
          x2 = balls[i].x;
          y2 = balls[i].y;
          //判断位置的平方和小球的圆心坐标的关系
          if (Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + 800 <= Math.pow(ballObj.offsetWidth + balls[i].offsetWidth, 2)) {
            //判断传过来的小球对象,相对于碰撞小球的哪个方位
            if (ballObj.x < balls[i].x) {
              if (ballObj.y < balls[i].y) {
                //小球对象在被碰小球的左上角
                ballObj.yflag = false;
                ballObj.xflag = false;
              } else if (ballObj.y > balls[i].y) {
                //小球对象在被碰小球的左下角
                ballObj.xflag = false;
                ballObj.yflag = true;
              } else {
                //小球对象在被撞小球的正左方
                ballObj.xflag = false;
              }
            } else if (ballObj.x > balls[i].x) {
              if (ballObj.y < balls[i].y) {
                //小球对象在被碰撞小球的右上方
                ballObj.yflag = false;
                ballObj.xflag = true;
              } else if (ballObj.y > balls[i].y) {
                //小球对象在被碰撞小球的右下方
                ballObj.xflag = true;
                ballObj.yflag = true;
              } else {
                //小球对象在被撞小球的正右方
                ballObj.xflag = true;
              }
            } else if (ballObj.y > balls[i].y) {
              //小球对象在被撞小球的正下方
              ballObj.yflag = true;
            } else if (ballObj.y < balls[i].y) {
              //小球对象在被撞小球的正上方
              ballObj.yflag = false;
            }
          }
        }
      }
    }
    for (var i = 0; i < balls.length; i++) {
      //将所有的小球传到函数中,来实现对小球的移动
      moveBalls(balls[i]);
    }
  </script>
</html>

运行效果:

原生JS实现多个小球碰撞反弹效果示例

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
[原创]用javascript实现检测指定目录是否存在的方法
Jan 12 Javascript
用js来定义浏览器中一个左右浮动元素相对于页面主体宽度的位置的函数
Jan 21 Javascript
Jquery 模拟用户点击超链接或者按钮的方法
Oct 25 Javascript
文本框只能选择数据到文本框禁止手动输入
Nov 22 Javascript
js实现文本框中焦点在最后位置
Mar 04 Javascript
使表格的标题列可左右拉伸jquery插件封装
Nov 24 Javascript
JS修改iframe页面背景颜色的方法
Apr 01 Javascript
Javascript 引擎工作机制详解
Nov 30 Javascript
vue基于两个计算属性实现选中和全选功能示例
Feb 08 Javascript
Vue项目history模式下微信分享爬坑总结
Mar 29 Javascript
axios实现文件上传并获取进度
Mar 25 Javascript
基于javascript的无缝滚动动画实现2
Aug 07 Javascript
浅析Angular19 自定义表单控件
Jan 31 #Javascript
JavaScript实现计算多边形质心的方法示例
Jan 31 #Javascript
微信小程序switch开关选择器使用详解
Jan 31 #Javascript
详解Angular调试技巧之报错404(not found)
Jan 31 #Javascript
微信小程序slider组件使用详解
Jan 31 #Javascript
vue项目实现记住密码到cookie功能示例(附源码)
Jan 31 #Javascript
AngularJS 将再发布一个重要版本 然后进入长期支持阶段
Jan 31 #Javascript
You might like
PHP下通过系统信号量加锁方式获取递增序列ID
2009/09/25 PHP
PHP表单验证内容是否为空的实现代码
2016/11/14 PHP
thinkPHP5.0框架应用请求生命周期分析
2017/03/25 PHP
PHP多进程编程实例详解
2017/07/19 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
2020/04/04 PHP
javascript 得到变量类型的函数
2010/05/19 Javascript
jQuery侧边栏随窗口滚动实现方法
2013/03/04 Javascript
JavaScript 判断用户输入的邮箱及手机格式是否正确
2013/12/08 Javascript
Javascript中引用示例介绍
2014/02/21 Javascript
查找Oracle高消耗语句的方法
2014/03/22 Javascript
jQuery学习笔记之创建DOM元素
2015/01/19 Javascript
使用RequireJS优化JavaScript引用代码的方法
2015/07/01 Javascript
bootstarp modal框居中显示的实现代码
2017/02/18 Javascript
js实现带三角符的手风琴效果
2017/03/01 Javascript
canvas基础绘制-绚丽倒计时的实例
2017/09/17 Javascript
深入浅析vue组件间事件传递
2017/12/29 Javascript
vue左右侧联动滚动的实现代码
2018/06/06 Javascript
js实现点击生成随机div
2020/01/16 Javascript
redux处理异步action解决方案
2020/03/22 Javascript
JS常见内存泄漏及解决方案解析
2020/05/30 Javascript
Python测试网络连通性示例【基于ping】
2018/08/03 Python
PyCharm鼠标右键不显示Run unittest的解决方法
2018/11/30 Python
Python+PyQt5实现美剧爬虫可视工具的方法
2019/04/25 Python
python自动发邮件总结及实例说明【推荐】
2019/05/31 Python
Python如何实现的二分查找算法
2020/05/27 Python
解决Keras 中加入lambda层无法正常载入模型问题
2020/06/16 Python
浅谈TensorFlow中读取图像数据的三种方式
2020/06/30 Python
python 实现ping测试延迟的两种方法
2020/12/10 Python
美国在线医疗分销商:MedEx Supply
2020/02/04 全球购物
HashMap和Hashtable的区别
2013/05/18 面试题
加拿大留学自荐信
2014/01/28 职场文书
个人安全生产承诺书
2014/05/22 职场文书
员工保密协议书
2014/09/27 职场文书
2014年财务部工作总结
2014/11/11 职场文书
美德少年主要事迹材料
2015/11/04 职场文书
再读《皇帝的新衣》的读后感悟!
2019/08/07 职场文书