這個主題的動畫程式骨架主要是使用Java程式為範例,使用多執行緒來進行動畫的狀態改變,其它的程式語言其實類似, 最後也補充了不使用多執行緒的版本。
Java的程式骨架
package cc.openhome;
import java.awt.*;
import javax.swing.JApplet;
public class AnimationSkeleton extends JApplet implements Runnable {
// 定義多執行緒的方法
public void run() {
// 動畫迴圈
while(true) {
// 動畫的狀態改變、緩衝區繪圖
this.repaint(); // 重繪畫面
// 執行緒暫停 50 毫秒
try {
Thread.sleep(50); // 避免Busy loop
}
catch(InterruptedException e) {
// 例外處理
}
} // while結束
} // run()結束
// 改寫update(),避免畫面不連續
public void update(Graphics g) {
this.paint(g); // 單純呼叫paint()
}
public void paint(Graphics g) {
super.paint(g);
// 繪圖動作
}
}
在這個骨架中,實作Runnable以使用多執行緒進行動畫狀態的改變,在這邊要養成一個習慣:「將動畫狀態的改變與繪 圖兩個工作分開。」這可以讓程式的邏輯更為清楚,雖然不使用多執行緒也可以繪製部份的動畫(例如畫框動畫),但上面這個骨架,在額外進行像是緩衝區繪圖時 相當方便。
其中改寫update()的部份是為了避免繪圖的閃爍,這是因為Java在呼叫repaint()之後,repaint()會先呼叫 update()清除畫面,而update()預設會使用白色背景清除畫面,然後再繪上使用者指定的背景,這會造成Java在繪圖時的閃爍,改寫 update()直接呼叫paint(),讓它不重繪畫面,讓重繪的動作由您控制,以避免閃爍的發生。
HTML 5 Canvas
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=Big5" http-equiv="content-type">
<script type="text/javascript">
window.onload = function() {
var canvas1 = document.getElementById('canvas1');
var context = canvas1.getContext('2d');
setTimeout(function() {
context.beginPath();
context.clearRect(0, 0, canvas1.width, canvas1.height);
// 動畫處理、繪圖緩衝區或清除部份區域
context.stroke();
// 每 20 毫秒重繪
setTimeout(arguments.callee, 20);
}, 20); // 每 20 毫秒重繪
};
</script>
</head>
<body>
<canvas id="canvas1" width="640" height="480"></canvas>
</body>
</html>
如果使用HTML 5 Canvas,由於JavaScript沒有像Java的Thread.sleep()方法,所以可以改用setInterval()來定時執行,動畫進 行最簡單的方式,就是每次清除上一次的畫面再重新繪製,比較複雜的話,可以使用繪圖緩衝區或清除部份區域。
Turbo C 繪圖模式
#include <graphics.h>
#include <stdlib.h>
void modify(); // 改變動畫狀態
void draw(); // 繪圖
int main(void) {
// 啟動繪圖模式
initgraph(&driver, &mode, "c:\\");
// 動畫迴圈
while(1) {
cleardevice(); // 清除螢幕,不一定需要這個函式
draw();
modify();
// 暫停執行
sleep(50); // 避免Busy loop
}
// 關閉繪圖模式
closegraph();
return 0;
}
void modify() {
// 動畫狀態改變
}
void draw() {
// 繪圖
}
在Turbo C中,所有的繪圖與狀態改變都是在while迴圈中進行,函式的設計與使用者的互動必須多花一些心思,程式的邏輯性會變得複雜一些。