オープンアプリ・ゲームコンテスト
コンテスト概要 応募方法 応募作で遊ぼう アプリ開発講座 Special Special

アプリ開発講座

講座スケジュール
第1回 オープンアプリ(Java)とJava実行環境
line
第2回 はじめてのオープンアプリ(Java)の作成
line
第3回 イメージの描画
line
第4回 キー入力の処理
line
第5回 オープンアプリ(Java)への移植
line
第6回 ゲームの作成
line
第7回 端末へのデータ保存
line
第8回 サウンドの再生
line
第9回 バイブレーションとブラウザ起動
line 最終回 HTTPによる通信
line

開発講座TOPへ



講師プロフィール
株式会社ユビキタスエンターテインメント 布留川英一

1999年のJavaMEの仕様公開を期に「JAVA PRESS(技術評論社)」にてライターとしての活動をはじめ、2000年の503iシリーズの発売を期にドワンゴへ移り、携帯アプリの研究開発を行う。2005年に独立し、ユビキタスエンターテインメントにて次世代コンテンツを作成中。
【著書】
MIDP 2.0 携帯Javaアプリ開発ハンドブック
iアプリゲーム開発テキストブック
ActionScript 3.0 ゲームプログラミングブック
他6冊

 

 

第5回 
オープンアプリ(Java)への移植


第5回の今回は、NTTドコモのiアプリ、ソフトバンクのS!アプリ、WillcomのJavaアプリをオープンアプリ(Java)に移植する際のポイントについて解説します。

APIの違い

コンフィギュレーションは全キャリア共通で「CLDC」、プロファイルもNTTドコモがDoJaを採用している以外は、MIDPが採用されています。つまり、仕様的にはMIDPの基本APIのみを使っているアプリであれば、ソフトバンク端末やWillcom端末向けのアプリをそのままauのオープンアプリプレーヤー対応端末でも実行することができます。

しかし、オープンアプリ(Java)にはオプションAPIはありません。WillcomのJavaアプリもオプションAPIがほとんどないため移植が容易ですが、S!アプリには「JSCL/VSCL/MEXA」といった便利な拡張APIが多数用意されているので、利用しているアプリはそれを基本APIに置き換える作業を行い、できない場合はどのような仕様変更を行うかを考える必要があります。

コンフィギュレーション プロファイル オプションAPI
オープンアプリ(Java) CLDC MIDP なし
iアプリ CLDC DoJa -
S!アプリ CLDC MIDP JSCL
VSCL
MEXA
Javaアプリ(Willcom) CLDC MIDP SDバインド

実行ファイルサイズ制限

実行ファイルのサイズ制限(JARファイルのサイズ+データ保存領域のサイズ)はキャリアごとに異なります。オープンアプリ(Java)は一番小さく300KBなので注意して下さい。

実行ファイルサイズ+データ保存領域サイズ
オープンアプリ(Java) 300KB+32KB
iアプリ 合計で1MB(903)
100KB+400KB(902以前)
30KB+200KB(70X)
S!アプリ 合計で1MB(3GC)
合計で256KB(P5型,P6型)
Javaアプリ(Willcom) 1MB+512KB

画面・フォントのサイズ制限

オープンアプリ(Java)には携帯アプリでは標準的な、12/16/20ピクセルが揃っていまが、iアプリで標準的な24ドットが使えないので多少調整は必要です。

画面サイズ フォントサイズ
オープンアプリ(Java) 240x268 12,16,20ドット
iアプリ 240x240程度(まれにVGA) 12,16(まれに20),24ドット
S!アプリ 240x240程度(まれにVGA) 12,20ドット
Javaアプリ(Willcom) 240x240程度(まれにVGA) 12,16,20ドット(まれに12のみ)

リソースの制限

画像リソースをiアプリから移植するには、GIFをPNGに変換する必要があります。サウンドリソースをiアプリとS!アプリから移植するには、MLDとSMAF・SMAF/PhraseをMIDI・WAVEに変換する必要があります。また、サウンドの同時再生可能数はMIDIが4音、WAVEが4音です。

画像 サウンド
オープンアプリ(Java) PNG,JPEG MIDI,WAVE,Tone Sequence
iアプリ GIF,JPEG MLD
S!アプリ PNG,JPEG SMAF,SMAF/Phrase
Javaアプリ(Willcom) PNG,JPEG MIDI

通信量の制限

オープンアプリ(Java)には、「1接続32KB」「1日3MB」という厳しい通信制限があります。そのためネットリソースを大量に活用するようなツール(WEBブラウザアプリなど)の作成には向きません。

通信量の制限
オープンアプリ(Java) 1接続32KB
1日3MB。通信規制は午後1時にリセット
iアプリ 1接続150KB
1日の通信量制限はない
S!アプリ 1日の通信量制限はない
Javaアプリ(Willcom) 1日の通信量制限はない

iアプリからオープンアプリ(Java)への移植

◎アプリ本体となる親クラス
アプリ本体となる親クラスはiアプリでは「com.nttdocomo.ui.IApplication」クラス、オープンアプリ(Java)では「javax.microedition.midlet.MIDlet」クラスです。

iアプリ オープンアプリ(Java)
アプリの親クラス com.nttdocomo.ui.IApplication javax.microedition.midlet.MIDlet
アプリの開始 start() コンストラクタ,startApp()
アプリの一時停止 なし pauseApp()
アプリの再開 resume() startApp()
アプリの終了 なし destroyApp(boolean)

iアプリではこれらメソッド内でメインループを作っても大丈夫ですが、オープンアプリ(Java)では不具合が発生する端末もあるので、処理し続けたい時には、新たにスレッドを作った方が良いです。

[iアプリ]本体の例
import com.nttdocomo.ui.*;

//本体
public class A extends IApplication {
    static A a;
    static B b;

    //アプリの開始
    public void start() {
        a=this;
        b=new B();
        Display.setCurrent(b);
        b.run();
    }

    //アプリの再開
    public void resume() {
    }
}

[オープンアプリ(Java)]本体の例
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

//本体
public class A extends MIDlet {
    static A a;
    static B b;

    //アプリの開始
    public A() {
        a=this;
        b=new B();
        Display.getDisplay(this).setCurrent(b);
        (new Thread(b)).start();
    }

    //アプリの復帰
    public void startApp() {
    }

    //アプリの一時停止
    public void pauseApp() {
    }

    //アプリの終了
    public void destroyApp(boolean uncond) {
    }
}



◎キーイベント
キャンバスとなるクラスの親クラスはiアプリでは「com.nttdocomo.ui.Canvas」クラス、オープンアプリ(Java)では「javax.microedition.ui.Canvas」クラスです。iアプリにはキープレスイベントとキーリリースイベントを取得するメソッドが、オープンアプリ(Java)にはそれに加えてキーリピートイベントを取得するメソッドがあります。

iアプリ オープンアプリ(Java)
キャンバスの親クラス com.nttdocomo.ui.Canvas javax.microedition.ui.Canvas
キープレス processEvent(int type,int param) keyPressed()
キーリリース processEvent(int type,int param) keyReleased()
キーリピート なし keyRepeated()
キー状態の取得 getKeypadState() keyPressed(),keyReleased()
ソフトラベル指定 setSoftLabel(int key,String label) addCommand(Command)
ソフトキープレス processEvent(int type,int param) commandAction()

次のようなキーイベント用のラッパーを作ると便利です。

[オープンアプリ(Java)]キーイベント用のラッパー
    private int keypadState;//キー状態
    private String[] softLabel=new String[2];//ソフトラベル
    private javax.microedition.lcdui.Command[] softKey=//ソフトキー
        new javax.microedition.lcdui.Command[2];

    //ソフトラベル
    protected void setSoftLabel(int key,String label) {
        //初期化
        if (softKey[0]==null) {
            softLabel[0]="";
            softLabel[1]="";
            softKey[0]=new javax.microedition.lcdui.Command(
                "",javax.microedition.lcdui.Command.SCREEN,0);
            softKey[1]=new javax.microedition.lcdui.Command(
                "",javax.microedition.lcdui.Command.SCREEN,1);
            addCommand(softKey[0]);
            addCommand(softKey[1]);
        }
        //ソフトキー1・2変更
        if (key==Canvas.SOFT_KEY_1) {
            if (softLabel[0].equals(label)) return;
            removeCommand(softKey[1]);
            removeCommand(softKey[0]);
            softLabel[0]=label;
            softKey[0]=new javax.microedition.lcdui.Command(
                label,javax.microedition.lcdui.Command.SCREEN,0);
            addCommand(softKey[0]);
            addCommand(softKey[1]);
        }
        //ソフトキー2変更
        else {
            if (softLabel[1].equals(label)) return;
            removeCommand(softKey[1]);
            softLabel[1]=label;
            softKey[1]=new javax.microedition.lcdui.Command(
                label,javax.microedition.lcdui.Command.SCREEN,1);
            addCommand(softKey[1]);
        }
    }

    //キープレスイベント
    public void keyPressed(int keyCode) {
        int key=getKey(keyCode);
        keypadState|=(1<<key);
        canvas.processEvent(
            Display.KEY_PRESSED_EVENT,key);
    }

    //キーリリースイベント
    public void keyReleased(int keyCode) {
        int key=getKey(keyCode);
        keypadState^=(1<<key);
        canvas.processEvent(
            Display.KEY_RELEASED_EVENT,key);
    }

    //キーの取得
    private int getKey(int keyCode) {
        switch(keyCode) {
        case 0:return Display.KEY_CLEAR;
        case KEY_NUM0:return Display.KEY_0;
        case KEY_NUM1:return Display.KEY_1;
        case KEY_NUM2:return Display.KEY_2;
        case KEY_NUM3:return Display.KEY_3;
        case KEY_NUM4:return Display.KEY_4;
        case KEY_NUM5:return Display.KEY_5;
        case KEY_NUM6:return Display.KEY_6;
        case KEY_NUM7:return Display.KEY_7;
        case KEY_NUM8:return Display.KEY_8;
        case KEY_NUM9:return Display.KEY_9;
        case KEY_STAR:return Display.KEY_ASTERISK;
        case KEY_POUND:return Display.KEY_POUND;
        default:
            switch(getGameAction(keyCode)) {
            case UP:return Display.KEY_UP;
            case DOWN:return Display.KEY_DOWN;
            case LEFT:return Display.KEY_LEFT;
            case RIGHT:return Display.KEY_RIGHT;
            case FIRE:return Display.KEY_SELECT;
            case GAME_A:return Display.KEY_GAME_A;
            case GAME_B:return Display.KEY_GAME_B;
            case GAME_C:return Display.KEY_GAME_C;
            case GAME_D:return Display.KEY_GAME_D;
            }
        }
        return keyCode;
    }

    //コマンドイベント
    public void commandAction(javax.microedition.lcdui.Command c,
        javax.microedition.lcdui.Displayable s) {
        if (c==softKey[0]) {
            canvas.processEvent(Display.KEY_PRESSED_EVENT,
Display.KEY_SOFT1); } else { canvas.processEvent(Display.KEY_PRESSED_EVENT,
Display.KEY_SOFT2); } } //キー状態の取得 protected int getKeypadState() { return keypadState; }



◎グラフィックス
グラフィックスはプログラムでかなりの割合を占める部分です。

iアプリ オープンアプリ(Java)
Graphicsクラス com.nttdocomo.ui.Graphics javax.microedition.ui.Graphics
色の指定 |g.setColor
(g.getColorOfRGB(255,255,255));
g.setColor
(g.getColorOfName(g.WHITE));
g.setColor(255,255,255);
文字列の描画 g.drawString("test",0,12); g.drawString
("test",0,12,g.LEFT|g.BASELINE);
イメージの描画 g.drawImage(image,0,0); g.drawImage
(image,0,0,g.LEFT|g.TOP);
ロック g.lock(); なし
アンロック g.unlock(true); flushGraphics();

グラフィックス用のラッパーを作ることによって、移植作業を軽減させることができます。

[オープンアプリ(Java)]グラフィックス用のラッパー
import javax.microedition.lcdui.*;

//グラフィックス用のラッパー
class G {
    //色定数
    static int AQUA   =(  0<<16)+(255<<8)+255;
    static int BLACK  =(  0<<16)+(  0<<8)+  0;
    static int BLUE   =(  0<<16)+(  0<<8)+255;
    static int FUCHSIA=(255<<16)+(  0<<8)+255;
    static int GRAY   =(128<<16)+(128<<8)+128;
    static int GREEN  =(  0<<16)+(128<<8)+  0;
    static int LIME   =(  0<<16)+(255<<8)+  0;
    static int MAROON =(128<<16)+(  0<<8)+  0;
    static int NAVY   =(  0<<16)+(  0<<8)+128;
    static int OLIVE  =(128<<16)+(128<<8)+  0;
    static int PURPLE =(128<<16)+(  0<<8)+128;
    static int RED    =(255<<16)+(  0<<8)+  0;
    static int SILVER =(192<<16)+(192<<8)+192;
    static int TEAL   =(  0<<16)+(128<<8)+128;
    static int WHITE  =(255<<16)+(255<<8)+255;
    static int YELLOW =(255<<16)+(255<<8)+  0;

    //変数
    Graphics g;//グラフィクス

    //コンストラクタ
    G(Graphics g) {
        this.g=g;
    }

    //文字列の描画
    void drawString(String str,int x, int y) {
        g.drawString(str,x,y+2,Graphics.LEFT|Graphics.BOTTOM);
    }

    //イメージの描画
    void drawImage(Image image,int x,int y) {
        g.drawImage(image,x,y,
            Graphics.LEFT|Graphics.TOP);
    }

    //ラインの描画
    void drawLine(int x1,int y1,int x2,int y2) {
        g.drawLine(x1,y1,x2,y2);
    }

    //矩形の描画
    void drawRect(int x,int y,int width,int height) {
        g.drawRect(x,y,width,height);
    }

    //矩形の塗り潰し
    void fillRect(int x,int y,int width,int height) {
        g.fillRect(x,y,width,height);
    }

    //円弧の塗り潰し
    void fillArc(int x,int y,int width,int height,int startAngle,
int arcAngle) { g.fillArc(x,y,width,height,startAngle,arcAngle); } //フォントの設定 void setFont(Font font) { g.setFont(font); } //色の取得 static int getColorOfName(int name) { return name; } //色の取得 static int getColorOfRGB(int red,int green,int blue) { return (red<<16)+(green<<8)+blue; } //色の設定 void setColor(int color) { g.setColor(color); } //ロック void lock() { } //アンロック void unlock(boolean forced) { A.b.flushGraphics(); } }

おわりに

今回はこれでおしまいです。次回は「ゲームの作成」について解説します。

ページ先頭へ


  Copyright(C) Spicysoft Corporation All rights reserved.
 
アプリゲット