zoukankan      html  css  js  c++  java
  • [Canvas]碰撞球 增加小球间碰撞检测

    点此下载代码并用Chrome或是Firefox打开index.html

    图例:

    代码:

    <!DOCTYPE html>
    <html lang="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <head>
         <title>碰撞球 19.3.3 18:11 by:逆火 horn19782016@163.com</title>
         
         <style>
         #canvas{
            background:#ffffff;
            cursor:pointer;
            margin-left:10px;
            margin-top:10px;
            -webkit-box-shadow:3px 3px 6px rgba(0,0,0,0.5);
            -moz-box-shadow:3px 3px 6px rgba(0,0,0,0.5);
            box-shadow:3px 3px 6px rgba(0,0,0,0.5);
         }
         
         #controls{
            margin-top:10px;
            margin-left:15px;
         }
         </style>
         
        </head>
    
         <body onload="init()">
            <div id="controls">
                <input id='animateBtn' type='button' value='运动'/>
            </div>
         
            <canvas id="canvas" width="750px" height="500px" >
                出现文字表示你的浏览器不支持HTML5
            </canvas>
         </body>
    </html>
    <script type="text/javascript">
    <!--
    var paused=true;
    animateBtn.onclick=function(e){
        paused=! paused;
        
        if(paused){
            animateBtn.value="运动";
        }else{
        
            animateBtn.value="暂停";
            window.requestAnimationFrame(animate); 
        }
    }
    
    var ctx;// 绘图环境
    var balls;// 球数组
    function init(){
    
    
        var canvas=document.getElementById('canvas');
        canvas.width=750;
        canvas.height=500;
        ctx=canvas.getContext('2d');
    
        balls=[
            {    
                x:150,
                y:250,
                vx:-7.2,
                vy:3.8,
                radius:25,
                innerColor:'rgba(255,25,0,1)',
                middleColor:'rgba(255,25,0,0.7)',
                outerColor:'rgba(255,25,0,0.5)',
                strokeStyle:'gray',
            },
            
            {    
                x:650,
                y:50,
                vx:-8.2,
                vy:2.5,
                radius:25,
                innerColor:'rgba(113,232,227,1)',
                middleColor:'rgba(113,232,227,0.7)',
                outerColor:'rgba(113,232,227,0.5)',
                strokeStyle:'red',
            },
            
            {    
                x:50,
                y:150,
                vx:12,
                vy:-14,
                radius:25,
                innerColor:'rgba(23,45,227,1)',
                middleColor:'rgba(23,45,227,0.7)',
                outerColor:'rgba(23,45,227,0.5)',
                strokeStyle:'blue',
            },
            
            {    
                x:30,
                y:60,
                vx:8,
                vy:-24,
                radius:25,
                innerColor:'rgba(23,45,69,1)',
                middleColor:'rgba(23,45,69,0.7)',
                outerColor:'rgba(23,45,69,0.5)',
                strokeStyle:'yellow',
            },
            
            {    
                x:300,
                y:300,
                vx:80,
                vy:-34,
                radius:25,
                innerColor:'rgba(123,45,69,1)',
                middleColor:'rgba(123,45,69,0.7)',
                outerColor:'rgba(123,45,69,0.5)',
                strokeStyle:'navy',
            },
       ];
    
    };
    
    function update(){
        for(var i=0;i<balls.length;i++){
            var ball=balls[i];
            
            // 与左右墙壁的碰撞检测
            if(ball.x+ball.vx+ball.radius>ctx.canvas.width || ball.x+ball.vx-ball.radius<0){
                ball.vx=-ball.vx;
            }
            
            // 与上下墙壁的碰撞检测
            if(ball.y+ball.vy+ball.radius>ctx.canvas.height || ball.y+ball.vy-ball.radius<0){
                ball.vy=-ball.vy;
            }
            
    
            // 小球之前的碰撞检测
            for(var j=0;j<balls.length;j++){
                if(i!=j){
                    var other=balls[j];
                    
                    var distance=Math.sqrt( Math.pow((ball.x+ball.vx-other.x-other.vx),2)+Math.pow((ball.y+ball.vy-other.y-other.vy),2));
                    
                    if(distance<ball.radius+other.radius){
                        // 如果两个碰撞小球的质量相等,联立动量守恒和能量守恒方程时可解得:两个小球碰撞后交换速度。
                        var x=ball.vx;
                        ball.vx=other.vx;
                        other.vx=x;
                    
                        var y=ball.vy;
                        ball.vy=other.vy;
                        other.vy=y;
                    }
                }
            }
            
            ball.x+=ball.vx;
            ball.y+=ball.vy;
        }
    }
    
    function draw(){
        ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
        
        for(var i=0;i<balls.length;i++){
            var ball=balls[i];
            
            gradient=ctx.createRadialGradient(ball.x,ball.y,0,ball.x,ball.y,ball.radius);
            gradient.addColorStop(0.3,ball.innerColor);
            gradient.addColorStop(0.5,ball.middleColor);
            gradient.addColorStop(1.0,ball.outerColor);
            
            ctx.save();
            ctx.beginPath();
            ctx.arc(ball.x,ball.y,ball.radius,0,Math.PI*2,false);
            ctx.fillStyle=gradient;
            ctx.strokeStyle=ball.strokeStyle;
            ctx.fill();
            ctx.stroke();
            ctx.restore();
        }
    }
    
    function animate(){
        if(!paused){
    
            update();
            draw();
        
            setTimeout( function(){
                window.requestAnimationFrame(animate); /// 让浏览器自行决定帧速率
            }, 0.10 * 1000 );// 延时执行
        }
    }
    //-->
    </script>

    2019年3月3日20点17分

  • 相关阅读:
    SpringBoot 线程池配置 定时任务,异步任务
    使用Calendar类对时间进行处理
    单例模式的几种实现方式
    一些簡單的入門算法
    OO第四单元博客
    OO第三单元博客
    OO第二单元博客
    OO第一单元博客
    BUAA_OO_2020_Unit4_Wandy
    BUAA_OO_UNIT3_2020
  • 原文地址:https://www.cnblogs.com/heyang78/p/10467329.html
Copyright © 2011-2022 走看看