• js实现小球碰撞(数学之美)


    <!DOCTYPE html>
    <html lang="zh_CN">
    <head>
    <meta charset="utf-8">
    <title>小球碰撞</title>
    <style type="text/css">
    .center{width:400px;text-align: center;margin: 0 auto;}
    #wrapper{position:relative;width:400px;height:400px;box-shadow: 0px 0px 3px #333 inset;background: #666;}
    .ball{position:absolute;width:20px;height:20px;border-radius: 10px;background:#fff;box-shadow: 2px 2px 2px #666;visibility: hidden;}
    </style>
    <script type="text/javascript">
    //下次加小球碰撞
    var speed = 5;
    var seq = 0;
    var boundary = null;
    var interval;
    var balls = [];
    var colors = ['rgba(0,0,240,0.8)', 'rgba(0,0,240,0.7)', 'rgba(0,0,240,0.6)', 'rgba(0,0,240,0.5)', 'rgba(0,0,240,0.4)', 'rgba(0,0,240,0.3)', 'rgba(0,0,240,0.2)'];
    
    var GeneralObject = function(){
    this.x = null;
    this.y = null;
    this.width = 0;
    this.height = 0;
    this.dom = null;
    };
    
    function Ball(id){
    this.dom = document.getElementById(id);
    this.x = null;
    this.y = null;
    this.width = this.dom.offsetWidth;
    this.height = this.dom.offsetHeight;
    this.hspeed = 2*speed * (Math.floor(Math.random() * 10) + 1)/10;
    this.vspeed = 2*speed * (Math.floor(Math.random() * 10) + 1)/10;
    };
    Ball.prototype = new GeneralObject();
    
    function Boundary(id){
    this.dom = document.getElementById(id);
    this.width = this.dom.offsetWidth;
    this.height = this.dom.offsetHeight;
    
    };
    Boundary.prototype = new GeneralObject();
    
    function init(){
    var ball = new Ball('ball');
    boundary = new Boundary('wrapper');
    ball.dom.style.left = Math.random()*(boundary.width - ball.width) + 'px';
    ball.x = parseInt(ball.dom.style.left);
    ball.dom.style.top = Math.random()*(boundary.height - ball.height) + 'px';
    ball.y = parseInt(ball.dom.style.top);
    ball.dom.style.visibility = 'visible';
    balls.push(ball);
    
    interval = setInterval(function(){
    go(balls, boundary);
    }, 20);
    
    }
    
    function go(balls, boundary){
    for(var i = 0; i < balls.length; i++){
    balls[i].dom.style.left = balls[i].x + balls[i].hspeed + 'px';
    balls[i].x = parseInt(balls[i].dom.style.left);
    balls[i].dom.style.top = balls[i].y + balls[i].vspeed + 'px';
    balls[i].y = parseInt(balls[i].dom.style.top);
    
    hitTest(balls[i], boundary);
    //得保证生成小球的地方没有已存在的小球与之重叠,现在还没有做到
    // if(i >= 1){
    // for(var j = i-1; j >= 0; j--){
    // hitBall(balls[i], balls[j]);
    // }
    // }
    
    }
    }
    
    function hitTest(ball, boundary){
    if(ball.y + ball.height >= boundary.height || ball.y + ball.height + ball.vspeed > boundary.height){
    ball.vspeed = -ball.vspeed;
    }
    if(ball.x + ball.width >= boundary.width || ball.x + ball.width + ball.hspeed > boundary.width){
    ball.hspeed = -ball.hspeed;
    }
    if(ball.y <= 0 || ball.y + ball.vspeed < 0){
    ball.vspeed = -ball.vspeed;
    }
    if(ball.x <= 0 || ball.x + ball.hspeed < 0){
    ball.hspeed = -ball.hspeed;
    }
    }
    
    function hitBall(ballA, ballB){
    if(CheckIntersect(ballA, ballB)){
    //简单处理为交换速度
    var temp;
    temp = ballA.vspeed;
    ballA.vspeed = ballB.vspeed;
    ballB.vspeed = temp;
    temp = ballA.hspeed;
    ballA.hspeed = ballB.hspeed;
    ballB.hspeed = temp;
    }
    }
    
    //圆形碰撞检测与方形碰撞检测原理不一样
    function CheckIntersect(ball1, ball2){
    var p1 = {};//提取出去作为ball的属性,在这个被循环调用的函数里面新建对象不好
    p1.x = ball1.x + ball1.width/2;
    p1.x1 = ball1.x + ball1.width/2 + ball1.hspeed;
    p1.y = ball1.y + ball1.height/2;
    p1.y1 = ball1.y + ball1.height/2 + ball1.vspeed;
    var p2 = {};
    p2.x = ball2.x + ball2.width/2;
    p2.x1 = ball2.x + ball2.width/2 + ball2.hspeed;
    p2.y = ball2.y + ball2.height/2;
    p2.y1 = ball2.y + ball2.height/2 + ball2.vspeed;
    
    if(Math.pow((p1.x-p2.x),2) + Math.pow((p1.y-p2.y),2) <= Math.pow((ball1.width/2 + ball2.width/2),2)
    || Math.pow((p1.x1-p2.x1),2) + Math.pow((p1.y1-p2.y1),2) <= Math.pow((ball1.width/2 + ball2.width/2),2)){
    return true;
    }
    return false;
    }
    
    function addEvent(){
    var addBtn = document.getElementById('add');
    addBtn.onclick = function(){
    var newdom = document.createElement('div');
    newdom.setAttribute('id','ball_'+ seq);
    newdom.setAttribute('class','ball');
    document.getElementById('wrapper').appendChild(newdom);
    var newBall = new Ball('ball_'+seq);
    //小球出现的地方不能是和边界重叠,不能和已存在的小球重叠,这里还没有办法做
    //小球出现的点随机
    // newBall.dom.style.left = Math.floor(Math.random()*(boundary.width - 2*newBall.width) + newBall.width) + 'px';
    // newBall.x = parseInt(newBall.dom.style.left);
    // newBall.dom.style.top = Math.floor(Math.random()*(boundary.height - 2*newBall.height) + newBall.height) + 'px';
    // newBall.y = parseInt(newBall.dom.style.top);
    
    //小球出现的点固定
    newBall.dom.style.left = 0 + 'px';
    newBall.x = 0;
    newBall.dom.style.top = newBall.dom.style.left;
    newBall.y = newBall.x;
    
    newBall.dom.style.visibility = 'visible';
    newBall.dom.style.background = colors[(Math.floor(Math.random() * colors.length) + 1)];
    balls.push(newBall);
    seq++;
    clearInterval(interval);//经过证明,一个页面可以有多个setInterval(定时器),这样省却了再interval里遍历数组的麻烦,但系统却要维护多个定时器,哪种办法更好些呢?
    /*
    以下内容来自网络,未亲测。
    关于游戏中的定时器的设计有以下两种争议:
    
    1) 每个需要定时器的地方都创建一个,然后问题归结为多个定时器的管理问题;
    
    2) 游戏中只有一个定时器,然后问题归结为一个定时器实现多个定时器的效果。
    
    实际从管理难度以及运行效率上来讲应该选择第2种。
    */
    interval = setInterval(function(){
    go(balls, boundary);
    }, 20);
    }
    }
    
    window.onload = function(){
    init();
    addEvent();
    }
    </script>
    </head>
    <body>
    <div class="center">
    <div id="wrapper">
    <div id="ball" class="ball"></div>
    </div>
    <div style="text-align:left;"><button id="add">add</button></div>
    </div>
    </body>
    </html>
  • 相关阅读:
    前端安全之XSS攻击
    从JavaScript执行上下文理解变量提升
    em、rem和px的区别
    纯CSS实现幻灯片效果
    小白在使用ISE编写verilog代码综合时犯得错误及我自己的解决办法
    结构体指针中的一点困惑
    xilinx fpga中块ram的使用——简单双端口ram的使用
    在模块中如何去写输出标志位的程序
    学习感悟
    xilinx fpga 生成3*3窗口
  • 原文地址:https://www.cnblogs.com/asqq/p/3194965.html
Copyright © 2020-2023  润新知