J2me手機(jī)游戲編程初體驗(yàn)
發(fā)表時(shí)間:2024-01-18 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]出發(fā) 學(xué)習(xí)J2me已經(jīng)有一段時(shí)間了,按書(shū)上說(shuō)的例子也做了無(wú)數(shù),雖然基本理解了J2me的整體編程思想,但做游戲程序卻仍然感到毫無(wú)頭緒。 本想試著照扒游戲【魔塔】,反復(fù)考慮了很長(zhǎng)時(shí)間,感覺(jué)其中復(fù)雜度較高,而且部分細(xì)節(jié)如關(guān)卡的設(shè)置、與敵人對(duì)戰(zhàn)等程序也都沒(méi)有接觸過(guò),所以決定做一個(gè)簡(jiǎn)易的推箱子游戲,...
出發(fā)
學(xué)習(xí)J2me已經(jīng)有一段時(shí)間了,按書(shū)上說(shuō)的例子也做了無(wú)數(shù),雖然基本理解了J2me的整體編程思想,但做游戲程序卻仍然感到毫無(wú)頭緒。
本想試著照扒游戲【魔塔】,反復(fù)考慮了很長(zhǎng)時(shí)間,感覺(jué)其中復(fù)雜度較高,而且部分細(xì)節(jié)如關(guān)卡的設(shè)置、與敵人對(duì)戰(zhàn)等程序也都沒(méi)有接觸過(guò),所以決定做一個(gè)簡(jiǎn)易的推箱子游戲,有兩關(guān)即可。
雖說(shuō)是簡(jiǎn)單很多,但真正想要做起來(lái)的時(shí)候卻無(wú)從下手;想了好久,腦袋里仍然是亂糟糟的,反正也沒(méi)有思路,不如靜下來(lái),做個(gè)簡(jiǎn)單的設(shè)計(jì)吧。
設(shè)計(jì)
由于需求簡(jiǎn)易,就直接進(jìn)入設(shè)計(jì)吧。^_^
首先,一定要有個(gè)主應(yīng)用程序類,相信大家都應(yīng)改知道;其次,不可避免,一定要有畫(huà)布,為了把程序的畫(huà)面呈現(xiàn)出來(lái);其中,我覺(jué)得還是把地圖跟畫(huà)布分開(kāi),這樣對(duì)地圖管理比較容易,而且增加或修改地圖比較方便;然后一定要有主角對(duì)吧,總要找個(gè)推箱子的人;說(shuō)到箱子,也許箱子也需要管理吧。
制作圖片 我一向認(rèn)為我自己沒(méi)有什么審美觀點(diǎn),不過(guò)做程序總要些圖片,沒(méi)辦法,只有映著頭皮做吧,多虧前一陣學(xué)了些簡(jiǎn)單的PhotoShop處理,做起來(lái)也不是十分困難,只不過(guò)選擇的圖片稍微差了點(diǎn),對(duì)付著用吧。
開(kāi)工 所謂萬(wàn)事具備只欠東風(fēng),雖然我們的設(shè)計(jì)雖然簡(jiǎn)單,總可以對(duì)付著用吧^_^。
繪制背景 先拋開(kāi)箱子(BoxSprite)和推箱子的人(PlayerSprite)兩個(gè)類,把全部經(jīng)歷集中到繪制地圖上(其實(shí)不過(guò)是第一幅地圖)。
這其中需要先了解幾個(gè)類,GameCanvas 、LayerManager和TiledLayer等幾個(gè)類。我們這里主要用TiledLayer這種方法構(gòu)造背景。
GameCanvas 類:GameCanvas實(shí)際上就是屏幕上一個(gè)可繪制區(qū)域。但每個(gè)GameCanvas類都有一個(gè)獨(dú)立的buffer,從而不但減少了堆的使用率,也可以使用單獨(dú)的堆控制程序。
LayerManager 類:這個(gè)類用來(lái)管理圖像的各個(gè)層,它將按正確的位置和次序渲染所有在它控制下的土層。
TiledLayer 類:通過(guò)使用這個(gè)函數(shù)可以定義游戲背景的特定區(qū)域,并且可以重復(fù)利用它們生成一個(gè)完整的圖像。
具體參考相關(guān)資料。
主程序 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();
}
}