多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內(nèi)最全IT社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當前位置:首頁 > web前端 > htmlcss > 基于HTML5的小球物理測試系統(tǒng),附實現(xiàn)原理

基于HTML5的小球物理測試系統(tǒng),附實現(xiàn)原理

來源:程序員人生   發(fā)布時間:2014-04-17 13:54:06 閱讀次數(shù):2704次

在線演示:基于HTML5的小球物理測試系統(tǒng)

源碼下載:點擊進入下載頁

功能說明:

一個基于HTML5 canvas的小球物理測試系統(tǒng),用戶可以手動為新的小球設(shè)置不同的屬性值(顏色,半徑,速度等),從而在canvas中發(fā)射小球,小球在運動過程中會收到重力,彈性以及摩擦力的影響。

實現(xiàn)原理:

在小球飛行過程中,以初始速度,入射角以及重力系數(shù)作為依據(jù),正交分解得出小球X軸和Y軸上的分速度,通過定時器不斷刷新canvas,顯示出小球飛行的動畫。當小球和墻壁產(chǎn)生碰撞時,以小球彈性為依據(jù)計算能量損耗,當小球在墻壁滾動時,以墻壁摩擦系數(shù)為依據(jù)計算其能量損耗。

代碼分析:

var bounceWall = (function() {


return function(canvasId,backgroundColor) {
this.init(canvasId, backgroundColor);

}
})();

構(gòu)造函數(shù),其中調(diào)用了prototype中的init方法進行初始化。需要傳入的參數(shù)是canvas的ID,和canvas的背景色,如果不傳入backgroundColor參數(shù),背景色默認為黑色。

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); //彈性
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; //根據(jù)速度和初速度得出其下次移動到的X坐標
this.nextY = this.currentY + this.dy; //根據(jù)速度和初速度得出其下次移動到的Y坐標


};

開始進入到bounce wall的prototype,首先使用Modernizr檢測是否可以使用canvas。Modernizr是一個可以用于檢測瀏覽器是否支持一些新功能的js庫,可以下載直接使用。

之后出現(xiàn)的是小球的構(gòu)造函數(shù)newBall,用戶需要傳入一系列的特性對其進行初始化,具體已經(jīng)在注釋中標出。需要特別注意的是其中的nextX和nextY記錄的是小球下一次出現(xiàn)位置的坐標,它根據(jù)現(xiàn)在的位置(currentX和currentY)以及小球X軸和Y軸上的分速度(dx和dy)計算得出。nextX和nextY屬性的用處主要是保證小球能和墻壁發(fā)生完全的碰撞,會在后面的代碼分析。

    /* 繪制canvas的背景 */
var drawBackground = function(contextObj, backgroundColor, canvasWidth, canvasHeight) {

contextObj.fillStyle = backgroundColor;
contextObj.fillRect(0, 0, parseInt(canvasWidth), parseInt(canvasHeight));

};

之后的函數(shù)是用戶繪制canvas的背景,依據(jù)的屬性是用戶設(shè)定的背景色,canvas的寬度和高度。

 /* 更新小球狀態(tài) */

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

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

/* 測試對墻壁產(chǎn)生是否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);
}

}


/* 測試對墻壁產(chǎn)生是否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;
}


};

接著是核心函數(shù),updateBallState。該函數(shù)的作用是通過小球半徑,canvas寬高等參數(shù),判斷小球是否和墻壁產(chǎn)生碰撞。并根據(jù)對四個不同墻壁的碰撞分別使用不同的處理方法。具體過程如下:

1.首先把上次記錄的nextX和nextY設(shè)置為現(xiàn)在的currentX和currentY,更新了現(xiàn)在小球所處的位置。

2.計算小球的nextX和nextY,這兩個參數(shù)將會決定小球下次所處的位置。

3.如果ballObj.nextX < ballObj.radius,冊小球于左邊的墻壁碰撞,此時把nextX設(shè)置為小球半徑的值,是為了讓小球在完全和墻壁發(fā)生碰撞(和墻壁距離為0)之后,再反彈。

      之后改變小球的速度:

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

      上面這個式子比較長,其中首先通過1 - ballObj.elasticity根據(jù)小球的彈性獲取一個系數(shù),該系數(shù)越大,則小球速度減小得越多。(1 - ballObj.elasticity) * Math.abs(ballObj.dx))) 則是在獲取到剛剛的系數(shù)之后,再和小球現(xiàn)在的速度相乘,得到小球碰撞后減少的速度值。由此可以發(fā)現(xiàn),小球彈性越好(ballObj.elasticity越大),則所減少的速度越少,每次碰撞性能損耗越少。之后再通過乘以-1把速度方向取反??梢园l(fā)現(xiàn)最后還需要把得出的值減1,和0比較取其較大的值,這是因為小球在不斷和墻壁碰撞的過程中,由于每次都是以現(xiàn)有速度的百分比作為減少的速度,所以永遠都不會為0,小球永遠都不會停下。所以這里通過減1,使小球的速度小于1時,速度會自動變成0,使小球最終停下。

4.如果不是和左邊墻壁發(fā)生碰撞,再同理判斷是否和其它墻壁碰撞,若產(chǎn)生碰撞,照例需要改變nextX和nextY,dx或dy的值。

    /* 把小球繪制在canvas中 */
var drawBallsToCanvas = function(ballArray, contextObj, backgroundColor, canvasWidth, canvasHeight, gravityValue, friction) {

return function() {

drawBackground(contextObj, backgroundColor, canvasWidth, 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, 0, 2 * Math.PI, false);

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

updateBallState(ballArray[i], canvasWidth, canvasHeight, gravityValue, friction);


}
}
};

這個方法主要功能是每次定時器觸發(fā)的時候,重新把所有小球繪制到canvas上。具體操作是首先重新畫canvas背景(否則在舊位置的小球會保留在canvas上并顯示出來),然后遍歷保存所有小球的數(shù)組,根據(jù)每個小球的屬性,在canvas上畫出具有新位置的小球,并調(diào)用之前的updateBallState方法,更新小球的屬性,為下次的移動作準備。

  return {
/* 初始化函數(shù) */
init: function(canvasId, backgroundColor, friction, gravityValue) {
if (!CanvasSupport)
return;

this.backgroundColor = backgroundColor || "#000"; //背景色,默認為黑色
this.friction = friction || 0.1; //墻壁摩擦系數(shù),默認為0.1
this.gravityValue = gravityValue || 0.2; //重力系數(shù),默認為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 = []; //保存所有小球的數(shù)組


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

},

最后進入到返回的object,它作為bounceWall的prototype。其中有init的方法,如果瀏覽器不支持canvas則返回,否則初始化一切初始屬性,并啟動setInternal定時器定時更新canvas的狀態(tài)。

        /* 添加小球 */
createBall: function(radius, color, speed, direction, currentX, currentY, elasticity) {// 小球半徑 顏色 速度 方向

var ball = new newBall(radius, color, speed, direction, currentX, currentY, elasticity);


this.ballArray.push(ball);

}

}

})();

添加小球的方法,demo中,該方法在“添加小球”的事件處理程序中被調(diào)用,根據(jù)用戶輸入數(shù)據(jù)進行新小球的添加。

   var wall = new bounceWall('wallCanvas', '#000');     //創(chuàng)建bounce wall

var radiusInput = util.$('radiusInput'); //半徑輸入文本框
var color_Input = util.$('color_Input'); //顏色輸入文本框
var speed_Input = util.$('speed_Input'); //速度輸入文本框
var elaticity_Input = util.$('elaticity_Input'); //彈性輸入文本框
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() { //綁定事件處理程序,調(diào)用creatBall方法創(chuàng)建新小球
wall.createBall(radiusInput.value, color_Input.value, speed_Input.value, inAngle_Input.value, X_Input.value, Y_Input.value, elaticity_Input.value);

}
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 永久在线毛片免费观看 | 日本免费观看网站 | 日本理论免费高清在线视频 | 中文字幕亚洲综合精品一区 | 日本欧美视频在线 | 俺去啦最新地址 | 欧美日本一 | 伊人色婷婷综在合线亚洲 | 怡红院免费的全部视频国产a | 最新在线观看精品国产福利片 | 精品一区二区三区免费站 | 春暖花开亚洲性无区一区二区 | 一级做a爰片性色毛片中国 一级做a爰全过程免费视频毛片 | 欧美大陆日韩一区二区三区 | 亚洲永久免费 | 亚洲国产精品一区二区久久 | 国产精品欧美在线不卡 | 日本成人在线网站 | 国产亚洲美女精品久久久久 | 亚洲欧美日韩中文字幕在线一区 | 亚洲成a v人片在线观看 | 午夜影院在线看 | 精品国产免费一区二区三区 | 日韩爱爱片 | 国产欧美综合在线一区二区三区 | 精品国产乱码久久久久久一区二区 | 日本一级做a爱片 | 欧美日韩精品一区二区在线线 | 国产精品国产亚洲精品看不卡 | 亚洲高清中文字幕一区二区三区 | 美女视频在线观看网站 | 欧美视频日韩专区午夜 | 亚洲色大成网站www久久九九 | 男人吃奶摸下面69视频免费 | 欧美午夜性刺激在线观看免费 | аⅴ资源中文在线天堂 | 国产成人黄网址在线视频 | 手机看片福利日韩 | 色费女人18毛片a级视频在线 | 久久亚洲天堂 | 在线观看亚洲免费 |