為什么要重新寫一個for循環,直接寫在第一個循環里為什么不正常了?
function updateBalls(){
for(var i = 0;i<balls.length;i++){
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
balls[i].vy += balls[i].g;
if(balls[i].y >= WINDOW_HEIGHT - RADIUS){
balls[i].y = WINDOW_HEIGHT - RADIUS;
balls[i].vy = -balls[i].vy*0.5;
? ?}
}
var cnt = 0;
? ?for( var i = 0 ; i < balls.length ; i ++ )
? ? ? ?if( balls[i].x + RADIUS > 0 && balls[i].x -RADIUS < WINDOW_WIDTH )
? ? ? ? ? ?balls[cnt++] = balls[i];
? ?while( balls.length > cnt ){
? ? ? ?balls.pop();
? ?}
? ? ? ?
}
2016-10-16
剛好在寫這里的代碼,共同學習,互相交流啦。
在這個函數里有三個循環。
前兩個for循環,乍一看循環條件都是一樣的,貌似可以合并。我判斷這兩個for到底能不能合并寫成一個for,主要是看他們是否互有影響。
老師的代碼中,第一個for在算小球下一個瞬間的運動位置(籠統地看,就是在計算每個球的運動軌跡),順便用if保證了碰到畫布下邊界后小球將回彈。第二個for,在if中限制了小球在左邊界的位置和小球在右邊界的位置。即保證小球一定出現在畫布上,計算所有在畫布上的小球,并把它們推到數組的最前方。這里是要得到cnt的值。內容上看,這兩個for循環的內容是可以合并的。
等價于
這里有個沒有聲明的默認條件,即cnt永遠小于等于balls.length,也就是說,第二個for循環的內容不會改變balls.length的值,即不會影響 i 循環的次數。從邏輯上看,這兩個for循環的內容也是可以合并的。所以我在代碼中把兩個for合并了,暫時未看到什么影響~
其實這也間接回答了你的問題,因為在for循環里,cnt的值是從0開始遞增的,我們想得到的是畫布上的出現小球總數。而balls里面放的是所有球(即畫布上我們可視區域內和從畫布邊緣消失的不可見但存在的球)。while做的事情就是去掉balls數組中我們不可見的球,及時縮減維護數組的總長度(每個瀏覽器都對數組的最長值有限制的,而且數組過長還會帶來性能卡頓等等問題,,),所以要等到 cnt 確定后再進行操作。舉個例子,按照樓主的寫法,如果while放在離他最近那個for循環里的話,第一次循環時,i=0,cnt=1,當?balls.length > 1 時刪除數組末尾的項。。。balls數組。。。就會只剩第一項了吧~
2016-05-20
如果要是想少寫一個for,可以這樣寫:
??? var cnt = 0;
?? ?for( var i = 0 ; i < balls.length ; i ++ ){
?? ?? balls[i].x += balls[i].vx;
??????? balls[i].y += balls[i].vy;
??????? balls[i].vy += balls[i].g;
??????? if( balls[i].y >= WINDOW_HEIGHT-RADIUS ){
??????????? balls[i].y = WINDOW_HEIGHT-RADIUS;//小球落地的位置,垂直
??????????? balls[i].vy = - balls[i].vy*0.75;//小球彈起的速度,垂直
??????? }
???????
??????? if(balls[i].x+RADIUS>0&&balls[i].x-RADIUS<WINDOW_WIDTH){
?????? ??? ?balls[cnt++]=balls[i];
??????? }
?? ?}
?? ?
?? ?while(balls.length>Math.min(300,cnt)){
?? ??? ?balls.pop();//消除數組末尾的小球
?? ?}