貼出一些關(guān)鍵代碼稍作解釋,有興趣的同學(xué)看看。
// ball class function Ball(type,x,y) { ... this.type = type; this.x = x; //位置 this.y = y; this.angle = 0; //角度 this.v = 0; //速度(不包含方向) ... return this; } 描述小球的四個信息,小球的類型(母球,目標(biāo)球),坐標(biāo),角度,速度 在更新坐標(biāo)時,讀取小球的v,刷新小球的位置 在與邊沿碰撞時,更改小球angle
var formPos = getBallPos(cueBall.elem), toPos = getBallPos(guideBall), angle = Math.atan2(toPos[0] - formPos[0],toPos[1] - formPos[1]); 計算母球,與參考球之間的角度,其它任意小球之間也是如此 值得注意的是我采用的是Math.atan2,而非Math.atan,這是因為Math.atan2返回的是(0 - Math.PI)和(-Math.PI - 0),可以確定唯一的角度,而Math.atan不唯一。
//邊緣碰撞 if(ball.x < R || ball.x > W - R) { ball.angle *= -1; ball.v = ball.v * (1 - LOSS); ... if(ball.type == "cue") { if(ball.angle > 0) vy -= rollRight; else vy += rollRight; vx += rollUp; rollUp *= 0.2; rollRight *= 0.2; ball.v = Math.sqrt(vx*vx + vy*vy); ball.angle = Math.atan2(vx,vy); } ... if(ball.y < R || ball.y > H - R) { ball.angle = ball.angle > 0 ? Math.PI - ball.angle : - Math.PI - ball.angle ; ... 不考慮小球旋轉(zhuǎn)時,邊緣碰撞很簡單,更改小球angle即可 當(dāng)小球旋轉(zhuǎn)時,如果碰到固定不動的物體時,那將會把速度作用給自身 并且自身旋轉(zhuǎn)速度減小 我這里計算球與球之間碰撞,并沒有將旋轉(zhuǎn)傳遞,這是不準(zhǔn)確的,有待改善
這一段是核心,即小球與小球碰撞后各自的速度,其實并不難 先判斷兩球距離 var dis = Math.sqrt(Math.pow(disX,2)+Math.pow(disY,2)); if(dis <= gap) { //如果目標(biāo)球是靜止的,則添加到數(shù)組movingBalls if(Math.round(obj.v) == 0) movingBalls.push(obj); //還原兩球相切狀態(tài),用其它方式做我不知道,但用js來做,這一步相當(dāng)關(guān)鍵,否則誤差將相當(dāng)大 ball.x -= (gap - dis)*sin; ball.y -= (gap - dis)*cos; disX = obj.x - ball.x; disY = obj.y - ball.y; // 下面則是先將整個坐標(biāo)系旋轉(zhuǎn)到相撞的水平方向 // 計算角度和正余弦值 var angle = Math.atan2(disY, disX), hitsin = Math.sin(angle), hitcos = Math.cos(angle), objVx = obj.v * Math.sin(obj.angle), objVy = obj.v * Math.cos(obj.angle); //trace(angle*180/Math.PI); // 旋轉(zhuǎn)坐標(biāo) var x1 = 0, y1 = 0, x2 = disX * hitcos + disY * hitsin, y2 = disY * hitcos - disX * hitsin, vx1 = vx * hitcos + vy * hitsin, vy1 = vy * hitcos - vx * hitsin, vx2 = objVx * hitcos + objVy * hitsin, vy2 = objVy * hitcos - objVx * hitsin; // 碰撞后的速度和位置 var plusVx = vx1 - vx2; vx1 = vx2; vx2 = plusVx + vx1; //母球加塞 if(ball.type == "cue") { vx1 += rollUp; rollUp *= 0.2; } x1 += vx1; x2 += vx2; // 將位置旋轉(zhuǎn)回來 var x1Final = x1 * hitcos - y1 * hitsin, y1Final = y1 * hitcos + x1 * hitsin, x2Final = x2 * hitcos - y2 * hitsin, y2Final = y2 * hitcos + x2 * hitsin; obj.x = ball.x + x2Final; obj.y = ball.y + y2Final; ball.x = ball.x + x1Final; ball.y = ball.y + y1Final; // 將速度旋轉(zhuǎn)回來 vx = vx1 * hitcos - vy1 * hitsin; vy = vy1 * hitcos + vx1 * hitsin; objVx = vx2 * hitcos - vy2 * hitsin; objVy = vy2 * hitcos + vx2 * hitsin; //最終速度 ball.v = Math.sqrt(vx*vx + vy*vy) * (1 - 0); obj.v = Math.sqrt(objVx*objVx + objVy*objVy) * (1 - 0); // 計算角度 ball.angle = Math.atan2(vx , vy); obj.angle = Math.atan2(objVx , objVy); }
- 坐標(biāo)旋轉(zhuǎn)的公式:
x1 = Math.cos(angle) * x - Math.sin(angle) * y; y1 = Math.cos(angle) * y + Math.sin(angle) * x;
- 反坐標(biāo)旋轉(zhuǎn):
x1 = Math.cos(angle) * x + Math.sin(angle) * y; y1 = Math.cos(angle) * y - Math.sin(angle) * x;
不一定用坐標(biāo)旋轉(zhuǎn),我只是習(xí)慣了用這種方式來計算碰撞,只要將正向碰撞的速度相差即可
經(jīng)典論壇交流: http://bbs.blueidea.com/thread-2951566-1-1.html
本文鏈接:http://www.95time.cn/tech/web/2009/7086.asp
出處:藍(lán)色理想
責(zé)任編輯:bluehearts
上一頁 JS實現(xiàn)2D桌球小游戲 [1] 下一頁
◎進入論壇網(wǎng)頁制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評論。
|