基于HTML5的小球物理测试系统,附实现原理

基于HTML5的小球物理测试系统,附实现原理,第1张

概述在线演示:基于HTML5的小球物理测试系统源码下载:点击进入下载页功能说明:一个基于HTML5 canvas的小球物理测试系统,用户可以手动为新的小球设置不同的属性值(颜色,半径,速度等),从而在canvas中发射小球,小球在运动过程中会收到重力,d性以及摩擦力的影响。实现原理:在小球飞…

在线演示:基于HTML5的小球物理测试系统

源码下载:点击进入下载页

功能说明:

一个基于HTML5 canvas的小球物理测试系统,用户可以手动为新的小球设置不同的属性值(颜色,半径,速度等),从而在canvas中发射小球,小球在运动过程中会收到重力,d性以及摩擦力的影响。

实现原理:

在小球飞行过程中,以初始速度,入射角以及重力系数作为依据,正交分解得出小球X轴和Y轴上的分速度,通过定时器不断刷新canvas,显示出小球飞行的动画。当小球和墙壁产生碰撞时,以小球d性为依据计算能量损耗,当小球在墙壁滚动时,以墙壁摩擦系数为依据计算其能量损耗。

代码分析:

var bounceWall = (function() {


return function(canvasID,backgroundcolor) {
this.init(canvasID,backgroundcolor);

}
})();

构造函数,其中调用了prototype中的init方法进行初始化。需要传入的参数是canvas的ID,和canvas的背景色,如果不传入backgroundcolor参数,背景色默认为黑色。

bounceWall.prototype = (function() {

var CanvasSupport = Modernizr.canvas; //检查浏览器是否支持canvas
var newBall = function(radius,color,speed,direction,currentX,currentY,elasticity) {

this.radius = parsefloat(radius); //半径
this.color = color; //颜色
this.speed = parsefloat(speed); //速度
this.elasticity = parsefloat(elasticity); //d性
this.direction = parsefloat(direction); //入射角
this.currentX = parsefloat(currentX); //初始X坐标
this.currentY = parsefloat(currentY); //初始Y坐标
this.dx = speed * Math.cos(this.direction * Math.PI / 180); //计算其X轴方向的初始速度
this.dy = speed * Math.sin(this.direction * Math.PI / 180); //计算其Y轴方向的初始速度
this.nextX = this.currentX + this.dx; //根据速度和初速度得出其下次移动到的X坐标
this.nextY = this.currentY + this.dy; //根据速度和初速度得出其下次移动到的Y坐标


};

开始进入到bounce wall的prototype,首先使用Modernizr检测是否可以使用canvas。Modernizr是一个可以用于检测浏览器是否支持一些新功能的Js库,可以下载直接使用。

之后出现的是小球的构造函数newBall,用户需要传入一系列的特性对其进行初始化,具体已经在注释中标出。需要特别注意的是其中的nextX和nextY记录的是小球下一次出现位置的坐标,它根据现在的位置(currentX和currentY)以及小球X轴和Y轴上的分速度(dx和dy)计算得出。nextX和nextY属性的用处主要是保证小球能和墙壁发生完全的碰撞,会在后面的代码分析。

    /* 绘制canvas的背景 */
var drawBackground = function(contextObj,backgroundcolor,canvasWIDth,canvasHeight) {

contextObj.fillStyle = backgroundcolor;
contextObj.fillRect(0,parseInt(canvasWIDth),parseInt(canvasHeight));

};

之后的函数是用户绘制canvas的背景,依据的属性是用户设定的背景色,canvas的宽度和高度。

 /* 更新小球状态 */

var updateBallState = function(ballObj,canvasHeight,gravityValue,friction) {

ballObj.currentX = ballObj.nextX;
ballObj.currentY = ballObj.nextY;
ballObj.nextX = ballObj.currentX + ballObj.dx;
ballObj.nextY = ballObj.currentY + ballObj.dy;

/* 测试对墙壁产生是否X轴碰撞 */

if (ballObj.nextX < ballObj.radius) {
ballObj.nextX = ballObj.radius;
ballObj.dx = Math.max(0,(ballObj.dx + ((1 - ballObj.elasticity) * Math.abs(ballObj.dx))) * -1 - 1);
}
else if ((ballObj.nextX + ballObj.radius) > parseInt(canvasWIDth)) {
ballObj.nextX = parseInt(canvasWIDth) - ballObj.radius;
ballObj.dx = Math.min(0,(ballObj.dx - ((1 - ballObj.elasticity) * Math.abs(ballObj.dx))) * -1 + 1);
}

/* 水平运动时受摩擦力影响 */
else if (ballObj.currentY >= (parseInt(canvasHeight) - ballObj.radius)) {

if (ballObj.dx > 0) {
ballObj.dx = Math.max(0,ballObj.dx - (ballObj.dx * friction) - 0.01);
}
else if (ballObj.dx < 0) {
ballObj.dx = Math.min(0,ballObj.dx - (ballObj.dx * friction) + 0.01);
}

}


/* 测试对墙壁产生是否Y轴碰撞 */
if (ballObj.nextY < ballObj.radius) {
ballObj.nextY = ballObj.radius;
ballObj.dy = Math.max(0,(ballObj.dy + ((1 - ballObj.elasticity) * Math.abs(ballObj.dy))) * -1 - 1);
}
else if ((ballObj.nextY + ballObj.radius) > parseInt(canvasHeight)) {
ballObj.nextY = parseInt(canvasHeight) - ballObj.radius;
ballObj.dy = Math.min(0,(ballObj.dy - ((1 - ballObj.elasticity) * Math.abs(ballObj.dy))) * -1 + 1);

}
else {
ballObj.dy = ballObj.dy + gravityValue;
}


};

接着是核心函数,updateBallState。该函数的作用是通过小球半径,canvas宽高等参数,判断小球是否和墙壁产生碰撞。并根据对四个不同墙壁的碰撞分别使用不同的处理方法。具体过程如下:

1.首先把上次记录的nextX和nextY设置为现在的currentX和currentY,更新了现在小球所处的位置。

2.计算小球的nextX和nextY,这两个参数将会决定小球下次所处的位置。

3.如果ballObj.nextX < ballObj.radius,册小球于左边的墙壁碰撞,此时把nextX设置为小球半径的值,是为了让小球在完全和墙壁发生碰撞(和墙壁距离为0)之后,再反d。

      之后改变小球的速度:

ballObj.dx = Math.max(0,(ballObj.dx + ((1 - ballObj.elasticity) * Math.abs(ballObj.dx))) * -1 - 1);

      上面这个式子比较长,其中首先通过1 - ballObj.elasticity根据小球的d性获取一个系数,该系数越大,则小球速度减小得越多。(1 - ballObj.elasticity) * Math.abs(ballObj.dx))) 则是在获取到刚刚的系数之后,再和小球现在的速度相乘,得到小球碰撞后减少的速度值。由此可以发现,小球d性越好(ballObj.elasticity越大),则所减少的速度越少,每次碰撞性能损耗越少。之后再通过乘以-1把速度方向取反。可以发现最后还需要把得出的值减1,和0比较取其较大的值,这是因为小球在不断和墙壁碰撞的过程中,由于每次都是以现有速度的百分比作为减少的速度,所以永远都不会为0,小球永远都不会停下。所以这里通过减1,使小球的速度小于1时,速度会自动变成0,使小球最终停下。

4.如果不是和左边墙壁发生碰撞,再同理判断是否和其它墙壁碰撞,若产生碰撞,照例需要改变nextX和nextY,dx或dy的值。

    /* 把小球绘制在canvas中 */
var drawBallsToCanvas = function(ballArray,contextObj,friction) {

return function() {

drawBackground(contextObj,canvasHeight);

for (var i = 0,len = ballArray.length; i < len; i++) {
contextObj.beginPath(); deBUGger;
contextObj.fillStyle = ballArray[i].color;
contextObj.arc(ballArray[i].currentX,ballArray[i].currentY,ballArray[i].radius,2 * Math.PI,false);

contextObj.fill();
contextObj.closePath();

updateBallState(ballArray[i],friction);


}
}
};

这个方法主要功能是每次定时器触发的时候,重新把所有小球绘制到canvas上。具体 *** 作是首先重新画canvas背景(否则在旧位置的小球会保留在canvas上并显示出来),然后遍历保存所有小球的数组,根据每个小球的属性,在canvas上画出具有新位置的小球,并调用之前的updateBallState方法,更新小球的属性,为下次的移动作准备。

  return {
/* 初始化函数 */
init: function(canvasID,friction,gravityValue) {
if (!CanvasSupport)
return;

this.backgroundcolor = backgroundcolor || "#000"; //背景色,默认为黑色
this.friction = friction || 0.1; //墙壁摩擦系数,默认为0.1
this.gravityValue = gravityValue || 0.2; //重力系数,默认为0.2
this.canvasObj = util.$(canvasID); //canvas对象
this.canvasWIDth = util.getComputedStyle(this.canvasObj).wIDth; //canvas高度
this.canvasHeight = util.getComputedStyle(this.canvasObj).height;//canvas宽度
this.contextObj = this.canvasObj.getContext('2d'); //2d的context对象
this.ballArray = []; //保存所有小球的数组


drawBackground(this.contextObj,this.backgroundcolor,this.canvasWIDth,this.canvasHeight);
setInterval(drawBallsToCanvas(this.ballArray,this.contextObj,this.canvasHeight,this.gravityValue,this.friction = 0.1),33);

},

最后进入到返回的object,它作为bounceWall的prototype。其中有init的方法,如果浏览器不支持canvas则返回,否则初始化一切初始属性,并启动setInternal定时器定时更新canvas的状态。

        /* 添加小球 */
createBall: function(radius,elasticity) {// 小球半径 颜色 速度 方向

var ball = new newBall(radius,elasticity);


this.ballArray.push(ball);

}

}

})();

添加小球的方法,demo中,该方法在“添加小球”的事件处理程序中被调用,根据用户输入数据进行新小球的添加。

   var wall = new bounceWall('wallCanvas','#000');     //创建bounce wall

var radiusinput = util.$('radiusinput'); //半径输入文本框
var color_input = util.$('color_input'); //颜色输入文本框
var speed_input = util.$('speed_input'); //速度输入文本框
var elaticity_input = util.$('elaticity_input'); //d性输入文本框
var inAngle_input = util.$('inAngle_input'); //入射角输入文本框
var X_input = util.$('X_input'); //初始X坐标输入文本框
var Y_input = util.$('Y_input'); //初始Y坐标输入文本框


var btn = util.$('add_btn'); //添加小球按钮
btn.onclick = function() { //绑定事件处理程序,调用creatBall方法创建新小球
wall.createBall(radiusinput.value,color_input.value,speed_input.value,inAngle_input.value,X_input.value,Y_input.value,elaticity_input.value);

}
总结

以上是内存溢出为你收集整理的基于HTML5的小球物理测试系统,附实现原理全部内容,希望文章能够帮你解决基于HTML5的小球物理测试系统,附实现原理所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/web/1023670.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存