javascript实现10个球随机运动、碰撞实例详解

本文实例讲述了javascript实现10个球随机运动、碰撞的方法。分享给大家供大家参考。具体如下:

学了一段时间的javascript了,做过一些小案例,目前最有难度的就是10个小球随机碰撞效果,这不,把它上上来与大家分享一下,相信不少和我一样的菜鸟在开始上手编程时都会有不少的困惑,希望它能给一些人带来帮助。

效果要求:10个小球在页面随机移动,碰到窗口边界或其他小球都会反弹

思路:

1、10个小球是10个div;
2、碰窗口反弹,定义vx vy为小球的移动变量,以及一个弹力变量bounce(负值),小球碰窗口边界时,vx vy分别乘以bounce,则改变了小球移动方向
3、小球相碰反弹,说简单点,当两个小球的圆心距变量dist小于其最小值(半径之和)则改变球的移动方向,实现反弹

好了,代码如下:

html和js是分开的文件哟
 
test.html文件如下:

<html>
 <head>
  <title></title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <style type="text/css">
body {
    margin:0;
    padding:0;
    text-align: center;
}
#screen { width: 800px; height: 640px; position: relative; background: #ccccff;margin: 0 auto;vertical-align: bottom}
#inner { position: absolute; left:0px; top:0px; width:100%; height:100%; }
#screen p {color:white;font:bold 14px;}
.one { background-image:url('bubble.png'); background-position: -66px -58px; }
.two { background-image:url('bubble.png'); background-position: -66px -126px;}
.three { background-image:url('bubble.png'); background-position: -66px -194px; }
.four { background-image:url('bubble.png'); background-position: -66px -263px; }
.five { background-image:url('bubble.png'); background-position: -66px -331px; }
.six { background-image:url('bubble.png'); background-position: -66px -399px; }
.seven { background-image:url('bubble.png'); background-position: -66px -194px; }
.eight { background-image:url('bubble.png'); background-position: -66px -263px; }
.nine { background-image:url('bubble.png'); background-position: -66px -331px; }
.ten{ background-image:url('bubble.png'); background-position: -66px -399px; }
  </style>
 </head>
 <body>
   <div id="screen" >
     <p>hi test it!</p>
     <div id="inner"></div>
   </div>
   <input type="button" id="start" value="start" >
   <input type="button" id="stop" value="stop">
   <br><br><br>
<script type="text/javascript" src="test.js"></script>
 </body>
</html>

test.js文件如下:

var getFlag=function (id) {
     return document.getElementByIdx_x(id);  //获取元素引用
}
var extend=function(des, src) {
     for (p in src) {
       des[p]=src[p];
   }
  return des;
 }
var clss=['one','two','three','four','five','six','seven','eight','nine','ten'];
var Ball=function (diameter,classn) {
  var ball=document.createElement_x("div");
  ball.className=classn;
  with(ball.style) {
    width=height=diameter+'px';position='absolute';
  }
  return ball;
}
var Screen=function (cid,config) {
  //先创建类的属性
  var self=this;
  if (!(self instanceof Screen)) {
    return new Screen(cid,config)
  }
  config=extend(Screen.Config, config)  //configj是extend类的实例
  self.container=getFlag(cid);      //窗口对象
  self.ballsnum=config.ballsnum;
  self.diameter=56;            //球的直径
  self.radius=self.diameter/2;
  self.spring=config.spring;       //球相碰后的反弹力
  self.bounce=config.bounce;       //球碰到窗口边界后的反弹力
  self.gravity=config.gravity;      //球的重力
  self.balls=[];             //把创建的球置于该数组变量
  self.timer=null;            //调用函数产生的时间id
  self.L_bound=0;            //container的边界
  self.R_bound=self.container.clientWidth;
  self.T_bound=0;
  self.B_bound=self.container.clientHeight;
};
Screen.Config={             //为属性赋初值
  ballsnum:10,
  spring:0.8,
  bounce:-0.9,
  gravity:0.05
};
Screen.prototype={
  initialize:function () {
    var self=this;
    self.createBalls();
    self.timer=setInterval(function (){self.hitBalls()}, 30)
  },
  createBalls:function () {
    var self=this, num=self.ballsnum;
    var frag=document.createDocumentFragment();  //创建文档碎片,避免多次刷新
     for (i=0;i<num;i++) {
      var ball=new Ball(self.diameter,clss[ Math.floor(Math.random()* num )]);
      ball.diameter=self.diameter;
      ball.radius=self.radius;
      ball.style.left=(Math.random()*self.R_bound)+'px'; //球的初始位置,
      ball.style.top=(Math.random()*self.B_bound)+'px';
      ball.vx=Math.random() * 6 -3;
      ball.vy=Math.random() * 6 -3;
      frag.appendChild(ball);
      self.balls[i]=ball;
    }
    self.container.appendChild(frag);
  },
  hitBalls:function () {
    var self=this, num=self.ballsnum,balls=self.balls;
    for (i=0;i<num-1;i++) {
      var ball1=self.balls[i];
      ball1.x=ball1.offsetLeft+ball1.radius;   //小球圆心坐标
      ball1.y=ball1.offsetTop+ball1.radius;
      for (j=i+1;j<num;j++) {
        var ball2=self.balls[j];
        ball2.x=ball2.offsetLeft+ball2.radius;
        ball2.y=ball2.offsetTop+ball2.radius;
        dx=ball2.x-ball1.x;           //两小球圆心距对应的两条直角边
        dy=ball2.y-ball1.y;
        var dist=Math.sqrt(dx*dx + dy*dy);    //两直角边求圆心距
        var misDist=ball1.radius+ball2.radius;  //圆心距最小值
       if(dist < misDist) {
          //假设碰撞后球会按原方向继续做一定的运动,将其定义为运动A
          var angle=Math.atan2(dy,dx);
         //当刚好相碰,即dist=misDist时,tx=ballb.x, ty=ballb.y
          tx=balla.x+Math.cos(angle) * misDist;
            ty=balla.y+Math.sin(angle) * misDist;
         //产生运动A后,tx > ballb.x, ty > ballb.y,所以用ax、ay记录的是运动A的值
            ax=(tx-ballb.x) * self.spring;
            ay=(ty-ballb.y) * self.spring;
         //一个球减去ax、ay,另一个加上它,则实现反弹
            balla.vx-=ax;
            balla.vy-=ay;
            ballb.vx+=ax;
            ballb.vy+=ay;
          }
      }
    }
    for (i=0;i<num;i++) {
      self.moveBalls(balls[i]);
    }
  },
  moveBalls:function (ball) {
    var self=this;
    ball.vy+=self.gravity;
    ball.style.left=(ball.offsetLeft+ball.vx)+'px';
    ball.style.top=(ball.offsetTop+ball.vy)+'px';
    //判断球与窗口边界相碰,把变量名简化一下
    var L=self.L_bound, R=self.R_bound, T=self.T_bound, B=self.B_bound, BC=self.bounce;
    if (ball.offsetLeft < L) {
      ball.style.left=L;
      ball.vx*=BC;
    }
    else if (ball.offsetLeft + ball.diameter > R) {
      ball.style.left=(R-ball.diameter)+'px';
      ball.vx*=BC;
    }
    else if (ball.offsetTop < T) {
      ball.style.top=T;
      ball.vy*=BC;
    }
    if (ball.offsetTop + ball.diameter > B) {
      ball.style.top=(B-ball.diameter)+'px';
      ball.vy*=BC;
    }
  }
}
window.onload=function() {
  var sc=null;
  getFlag('start').onclick=function () {
    document.getElementByIdx_x("inner").innerHTML='';
    sc=new Screen('inner',{ballsnum:10, spring:0.8, bounce:-0.9, gravity:0.05});
    sc.initialize();
  }
  getFlag('stop').onclick=function() {
    clearInterval(sc.timer);
  }
}

测试后的效果还是很不错的,各位也许会觉得代码挺长,但是其思路还是蛮清晰的:
首先创建Screen类,并在Screen的构造函数中给出了球移动、碰撞所需的各种属性变量,如ballsnum、spring、bounce、gravity等等
然后用原型prototype给出相应的函数,如创建球,createBalls,球碰撞hitBalls,球移动moveBalls,给每个函数添加相应的功能、
最后用按钮点击事件调用函数,仅此而已。

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

(0)

相关推荐

  • Js实现简单的小球运动特效

    废话不多说了,直接给大家贴js代码了,具体代码如下所示: <!DOCTYPE html> <html> <head> <title></title> <meta http-equiv="content-type" content="text/html;charset=utf-"/> </head> <body style="background:pink;"

  • Javascript实现重力弹跳拖拽运动效果示例

    演示地址: http://www.ihuxu.com/project/gcdmove/ 调用示例: var GCDM = gcdMove(oDiv,100,0); GCDM.startMove();//开始运动 GCDM.stopMove();//结束运动 该段JS代码已经封装好了,代码如下: 简要说明 - obj为要改动的对象元素,通常为某个div:iSpeedX,iSpeedY为div出师的横向(右侧),竖向(下)的初始速度,当然也可以设为零. 复制代码 代码如下: /** * @Desc

  • js+html5实现的自由落体运动效果代码

    本文实例讲述了js+html5实现的自由落体运动效果.分享给大家供大家参考,具体如下: 运行效果截图如下: 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/x

  • js运动动画的八个知识点

    今天简单的学了一下js运动动画,记录一下自己的心得体会,分享给大家. 下面是我整理出来的结果. 知识点一:速度动画. 1.首先第一步实现速度运动动画,封装一个函数,用到的知识是setInterval(function(){ 复制代码 代码如下: oDiv.style.left=oDiv.offsetLeft+10+"px"; },30). 对于这里为什么要用到offsetLeft,我特意百度了一下,我得到的有用信息是: a.offsetLeft和left的相同之处都是表示子节点相对于父

  • Javascript模拟加速运动与减速运动代码分享

    加速运动,即一个物体运动时速度越来越快:减速运动,即一个物体运动时速度越来越慢.现在用Javascript来模拟这两个效果,原理就是用setInterval或setTimeout动态改变一个元素与另外一个元素的距离,如xxx.style.left或xxx.style.marginLeft,然后每次运动后都使速度增加,这样加速运动的效果就出现了,减速运动是同样的道理. 下面是两个示例: 加速运动 复制代码 代码如下: <!DOCTYPE html> <html> <head&g

  • js简单实现点击左右运动的方法

    本文实例讲述了js简单实现点击左右运动的方法.分享给大家供大家参考.具体分析如下: 这里可实现点击向右,方块向右移动,点击向左,方块向左移动的效果 可以用setInterval来实现过多长时间,div移动多长的距离来实现运动效果. 要点一:如果元素的左边距离小于目标距离,则是正向移动,否则是负向移动 if(run.offsetLeft <target){ speed = 2; }else{ speed = -2; } 要点二:如果元素的左边距离等于目标距离,停止定时器,否则,元素的左边距离等于现

  • 使用JavaScript 实现对象 匀速/变速运动的方法

    实例1--控制一个对象的匀速移动和停止 HTML: 复制代码 代码如下: <input id="btn" type="button" value=" Move It ! "/>    <div id="d1">        <img id="i1" src="1.jpg" alt/>    </div> JS:实现向右运动 复制代码 代码

  • JS实现匀速运动的代码实例

    效果: 思路: 利用setInerval()计时器,进行运动.然后关键的一点是在最后停止的时候给它一个填充缝隙的判断. 代码: 复制代码 代码如下: <head runat="server">    <title></title>    <style type="text/css">        #div1        {            width: 100px;            height: 10

  • JS实现匀加速与匀减速运动的方法示例

    本文实例讲述了JS实现匀加速与匀减速运动的方法.分享给大家供大家参考,具体如下: /* * 动画帧函数 * * */ var requestFrame=function(){ var prefixList=['webkit','moz','ms']; var func; for(var i=0;i<prefixList.length;i++){ func=window[prefixList[i]+"RequestAnimationFrame"]; if(func){ return

  • JavaScript拖拽、碰撞、重力及弹性运动实例分析

    本文实例讲述了JavaScript拖拽.碰撞.重力及弹性运动实现方法.分享给大家供大家参考,具体如下: js拖拽.碰撞与重力实现代码: window.onload=function () { var oDiv=document.getElementById('div1'); var lastX=0; var lastY=0; oDiv.onmousedown=function (ev) { var oEvent=ev||event; var disX=oEvent.clientX-oDiv.of

  • js实现缓冲运动效果的方法

    本文实例讲述了js实现缓冲运动效果的方法.分享给大家供大家参考.具体分析如下: 该实例可实现一开始速度很快,然后慢下来,直到停止的效果. 要点: var speed = (target-box.offsetLeft)/8; 目标点减去元素的当前位置的值除以8,因为offsetleft的值是一直在变大,所以速度的值也是一直的变小 speed = speed>0?Math.ceil(speed):Math.floor(speed); 正向速度的时候向上取整,反向速度的时候向下取整 代码: <!DO

随机推荐