輕輕鬆鬆學習JavaScript

來源:互聯網
上載者:User

JavaScript 的曆史雖短,但卻發展迅速。最初NetScape開發了LiveScript語言,使得它的Navigator和Web 服務器產品有了基本的指令碼編寫功能。當 Navigator 2.0中加入了Java小程式後,NetScape才把LiveScript變成了JavaScript,至此JavaScript誕生。

本文將以一個有趣的小程式為開端,介紹JavaScript的基本文法與功能。此趣味程式為小球碰撞模擬程式,它可模擬彈性碰撞和動能有損的不完全恢複碰撞。你若想瞭解此常式中的球間碰撞處理常式,需熟悉向量的座標旋轉和一些基本的物理學知識。如果你對此一竅不通,也沒什麼關係,因為對於小球之間的碰撞程式僅為幾個函數,你只管調用就是了,這並不影響我們對JavaScript 的學習。之所以要寫這樣一個帶點旁門左道的趣味常式,只是希望你對JavaScript多增加一分興趣。

廢話就不多說,現在開始吧。

第一步:材料的準備

製作兩張小球圖片,紅球 、藍球 各一張。圖片格式為 GIF。你可先用3D軟體製作出立體球圖片,然後再將其轉為GIF格式,這樣程式動畫會顯得更加逼真。需注意的是圖片背景一定要透明,不然就會讓人看出破綻。最後還需一張背景圖,圖片格式同上。

第二步:編寫首頁骨架

1. 在NetObject ScriptBuilder 中用New 命令產生一個HTML檔案的骨架。順便在新產生的HTML檔案中,將TITLE標誌之間的文字改為"小球碰撞模擬示範程式"。

2. 加入背景圖案和小球圖片資源。
將BODY標誌改為,此語句中的background 屬性指定window.gif 為背景圖案。

為載入小球圖片資源,在標誌與間添加以下兩句

這兩句HTML指令碼的含義完全相同,標誌IMG用於加入圖片資源,其中SRC屬性指明加入的圖片檔案名稱。ID屬性指出圖片的對象名稱,這是個重要屬性,因為以後在JavaScript 編程中要使用它。如第一句中,指明BallBlue為圖片資源的對象名稱(你可以把它想象成變數名)。STYLE屬性指明圖片在瀏覽器中的風格,其中"position" 開關設為"absolute",這樣圖片在視窗中的定位就可使用絕對座標模式,而非文本行模式。

HTML 部分的編寫到此完成。接下來該用JavaScript 讓圖片動起來了。

第三步:編寫JavaScript 程式

1.模擬程式使用視窗對象的SetTimeout()方法迴圈調用Move_Step()函數,達到移動圖片的目的,而Move_Step()根據速度向量來計算移動一步的長度和方向。碰撞處理分為兩部分,第一是球對牆壁的碰撞處理,其處理函數為Ball_Crash_Wall(),第二是球體之間的碰撞處理,其處理函數為Ball_Crash_Ball()。還需設定一些碰撞標誌變數,記錄當前碰撞狀態,以避免模擬誤差帶來的錯誤,也許現在你還不明白為什麼誤差會導致錯誤,不要緊,後面會慢慢告訴你。

2.圖片對象使用屬性 style.pixelLeft、style.pixelTop 指定圖片在視窗上的位
置,這兩個屬性是圖片運動的關鍵。不過在計算圖片移動位置時並不用它,而是用陣列變數BallCoord 記錄圖片當前座標位置,因為屬性 style.pixelLeft、style.pixelTop 是整型變數,而在計算碰撞中有小數產生,這樣如果直接用 style.pixelLeft、style.pixelTop 記錄位置,除了有誤差,最重要的是在視窗邊緣發生某些類型的球間碰撞時,會產生小球被撞出螢幕的錯誤。而陣列變數可為浮點型,用於存放小數,從而避免了錯誤的發生。

(一)變數定義與程式的初始化

JavaScript 語句可放在HTML檔案的主體(BODY區)中或檔案頭(HEAD區)中,區別是HEAD 區一般擺放預製好的函數和全域變數,以供BODY區的語句調用,而BODY區一般放入程式初始語句。JavsScript 的變數定義比較自由,但仍需滿足先定義後使用的基本規則。

1.在HEAD區中定義全域變數:
Window_Top = 22 //視窗頂端位置。
Window_Left = 22 //視窗左端位置。
Window_Bottom = 294 //視窗底端位置。
Window_Right = 590 //視窗右端位置。
Setp_Proportion = 3.00 //速度放大比率。

BallCoord = new Array(new Array(2),new Array(2)) //定義一個二維數組,用於記錄兩球的當前座標。

BallDiametre = new Array(66,92) //定義一維數組,存放兩球的直徑,其值分別為66和92。

BallMoveVector = new Array(new Array(2,1),new Array(1,-2))//定義一個二維數組,用於記錄兩球的速度向量,第二維分別存放X與Y軸的速度。

CrashingWall = new Array(new Array(false,false,false,false),new Array(false,false,false,false))//數組 CrashingWall 用於避免牆壁碰撞的二次計算,值為 true ,表明當前處於碰撞狀態。初值為 false。

2.在BODY區中完成程式的初始工作。其內容如下:

這裡你已經看見了一個JavaScript 程式的架構。標誌SCRIPT 告訴瀏覽器,下面的內容為指令碼程式,用LANGUAGE="JavaScript" 指明程式語言為JavaScript。不管是在BODY區,還是HEAD區中,任何JavaScript程式必須放在 標誌之間。程式中用 new Array() 定義了一個數組Balls,以便以後存放圖片對象。接下來的語句Balls[0] = BallBlue 將圖片對象BallBlue 賦給Balls[0],如果你細心,你會發現BallBlue正是載入圖片資源語句中指定的對象名。語句Balls[0].style.pixelTop = BallCoord[0][0] = 100,同時將值100賦給陣列變數BallCoord[0][0]和圖片對象的style.pixelTop屬性。從而座標陣列變數BallCoord[0][0]得到了初值並且指定了球1的初始頂端位置。其餘語句的含義雷同。最後一句調用函數Move_Step()將小球移動一步。

(二) 單步移動函數Move_Step()講解

在HTML檔案的HEAD區中編寫Move_Step() 函數其內容如下:
function Move_Step() {
Ball_Crash_Ball() //調用球間碰狀處理函數

Balls_Crash_Wall(0) //調用藍球碰牆處理函數
Balls_Crash_Wall(1) //調用紅球碰牆處理函數

//計算移動步長
BallCoord[0][0] += BallMoveVector[0][0] * Setp_Proportion
BallCoord[0][1] += BallMoveVector[0][1] * Setp_Proportion
BallCoord[1][0] += BallMoveVector[1][0] * Setp_Proportion
BallCoord[1][1] += BallMoveVector[1][1] * Setp_Proportion
//移動一步
Balls[0].style.pixelTop = BallCoord[0][0]
Balls[0].style.pixelLeft = BallCoord[0][1]
Balls[1].style.pixelTop = BallCoord[1][0]
Balls[1].style.pixelLeft = BallCoord[1][1]
window.setTimeout("Move_Step()",100) //100毫秒後再次調用Move_Step()函數
}
該函數的大部分含義,你可看其中的注釋,這裡只對幾點加以說明。

1在語句BallCoord[0][0] += BallMoveVector[0][0] * Setp_Proportion中, BallMoveVector數組存放著速度向量。Setp_Proportion 變數存放步長放大比率,BallMoveVector[0][0] 乘以Setp_Proportion 得到移動一步的長度。最後該語句加上BallCoord[0][0]原值後再賦給BallCoord[0][0]本身,得到移動位置。

2.語句window.setTimeout("Move_Step()",100) 表示100毫秒後再次調用Move_Step()函數。現在有了setTimeout()方法,程式就不斷的迴圈起來了。

Ball_Crash_Ball()是小球之間的碰撞處理函數, 你只管調用就是了,如果你不使用它,程式一樣能運行,只是少了處理球間碰撞的功能。(在Ball_Crash_Ball()函數中調用了函數CrashEnd_Speed() 與atan360(x,y),以及使用了全域變數CrashingBalls,因而要正確使用它,必須將以上所說的函數與變數都拷入你的程式中)

(三) 在HEAD區中編寫牆壁碰撞處理函數Balls_Crash_Wall()

一個簡化的函數如下:

function Balls_Crash_Wall(i) {

if( BallCoord[i][0] <= Window_Top)
BallMoveVector[i][0] = - BallMoveVector[i][0]

if ( BallCoord[i][1] <= Window_Left)
BallMoveVector[i][1] = - BallMoveVector[i][1]

if ( BallCoord[i][0] + BallDiametre[i] >= Window_Bottom)
BallMoveVector[i][0] = - BallMoveVector[i][0]

if ( BallCoord[i][1] + BallDiametre[i] >= Window_Right)
BallMoveVector[i][1] = - BallMoveVector[i][1]

}

函數首先判斷是否球已經碰到了牆壁,如是就將相應方向上的速度方向反向,而大小不變。但這個函數有可能發生錯誤(錯誤發生的原因有些複雜,這裡只梢作提示。由於小球移動的步長往往大於1個點,而模擬又是離散進行的,從而在有些情況下會發生錯誤)。需用陣列變數CrashingWall 來標識碰撞狀態,使得小球與牆壁處於碰撞狀態時不能再發生第二次小球與牆壁的碰撞,相應的語句也要更改,如第一句改為

if( BallCoord[i][0] <= Window_Top)
{ if (!CrashingWall[i][0]) { BallMoveVector[i][0] = - BallMoveVector[i][0] }
CrashingWall[i][0] = true
} else CrashingWall[i][0] = false

語句中CrahingWall數組的類型為邏輯型,記錄球與牆壁是否正在發生碰撞。當為碰撞狀態時,就不必再將球的運動方向反向。

到此程式的編寫基本完成,其它詳細內容見光碟片的原程式及說明。現在在NetObject ScriptBuilder 中選擇菜單Preview 項,運行程式。

附註:
1. 運行本常式需先安裝IE4.0以上瀏覽器 或Netscape Navigator 4.0以上瀏覽器

2. 球間碰撞處理提示:當兩球發生碰撞時,計算兩球圓心連線與X軸的夾角。在依據此夾角對座標進行旋轉。將原速度向量映射到旋轉後的座標中。從而將球間的任意碰撞轉變為正對心碰撞。用衝量定理可推出碰後的速度計算公式。然後再將座標旋轉成原始座標。可得碰撞後的速度向量。看了上面的文字是不是有些煩人,其實並非如此,程式中只用了11行語句就完成了全部計算。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.