捲軸背景


橫向捲軸或縱向捲軸的遊戲大家應該有玩過,其背景其本身都很單調,例如一個星空不斷的移動,或是一個海洋,其實它 只使用到一張背景圖片不斷的播放而已,其製作的概念是將圖片的兩端接起來,然後像跑馬燈一樣不斷的捲動,所以背景就會循環播放,如下圖所示:



當然電腦上的圖片可無法像紙片一樣的「捲」起來,我們製作的方法是在播放區域超出圖片範圍時,從圖片後端剪下一段並補到播放畫面上,如下圖所示: 


按照以上,只要稍微計算一下,就可以輕易的製作出捲動的效果,不過這邊要介紹一個投機但方便的方法,可以省下一些運算的成本,我們將背景圖 片複製為兩個,首先一張圖的繪製目標X1位置由0開始,另一張圖繪製目標位置X2由-ImageWidth開始,也就是在繪圖區域之外,其中 ImageWidth為圖片寬度,如下圖所示:


X1與X2都一直向右移動,所以圖片可以完美的播放,如果X1超過繪圖區域右緣了,就將X1設定為-ImageWidth,同樣的,如果X2超出繪圖區域 右緣,就將之再設定為-ImageWidth,如此循環不已,背景就可以不斷的播放了。

捲軸背景的基本工作原理還可以再變化一下,例如可以製作遠景與近景,遠景在螢幕上方更新,圖片更新速度較慢,而近景在螢幕下方更新,而更新速度較快,還有 如雲彩的行進等等,像這類的變化應用不少。

連結 示範星空背 景的捲軸播放,以下是示範程式:
  • ScrollBackground.java
package cc.openhome;

import java.awt.*;
import javax.swing.JApplet;

public class ScrollBackground extends JApplet implements Runnable {
private int imageWidth;
private int x1, x2;
private Image scrollImage, offScreen;

public void init() {
//取得捲動畫面影像
MediaTracker mediaTracker = new MediaTracker(this);
scrollImage = getImage(getDocumentBase(),"scroll.gif");
mediaTracker.addImage(scrollImage,0);

try {
mediaTracker.waitForAll();
}
catch(InterruptedException e){
e.printStackTrace();
}

offScreen = createImage(getWidth(), getHeight());

imageWidth = scrollImage.getWidth(this);

x1 = 0;
x2 = -imageWidth;
}

public void start() {
(new Thread(this)).start();
}

public void paint(Graphics g) {
g.drawImage(offScreen, 0, 0, this);
}

public void update(Graphics g) {
paint(g);
}

public void run() {
Graphics gOffScreen = offScreen.getGraphics();

while(true) {
gOffScreen.drawImage(scrollImage, x1, 0, this);
gOffScreen.drawImage(scrollImage, x2, 0, this);

repaint();

try {
Thread.sleep(20);
}
catch(InterruptedException e){
e.printStackTrace();
}

//更新影像位置(產生捲動效果)
if(x1 == getWidth()) {
x1 = -imageWidth;
}
else {
x1++;
}

if(x2 == getWidth()) {
x2 = -imageWidth;
}
else {
x2++;
}
}
}
}

以下是使用HTML5 Canvas的方式(如果瀏覽器支援HTML5 Canvas,例如最新版的Firexfox、Chrome、IE9等,可以直接將下面的內容存為HTML或按下檔名連結,直接載入瀏覽器執行觀看結果:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=Big5" http-equiv="content-type">
<script type="text/javascript">
window.onload = function() {
var img = new Image();
img.onload = function() {
var canvas1 = document.getElementById('canvas1');
var canvas2 = document.getElementById('canvas2');
var context1 = canvas1.getContext('2d');
var context2 = canvas2.getContext('2d');

var imageWidth = img.width;
var x1 = 0;
var x2 = -imageWidth;

var context = context2;
setTimeout(function() {
context.drawImage(img, x1, 0);
context.drawImage(img, x2, 0);


if(context === context2) {
document.body.replaceChild(canvas1, canvas2);
context = context1;
}
else {
document.body.replaceChild(canvas2, canvas1);
context = context2;
}

if(x1 === canvas1.width) {
x1 = -imageWidth;
}
else {
x1++;
}

if(x2 === canvas1.width) {
x2 = -imageWidth;
}
else {
x2++;
}
setTimeout(arguments.callee, 100);
}, 100);
};
img.src = 'images/scroll.gif';
};
</script>
</head>
<body>
<canvas id="canvas1" width="300" height="200"></canvas>
<canvas id="canvas2" width="300" height="200"></canvas>
</body>
</html>