<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    J2ME小游戲介紹

    Posted on 2006-05-25 21:32 小李飛刀 閱讀(765) 評論(0)  編輯  收藏 所屬分類: 開發工具
    J2ME Game APIs的使用介紹
    --效率問題比較嚴重,拿出來請高手指正

    一個J2ME的2D游戲技術DEMO???????????????????? 源碼

    計劃了很久了,準備作為J2ME的Game APIs的例子貼出來,無奈一直不得空,直到最近才簡單地整理了一下,把它共享出來。

    嚴格地講,這個不能算作一個完整的游戲,沒有自己的創意,只是簡單地模仿了一個Flash的小游戲,當時是為了自己練習用的,Game Play也很簡單,但包含了J2ME的Game包中所有的東西,作為一個Demo來講,內容還是很充實的。

    在介紹之前,先簡單地提一下Gaming API中的幾個類,包括Sprite,TiledLayer,LayerManager,Media.Player等。
    Sprite:偶爾看到過有些人把它翻譯成精靈,我偷懶一下,就不翻譯了,這個類用來表達游戲中的一個活動的角色,包括玩家控制的Player角色和非玩家控制的角色(NPC)。
    TiledLayer:這個是用來表達背景的類,其實從繪圖的角度來看,Sprite和TiledLayer沒有本質差別,只是將要畫在屏幕上的一幅圖像而已,因此在Game包中它們都是Layer類的子類。并且都能夠從一幅圖像方便地構造。
    LayerManager:這個是用來管理所有圖像對象的類,通過把Sprite和TiledLayer加入其中,J2ME設備就知道如何來繪制它們了。
    GameCanvas:最后要提到的是畫布,這是所有可視對象最終要表演的舞臺。其實跟以前的Canvas沒有本質的不同,同樣是提供了一個Graphics接口來供把一些內容畫上去而已,但增加了對玩家輸入的處理,能夠通過按鍵狀態來直接讀入玩家按鍵操作,相對更加簡便了。
    還利用到了Media包中的Player和ToneControl來播放音樂,沒有音樂和聲音的游戲是不可能出現的,呵呵。

    先簡單地介紹一下這個游戲,玩家只能控制角色(一個端著網兜的小人)水平地移動,接住自然下落的小球就得分,積分到一定程度后,小球下落速度將加快,直到最高速為止;如果沒接到小球,也有相應的懲罰,最終游戲會Game Over。

    為了避免過于單調,玩家角色不是簡單地平移,而是利用了Sprite的簡單幀動畫來讓角色看上去有些動作。其實很方便的,只是在移動位置時更換一下圖像就行了,Sprite提供有幾個方法NextFrame(),PrevFrame()用來切換。
    聲音部分就更簡單了,只是重復地播放一段預先寫進去的音樂,來自Sun的WTK中的一個例子。
    不過既然提到了它,就還是先簡單地說一下吧,免得后面介紹其他部分時有些疑問。

    J2ME中的聲音部分非常簡單,當然效果也不太好,所需的基本元素只有如下幾個,一個內容部分的Byte系列;一個是播放器Player;還有一個是控制部分的ToneControl。代碼示例如下:

    ????????????? tonePlayer = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
    ????????????? tonePlayer.setLoopCount(-1);
    ????????????? tonePlayer.realize();
    ????????????? ToneControl tc = (ToneControl)tonePlayer.getControl("javax.microedition.media.control.ToneControl");
    ????????????? tc.setSequence(mySequence);

    當然還需要些初始化工作和異常處理,然后就可以通過tonePlayer.start()/close()方法來控制聲音的播放和停止了。

    具體請參見源碼中CanvasGetBall.java中的createTonePlayer()方法。

    鑼鼓響了半天,主角也該出場了。這個游戲里的主角只有一個接球小人,不過角色還有一個跟它演對手戲的NPC,就是那只從天而降的小球了。這兩個類都是Sprite的子類,小球因為有些自己的動作,同時實現了Runnable接口,能自主活動。不過也很簡單,NPC嘛,一般來說都是相對弱智些,不然也沒法玩了,誰的反應速度跟得上機器啊,再說了,NPC知道的信息也要多些:)。

    先來看看主角吧,BallPlayer類就是我們的主角,其實非常簡單,在所有的6個類中,除了記分用的Score外就數它最小了。提供一幅圖像把它實例化后,就只能通過左右移動來控制了,額外的幾個方法都是跟記分有關系的,先略過不提。
    先來看看它的構造方法:

    ? public BallPlayer(Image img, int fw, int fh) {
    ??? super(img, fw, fh);
    ??? this.step = fw / 2;
    ? }

    主要工作都由它的父類Sprite做了,給出一幅圖像,這個圖像是用PNG格式提供的,大家可能留意到不是一幅單一的圖像,而是有點象幀動畫中的幾個關鍵幀,不錯,的確如此,構造方法中的后兩個參數就是告訴Sprite如何分割這幅圖像的。這里整個Player共有6個關鍵幀,比較粗糙,呵呵,自己動手截屏做的:)

    Field step是用來控制主角的移動步伐的,為了快一點,取了它身寬的一半。

    接下來我們看看如何移動它,就是通過這樣兩個方法來左移和右移。

    ? public void left() {
    ??? prevFrame();
    ??? if( (getX() - step) >= -12 ) {
    ????? move( -1 * step, 0);
    ??? }
    ? }
    ? public void right () {
    ??? nextFrame();
    ??? if((getX() + step) < canvas.getWidth()) {
    ????? move(step, 0);
    ??? }
    ? }

    留意一下,這里只管相對位移,主角的開始位置通過setPosition來設定,在運動過程中最好就不要直接設置位置了,增大計算量,要不就看起來動作不自然了。

    接下來簡單說一下配角--球。球的構造跟主角類似,只是為了節省構造銷毀對象帶來的開銷,這個對象是一直存在的,也就是讓它掉下去了又自己起來,并根據記分來確定下落速度,簡單地用線程實現的,沒怎么仔細設計,大家看看代碼就清楚了。

    再來看看CanvasGetBall這個類,它從GameCanvas繼承,并實現了CommandListener和Runnable兩個接口,是整個游戲中最復雜的一個類了,主要工作有如下幾個部分,實例化主角,配角對象,還有背景對象,音樂等,并在適當的時候畫出這些對象,在頂部畫出些狀態信息,并根據玩家操作開始和暫停游戲,并顯示相應畫面。并通過進行碰撞檢測來判定玩家是否接到了小球。
    檢測方法如下:
    ? private boolean notMiss( ) {
    //??? return player.collidesWith(ball,false);
    ??? int ballCX = ball.getX() + ball.getWidth()/2;
    ??? int ballCY = ball.getY() + ball.getHeight()/2;
    ??? int playerCX = player.getX() + player.getWidth()/2;
    ??? int playerCY = player.getY() + player.getHeight()/2;
    ??? return ((Math.abs(playerCX - ballCX)< ball.getWidth()/2) &&
    ??????????? (Math.abs(ballCY - playerCY) < 5));
    ? }
    被注釋掉的一行是直接用Sprite的碰撞檢測,下面的部分是自己計算兩幅圖像有沒有重疊,效果差不多。其中collidesWith()的第二個參數是告訴內部方法是否要用像素級別的檢測,通常答案是千萬不要,這很慢的,而且沒有必要這么精確。

    為了說明整個游戲的控制邏輯,我們先來看看MIDletGetBall這個類,跟通常的MIDlet略有不同,因為我把主線程放在了CanvasGetBall中,MIDletGetBall只是簡單地控制主線程就行了。

    ? public void startMainThread() {
    ??? Display.getDisplay(this).setCurrent(displayable);
    ??? if(mainThread != null) {
    ????? mainThread = null;
    ????? Runtime.getRuntime().gc();
    ??? }
    ??? mainThread = new Thread(displayable);
    ??? mainThread.start();
    ? }
    其中第一行就是設置當前顯示頁面;也就是顯示CanvasGetBall。

    回到CanvasGetBall,整個游戲分幾個階段,相應有不同的畫面和命令接口,詳細說明如下:
    1. 等待開始,對應在方法ready():
    ???? public void ready() {
    ??????? cover.setTitle(TIPS[2]);
    ??????? cover.addCommand(playCommand);
    ??????? Display.getDisplay(MIDletGetBall.instance).setCurrent(cover);
    ???? }
    ??? 為了繪制方便,這里單獨用了個GameCanvas來繪制提示信息和響應命令,并根據玩家操作在CanvasCover和CanvasGetBall兩個畫面之間來回切換。

    2. 游戲畫面,包括啟動和結束兩個方法:
    ?public void start() {
    ??? if(!playing) {
    ????? strTip = TIPS[0];
    ????? playing = true;
    ????? MIDletGetBall.instance.startMainThread();
    ????? removeCommand(playCommand);
    ????? removeCommand(resumeCommand);
    ????? addCommand(pauseCommand);
    ????? ball.start();
    ????? try {
    ??????? if(tonePlayer != null) {
    ????????? tonePlayer.start();
    ??????? }
    ????? }
    ????? catch (MediaException ex) {
    ??????? tonePlayer.close();
    ??????? tonePlayer = null;
    ????? }
    ??? }
    ? }
    ? public void stop () {
    ??? if(playing) {
    ????? ball.stop();
    ????? strTip = TIPS[1];
    ????? try {
    ??????? Thread.sleep(300);
    ????? }
    ????? catch (InterruptedException ex) {
    ????? }
    ????? playing = false;
    ????? removeCommand(pauseCommand);
    ????? addCommand(resumeCommand);
    ????? try {
    ??????? tonePlayer.stop();
    ????? }
    ????? catch (MediaException ex1) {
    ??????? tonePlayer.close();
    ??????? tonePlayer = null;
    ????? }
    ??? }
    ? }

    ?并對應設置相應的命令來讓玩家能夠繼續下去,構成一個簡單的封閉控制環路。

    3.游戲結束,對應方法gameover()
    ? public void gameover() {
    ??? this.stop();
    ??? cover.setTitle(TIPS[3]);
    ??? cover.removeCommand(playCommand);
    ??? cover.addCommand(restartCommand);
    ??? Display.getDisplay(MIDletGetBall.instance).setCurrent(cover);
    ? }


    說到這里,基本上也就把它講完了,具體內容請詳細研究源碼,其實沒必要看太多書,深入地研究一個問題并根據自己的理解來改進或者是修正它,實踐才是最好的老師,希望大家能夠有所收獲。

    總結一下,這個游戲存在的問題有如下幾個:
    1. 沒有好的Game Play,畫面很差;
    2. 可玩性不強,控制比較單調;
    3. 游戲聲音過于單調;
    4. 運行速度有些慢。

    但作為一個技術Demo,它涵蓋了Game包中的所有內容,并提供了一個利用線程方式實現簡單游戲的方法,很簡單,但不適合真實的游戲,比較費時。
    背景處理很差,可以通過一個Map來分割組合處理背景小片,能讓游戲場景變得生動些,可以實現類似于卷軸游戲的效果,自己試試吧!

    附:源代碼和工程,在JBuilderX下編譯,同時需要WTK2.0或以上版本。好久沒有用Jbuilder了,買不起正版:),現在主要開發工具是Eclipse和EclipseME,感覺非常爽,免費的也有好貨。

    posts - 44, comments - 43, trackbacks - 0, articles - 5

    Copyright © 小李飛刀

    涉足江湖,廣交朋友
    尋找有共同興趣愛好者一起開創掌上移動應用!


    歡迎光臨!您是第 hit counter 位訪客。
    主站蜘蛛池模板: xxxx日本在线播放免费不卡| 免费a级毛片无码a∨性按摩| a级毛片免费高清视频| 67194在线午夜亚洲| 亚洲成a人片在线观看无码| 日本一区免费电影| 国产免费的野战视频| 中国一级毛片视频免费看| 无人视频免费观看免费视频 | 韩日电影在线播放免费版| 国产精品亚洲一区二区无码| 亚洲mv国产精品mv日本mv| 亚洲2022国产成人精品无码区| 久久亚洲精品无码观看不卡| 国产免费私拍一区二区三区| 蜜桃视频在线观看免费网址入口| 91在线手机精品免费观看| 久久青草免费91线频观看不卡| 久久国产精品免费一区| 一个人免费观看日本www视频| 无套内射无矿码免费看黄| 特级毛片免费观看视频| 日韩亚洲综合精品国产| 国产成人精品久久亚洲高清不卡 | 国产真实伦在线视频免费观看| 成人特黄a级毛片免费视频| 久草免费在线观看视频| 亚洲精品在线免费观看视频| 一级成人a毛片免费播放| 免费A级毛片在线播放| 蜜桃成人无码区免费视频网站| 污污网站免费观看| 特级无码毛片免费视频尤物| 日本高清免费观看| 永久黄色免费网站| 日韩免费精品视频| 搡女人真爽免费视频大全| 天天操夜夜操免费视频| 国产99视频精品免费视频7| 亚洲国产成人精品无码久久久久久综合| 国产成人精品123区免费视频|