出發
學習J2me已經有一段時間了,按書上說的例子也做了無數,雖然基本理解了J2me的整體編程思想,但做遊戲程式卻仍然感到毫無頭緒。
本想試著照扒遊戲【魔塔】,反覆考慮了很長時間,感覺其中複雜度較高,而且部分細節如關卡的設定、與敵人對戰等程式也都沒有接觸過,所以決定做一個簡易的推箱子遊戲,有兩關即可。
雖說是簡單很多,但真正想要做起來的時候卻無從下手;想了好久,腦袋裡仍然是亂糟糟的,反正也沒有思路,不如靜下來,做個簡單的設計吧。
設計
由於需求簡易,就直接進入設計吧。^_^
首先,一定要有個主應用程式類,相信大家都應改知道;其次,不可避免,一定要有畫布,為了把程式的畫面呈現出來;其中,我覺得還是把地圖跟畫布分開,這樣對地圖管理比較容易,而且增加或修改地圖比較方便;然後一定要有主角對吧,總要找個推箱子的人;說到箱子,也許箱子也需要管理吧。
製作圖片
我一向認為我自己沒有什麼審美觀點,不過做程式總要些圖片,沒辦法,只有映著頭皮做吧,多虧前一陣學了些簡單的PhotoShop處理,做起來也不是十分困難,只不過選擇的圖片稍微差了點,對付著用吧。
開工
所謂萬事具備只欠東風,雖然我們的設計雖然簡單,總可以對付著用吧^_^。
繪製背景
先拋開箱子(BoxSprite)和推箱子的人(PlayerSprite)兩個類,把全部經曆集中到繪製地圖上(其實不過是第一幅地圖)。
這其中需要先瞭解幾個類,GameCanvas 、LayerManager和TiledLayer等幾個類。我們這裡主要用TiledLayer這種方法構造背景。
GameCanvas 類:GameCanvas實際上就是螢幕上一個可繪製地區。但每個GameCanvas類都有一個獨立的buffer,從而不但減少了堆的使用率,也可以使用單獨的堆控製程序。
LayerManager 類:這個類用來管理映像的各個層,它將按正確的位置和次序渲染所有在它控制下的土層。
TiledLayer 類:通過使用這個函數可以定義遊戲背景的特定地區,並且可以重複利用它們產生一個完整的映像。
具體參考相關資料。
主程式
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
public class myBox extends MIDlet implements CommandListener
{
private BoxCanvas boxCanvas;
protected Display display;
public void startApp()
{
display = Display.getDisplay(this);
try{
boxCanvas = new BoxCanvas(this);
boxCanvas.start();
Command exitCommand = new Command(/"Exit/", Command.EXIT, 1);
boxCanvas.addCommand(exitCommand);
boxCanvas.setCommandListener(this);
}catch(Exception e){
}
display.setCurrent(boxCanvas);
}
public Display getDisplay()
{
return display;
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
System.gc();
notifyDestroyed();
}
public void commandAction(Command c, Displayable s) {
if (c.getCommandType() == Command.EXIT) {
destroyApp(true);
notifyDestroyed();
}
}
}
BoxCanvas類
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import java.util.*;
public class BoxCanvas extends GameCanvas implements Runnable
{
private myBox midlet;
private BoxMaps boxMaps;
private Thread gameThread = null;
private LayerManager layerManager;
private TiledLayer tl_ground;
private static final int MILLIS_PER_TICK = 50;
public BoxCanvas(myBox midlet) throws Exception
{
super(true);
this.midlet = midlet;
boxMaps = new BoxMaps();
tl_ground = boxMaps.getTiled();
layerManager = new LayerManager();
layerManager.append(tl_ground);
}
public void start()
{
gameThread = new Thread(this);
gameThread.start();
}
public void stop()
{
gameThread = null;
}
public void run()
{
Graphics g = getGraphics();
Thread currentThread = Thread.currentThread();
try{
while (currentThread == gameThread) {
long startTime = System.currentTimeMillis();
if (isShown()) {
//tick();
//input();
render(g);
}
long timeTake = System.currentTimeMillis() - startTime;
if (timeTake < MILLIS_PER_TICK) {
synchronized (this) {
wait(MILLIS_PER_TICK - timeTake);
}
} else {
currentThread.yield();
}
}
}catch (InterruptedException ex) {
// won't be thrown
}
}
private void render(Graphics g) {
//g.setColor(0xF8DDBD);
int w = getWidth();
int h = getHeight();
int x = (w - 192) / 2;
int y = (h - 192) / 2;
g.setColor(boxMaps.getGroundColor());
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(0x0000ff);
tl_ground = boxMaps.getTiled();
layerManager.paint(g,x,y);
flushGraphics();
}
}
BoxMaps類
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
public class BoxMaps
{
private static final int[][] map1 = {
{0,0,0,0,1,1,1,0,0,0,0,0},
{0,0,0,0,4,0,2,0,0,0,0,0},
{0,0,0,0,4,0,2,0,0,0,0,0},
{0,0,0,0,4,0,1,1,1,1,1,2},
{0,0,0,0,4,0,0,0,0,0,0,2},
{4,1,1,1,1,0,0,0,3,3,3,2},
{4,0,0,0,0,0,0,0,2,0,0,0},
{4,3,3,3,3,3,3,0,2,0,0,0},
{0,0,0,0,0,0,4,0,2,0,0,0},
{0,0,0,0,0,0,4,0,2,0,0,0},
{0,0,0,0,0,0,4,0,2,0,0,0},
{0,0,0,0,0,0,3,3,3,0,0,0}
};
private static final int TILE_WIDTH = 16;
private static final int TILE_HEIGHT = 16;
private int[][] currentMap;
private TiledLayer tl_BoxGround;
private int groundColor;
public BoxMaps() throws Exception{
setMap(1);
}
public void setMap(int level) throws Exception {
Image tileImages = Image.createImage(/"/wall.png/");
switch(level)
{
case 1:
currentMap = map1;
groundColor = 0xF8DDBE;
break;
default:
groundColor = 0xF8DDBE;
break;
}
tl_BoxGround = new TiledLayer(12,12,tileImages,TILE_WIDTH,TILE_HEIGHT);
for (int row=0; row<12; row++) {
for (int col=0; col<12; col++) {
tl_BoxGround.setCell(col,row,currentMap[row][col]);
}
}
}
public TiledLayer getTiled() {
return tl_BoxGround;
}
public int getGroundColor() {
return groundColor;
}
}
運行一下,看看效果,哈哈,效果出來了,怎麼樣?比較簡單吧