播放動畫為什麼還要有個系統待我慢慢講來。
狀態機大家都知道了,就是無限循環的東西。
動畫是由一桢一桢組成的,這個桢和游戲的桢概念不同。但含義都差不多。
每一桢就是組成動畫的一幅畫,上一桢和下一桢可能相同也可能不同,連續播放就可看到動畫的效果 比如一個動畫由12桢組成:(假設 | \—/都是小棍形狀)
|, |, |, \, \, \, —, —, —, /, /, /
那麼連續播放的話,就是播完從頭再撥,就可以看到一個小棍兒在不停的轉。
那麼在一個不斷循環的系統中播放動畫,播完一遍需要12次循環,也就是12桢。
為什麼相同的桢要播放三次,那是因為你要控制它播放的速度。
如果每桢播一次,機器又很快,就是FPS很快,你就會看到一個小棍兒在瘋轉。
相同的一個動畫,如果你的機器快,他的機器慢,在上面看起來效果就不一樣。
但是之前我們講過FPS,講過限桢的概念。
就是把一桢的時間控制在相同的范圍。
如果程序限了桢,不管在哪個機器上,繪制一桢的時間都是確定的。
那麼這個動畫在哪看起來速度都一樣。
那麼現在看看代碼怎麼寫呢?
一個動畫有12桢意味著要播12次。
int frameIndex = 0; //用來記錄一個動畫的當前桢。
while (true) {
if (frameIndex == 0) {
// 畫 |
} else if (frameIndex == 1) {
// 畫 |
} else if (frameIndex == 2) {
// 畫 |
} else if (frameIndex == 3) {
// 畫 \
} else ...........
....................
frameIndex ++; //上面的代碼確保每次只畫一桢,這句話在畫完了之後把frame往下推一個。
}
這樣的代碼很麻煩,也肯定不是一個成熟的游戲需要的。
更簡單些,這樣:
while (true) {
playAnimation();
這個playAnimation() 這樣寫:
int frameIndex = 0;
Image[] animationFrames;
//定義一個圖像數組來存儲一個動畫的每一桢圖像。假設已經被裝載好了。假設是上面那幅動畫,這個數組裡面就存了12幅畫。
(實際不是這樣,還要更仔細一些,例如只存二進制數據而不是一個圖像,到了播放時才即時創建一幅出來。而且相同的桢數據不會重復放在裡面。
現在只是舉個比上面的代碼好點兒的例子。)
public void playAnimation() {
Image currentFrameImage = animationFrames[frameIndex]; //把當前桢的那幅圖給取出來
if (playAnimation) { //現在假設沒有這個變量,往後看。
drawImag(currentFrameImage,...);//畫到屏幕上。(代碼沒寫全,drawImage還有很多參數)
frameIndex ++; // 桢往後推個1。下次畫就是畫下一桢了。
}
if (frameIndex > animationFrames.length) {// 如果播完了12桢怎麼辦?自己決定,是重頭畫還是停止。
//如果重頭畫
//frameIndex = 0;
//如果讓這個動畫畫一遍就停下.
// playAnimation = false;
//現在知道有什麼用了吧?雖然playAnimation還在被一直調用,但已經沒有東西畫出來了。
}
恩, 動畫的播放原理差不多就這樣。
然後再說說詳細說說動畫的組成。
動畫是由一桢一桢的圖像組成。
而每一桢的圖像又是一塊一塊的小圖拼成。
為什麼要這樣做?
一方面,在J2ME程序中,程序+資源包的大小十分受限。
假如做一個小人兒的動畫,就算10桢,就需要10幅畫。
如果再多做幾個小人兒動畫,就是10xN幅畫,太大了。
這樣,就可以把各種各樣小人兒的頭,不同形狀,不同動作,專門做成一整套,一個一個的,或者說看起來一塊一塊的,拼到一個大圖上。
小人兒們的腿,身子,胳膊等等,也都按不同形狀,不同動作等分別做成一整套。
這樣,就可以從這些胳膊腿兒裡面挑一個形狀,挑一個動作,組成一個小人,這就形成了一桢。
不同的形狀,不同的動作的組合可以做很多個不同的動畫,但是資源大小並沒有改變。(不能貼圖,google應該改進.)
另外一方面,碰撞檢測。
在播放動畫的時候,往往需要檢測一個動畫和另一個動畫是否碰撞在一起。
例如,街霸。
那麼檢測碰撞,不是檢測整個一桢的碰撞,而是這一桢中,人的胳膊腿兒等的碰撞。
這樣,把一大塊桢分開成小的模塊,也更合理。
這個組成桢的基本單位,術語稱作"Module"。
在這裡不多說,其實我也說不出啥東西。還是要自己做,自己研究。
還有動畫的應用。
例如我們要播放一個片頭動畫,這很常見。展示我們的logo之類的。
就這樣。
while (true) {
playAnimation(mylogo);
我們要讓主角行走。
while (true) {
player.setAction(walk); //把動畫封裝在一個player類中。
player.update(); // 之前玩家已經把動作設置成為walk了。現在來更新這個動作。其實就是動畫的播放
public class Player {
int action;
public void update() {
switch (action) {
case walk:
playAnimation(walkAnimation); //呵呵,怎麼樣?這就差不多是AI了,只不過這個AI只是會播放動畫
//再隨便瞎寫幾句
if (keyPressed(Num4)) {
//如果按了四鍵,就讓玩家的位置發生變化。相應的,playAnimation裡繪制桢的坐標就發生了變化。
//這樣看起來,主角就是一邊做walk的動作一邊移動了。呵呵。像真實世界中的。
posX -= 20; //往左移動。
}
break;
}
}