▼MIDP2.0メモ▼
iアプリをS!アプリ・オープンアプリに移植する


iアプリをS!アプリ・オープンアプリに移植する。



画像の準備
iアプリはgif、S!アプリ・オープンアプリはpngを用意。

キツネ0
-0.png
-24x24


キツネ1
-1.png
-24x24



-2.png
-24x24


ゲームオーバー
-3.png
-82x14


iアプリのソースコード


プログラム
A.java
import com.nttdocomo.ui.*;

//横スクロールアクションゲーム(本体)
public class A extends IApplication {

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


B.java
import com.nttdocomo.ui.*;
import java.util.*;

//横スクロールアクションゲーム(キャンバス)
public class B extends Canvas {
    //シーン定数
    final static int S_TITLE   =0;//タイトル
    final static int S_PLAY    =1;//プレイ
    final static int S_GAMEOVER=2;//ゲームオーバー

    //変数
    static int keyEvent;//キーイベント

    //メインループ
    void exe() {
        int i,len;
        try {
            //システム
            int      scene    =S_TITLE;      //シーン
            int      next     =S_TITLE;      //次のシーン
            int      score    =0;            //スコア
            long     sleepTime=0L;           //スリープ時間
            Graphics g        =getGraphics();//グラフィックス
            Random   rand     =new Random(); //乱数

            //フォント
            Font font=Font.getFont(Font.SIZE_SMALL);
            g.setFont(font);

            //イメージの読み込み
            Image[] image=new Image[4];
            for (i=0;i<4;i++) {
                MediaImage m=MediaManager.getImage("resource:///"+i+".gif");
                m.use();
                image[i]=m.getImage();
            }

            //キツネ
            int     foxY    =0;    //Y座標
            int     jumpPow =0;    //ジャンプ力
            boolean jumpAble=false;//ジャンプ可

            //マップ
            int   mapX=0;          //X座標
            int[] mapH=new int[16];//高さ
            len=mapH.length;

            //ソフトラベル
            setSoftLabel(SOFT_KEY_1,"スタート");

            //メインループ
            while (true) {
                //シーンの初期化
                if (next>=0) {
                    //タイトル・プレイの初期化
                    if (next==S_TITLE || next==S_PLAY) {
                        score   =0;
                        foxY    =240-72;
                        jumpPow =0;
                        jumpAble=true;
                        mapX    =0;
                        for (i=0;i<len;i++) mapH[i]=3;
                    }
                    //共通の初期化
                    scene   =next;
                    next    =-1;
                    keyEvent=-999;
                }
                g.lock();

                //背景の描画
                g.setColor(g.getColorOfRGB(170,200,255));
                g.fillRect(0,0,240,240);
                for (i=0;i<32;i++) {
                    g.setColor(g.getColorOfRGB(106+i*2,136+i*2,255));
                    g.fillRect(0,i*2,240,2);
                }

                //地面の描画
                for (i=0;i<len;i++) {
                    g.drawImage(image[2],mapX+i*24,240-mapH[i]*24);
                }

                //キツネの描画
                i=(jumpAble)?score%2:1;
                g.drawImage(image[i],36,foxY-24);

                //スコアの描画
                g.setColor(g.getColorOfName(g.WHITE));
                g.drawString(""+score,10,10+font.getAscent());

                //プレイ時の処理
                if (scene==S_PLAY) {
                    //スコア加算
                    score++;

                    //衝突判定
                    if (foxY>240-mapH[2]*24) {
                        next=S_GAMEOVER;
                        jumpAble =false;
                    }
                    //上昇
                    else if (jumpPow>=0) {
                        foxY-=jumpPow*2;
                        jumpPow--;
                    }
                    //下降
                    else {
                        foxY+=6;
                        jumpAble=false;
                        if (mapH[2]!=0 &&
                            foxY>240-mapH[2]*24) {
                            foxY=240-mapH[2]*24;
                            jumpAble=true;
                        }
                    }
                    //横スクロール
                    mapX-=4;
                    if (mapX==-24) {
                        mapX=0;
                        //地面の高さを左にシフト
                        System.arraycopy(mapH,1,mapH,0,len-1);

                        //地面の高さを指定
                        i=(rand.nextInt()>>>1)%5;
                        if (mapH[len-2]==0) { //"len-2"が穴の時"len-1"は"len-3"と同じ高さ
                            mapH[len-1]=mapH[len-3];
                        } else if (i==0) {//5分の1の確立で穴
                            mapH[len-1]=0;
                        } else if (i==1) {//5分の1の確立で1高く
                            mapH[len-1]=mapH[len-2]+1;
                            if (mapH[len-1]>4) mapH[len-1]=4;
                        } else if (i==2) {//5分の1の確立で1低く
                            mapH[len-1]=mapH[len-2]-1;
                            if (mapH[len-1]<1) mapH[len-1]=1;
                        }
                    }

                    //ジャンプ処理
                    i=getKeypadState();
                    if (jumpAble && ((1<<Display.KEY_SELECT)&i)!=0) {
                        jumpAble=false;
                        jumpPow =9;
                    } else if (!jumpAble && ((1<<Display.KEY_SELECT)&i)==0) {
                        jumpPow=-10;
                    }
                }

                //ゲームオーバー時の処理
                if (scene==S_GAMEOVER) {
                    if (foxY<240+33) foxY+=12;
                    g.drawImage(image[3],(240-82)/2,60);
                }
                g.unlock(true);

                //キーイベント
                if (keyEvent==Display.KEY_SOFT1) next=S_PLAY;
                keyEvent=-999;

                //スリープ
                sleepTime=sleepTime+100-System.currentTimeMillis();
                if (sleepTime<0)   sleepTime= 10;
                if (sleepTime>100) sleepTime=100;
                Thread.sleep(sleepTime);
                sleepTime=System.currentTimeMillis();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //キーイベントの処理
    public void processEvent(int type,int param) {
        if (type==Display.KEY_PRESSED_EVENT) keyEvent=param;
    }

    //描画
    public void paint(Graphics g) {}
}


S!アプリ・オープンアプリのソースコード


プログラム
A.java
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

//横スクロールアクションゲーム(本体)
public class A extends MIDlet 
    implements Runnable {
    static A a;//本体
    static B b;//キャンバス

    //コンストラクタ
    public A() {
        (new Thread(this)).start();
    }

    //処理
    public void run() {
        a=this;
        b=new B();
        Display.getDisplay(this).setCurrent(b);
        b.exe();
    }

    //アプリの開始
    public void start() {
    }

    //アプリの開始
    public void startApp() {
    }

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

    //アプリの終了
    public void destroyApp(boolean flag) {
    }
    
    //アプリの終了
    public void terminate() {
        destroyApp(false);
        notifyDestroyed();
    }

    //引数の取得
    public String[] getArgs() {
        return new String[]{};
    }
    
    //ソースURL
    public String getSourceURL() {
        return "";
    }
}


B.java
import javax.microedition.lcdui.*;
import java.util.*;

//横スクロールアクションゲーム(キャンバス)
public class B extends ICanvas {
    //シーン定数
    final static int S_TITLE   =0;//タイトル
    final static int S_PLAY    =1;//プレイ
    final static int S_GAMEOVER=2;//ゲームオーバー

    //変数
    static int keyEvent;//キーイベント

    //メインループ
    void exe() {
        int i,len;
        try {
            //システム
            int       scene    =S_TITLE;      //シーン
            int       next     =S_TITLE;      //次のシーン
            int       score    =0;            //スコア
            long      sleepTime=0L;           //スリープ時間
            IGraphics g        =getGraphics();//グラフィックス
            Random    rand     =new Random(); //乱数

            //フォント
            IFont font=IFont.getFont(IFont.SIZE_SMALL);
            g.setFont(font);

            //イメージの読み込み
            Image[] image=new Image[4];
            for (i=0;i<4;i++) {
                image[i]=Image.createImage("/"+i+".png");
            }

            //キツネ
            int     foxY    =0;    //Y座標
            int     jumpPow =0;    //ジャンプ力
            boolean jumpAble=false;//ジャンプ可

            //マップ
            int   mapX=0;          //X座標
            int[] mapH=new int[16];//高さ
            len=mapH.length;

            //ソフトラベル
            setSoftLabel(SOFT_KEY_1,"スタート");

            //メインループ
            while (true) {
                //シーンの初期化
                if (next>=0) {
                    //タイトル・プレイの初期化
                    if (next==S_TITLE || next==S_PLAY) {
                        score   =0;
                        foxY    =240-72;
                        jumpPow =0;
                        jumpAble=true;
                        mapX    =0;
                        for (i=0;i<len;i++) mapH[i]=3;
                    }
                    //共通の初期化
                    scene   =next;
                    next    =-1;
                    keyEvent=-999;
                }
                g.lock();

                //背景の描画
                g.setColor(g.getColorOfRGB(170,200,255));
                g.fillRect(0,0,240,240);
                for (i=0;i<32;i++) {
                    g.setColor(g.getColorOfRGB(106+i*2,136+i*2,255));
                    g.fillRect(0,i*2,240,2);
                }

                //地面の描画
                for (i=0;i<len;i++) {
                    g.drawImage(image[2],mapX+i*24,240-mapH[i]*24);
                }

                //キツネの描画
                i=(jumpAble)?score%2:1;
                g.drawImage(image[i],36,foxY-24);

                //スコアの描画
                g.setColor(g.getColorOfName(g.WHITE));
                g.drawString(""+score,10,10+font.getAscent());

                //プレイ時の処理
                if (scene==S_PLAY) {
                    //スコア加算
                    score++;

                    //衝突判定
                    if (foxY>240-mapH[2]*24) {
                        next=S_GAMEOVER;
                        jumpAble =false;
                    }
                    //上昇
                    else if (jumpPow>=0) {
                        foxY-=jumpPow*2;
                        jumpPow--;
                    }
                    //下降
                    else {
                        foxY+=6;
                        jumpAble=false;
                        if (mapH[2]!=0 &&
                            foxY>240-mapH[2]*24) {
                            foxY=240-mapH[2]*24;
                            jumpAble=true;
                        }
                    }
                    //横スクロール
                    mapX-=4;
                    if (mapX==-24) {
                        mapX=0;
                        //地面の高さを左にシフト
                        System.arraycopy(mapH,1,mapH,0,len-1);

                        //地面の高さを指定
                        i=(rand.nextInt()>>>1)%5;
                        if (mapH[len-2]==0) { //"len-2"が穴の時"len-1"は"len-3"と同じ高さ
                            mapH[len-1]=mapH[len-3];
                        } else if (i==0) {//5分の1の確立で穴
                            mapH[len-1]=0;
                        } else if (i==1) {//5分の1の確立で1高く
                            mapH[len-1]=mapH[len-2]+1;
                            if (mapH[len-1]>4) mapH[len-1]=4;
                        } else if (i==2) {//5分の1の確立で1低く
                            mapH[len-1]=mapH[len-2]-1;
                            if (mapH[len-1]<1) mapH[len-1]=1;
                        }
                    }

                    //ジャンプ処理
                    i=getKeypadState();
                    if (jumpAble && ((1<<IDisplay.KEY_SELECT)&i)!=0) {
                        jumpAble=false;
                        jumpPow =9;
                    } else if (!jumpAble && ((1<<IDisplay.KEY_SELECT)&i)==0) {
                        jumpPow=-10;
                    }
                }

                //ゲームオーバー時の処理
                if (scene==S_GAMEOVER) {
                    if (foxY<240+33) foxY+=12;
                    g.drawImage(image[3],(240-82)/2,60);
                }
                g.unlock(true);

                //キーイベント
                if (keyEvent==IDisplay.KEY_SOFT1) next=S_PLAY;
                keyEvent=-999;

                //スリープ
                sleepTime=sleepTime+100-System.currentTimeMillis();
                if (sleepTime<0)   sleepTime= 10;
                if (sleepTime>100) sleepTime=100;
                Thread.sleep(sleepTime);
                sleepTime=System.currentTimeMillis();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //キーイベントの処理
    public void processEvent(int type,int param) {
        if (type==IDisplay.KEY_PRESSED_EVENT) keyEvent=param;
    }
}


IDisplay.java
//iアプリのDisplayクラスのラッパー
public class IDisplay {
    public final static int KEY_0             =0x00;
    public final static int KEY_1             =0x01;
    public final static int KEY_2             =0x02;
    public final static int KEY_3             =0x03;
    public final static int KEY_4             =0x04;
    public final static int KEY_5             =0x05;
    public final static int KEY_6             =0x06;
    public final static int KEY_7             =0x07;
    public final static int KEY_8             =0x08;
    public final static int KEY_9             =0x09;
    public final static int KEY_ASTERISK      =0x0a;
    public final static int KEY_POUND         =0x0b;
    public final static int KEY_UP            =0x11;
    public final static int KEY_DOWN          =0x13;
    public final static int KEY_LEFT          =0x10;
    public final static int KEY_RIGHT         =0x12;
    public final static int KEY_CLEAR         =0x20;
    public final static int KEY_IAPP          =0x18;
    public final static int KEY_SELECT        =0x14;
    public final static int KEY_SOFT1         =0x15;
    public final static int KEY_SOFT2         =0x16;
    public final static int KEY_PRESSED_EVENT =0;
    public final static int KEY_RELEASED_EVENT=1;
}

IFont.java
import javax.microedition.lcdui.*;

//iアプリのFontクラスのラッパー
public final class IFont {
    //Font定数
    public final static int SIZE_TINY  =Font.SIZE_SMALL;
    public final static int SIZE_SMALL =Font.SIZE_MEDIUM;
    public final static int SIZE_MEDIUM=Font.SIZE_LARGE;

    //変数
    Font font;//フォント

    //フォントの取得
    public static IFont getFont(int size) {
        IFont iFont=new IFont();
        iFont.font=Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_PLAIN,size);
        return iFont;
    }

    //文字列幅の取得
    public int stringWidth(String str) {
        return font.stringWidth(str);
    }

    //ラインブレイクの取得
    public int getLineBreak(String str,int offset,int len,int width) {
        for (int l=0;l<=len-offset;l++) {
            if (font.substringWidth(str,offset,l)>width) {
                return offset+l-1;
            }
        }
        return str.length();
    }
    
    //アセントの取得
    public int getAscent() {
        return font.getBaselinePosition();
    }

    //ディセントを取得
    public int getDescent() {
        return font.getHeight()-font.getBaselinePosition();
    }
}


IGraphics.java
import javax.microedition.lcdui.*;

//iアプリのGraphicsクラスのラッパー
public final class IGraphics {
    //色定数
    public static int AQUA   =(  0<<16)+(255<<8)+255;
    public static int BLACK  =(  0<<16)+(  0<<8)+  0;
    public static int BLUE   =(  0<<16)+(  0<<8)+255;
    public static int FUCHSIA=(255<<16)+(  0<<8)+255;
    public static int GRAY   =(128<<16)+(128<<8)+128;
    public static int GREEN  =(  0<<16)+(128<<8)+  0;
    public static int LIME   =(  0<<16)+(255<<8)+  0;
    public static int MAROON =(128<<16)+(  0<<8)+  0;
    public static int NAVY   =(  0<<16)+(  0<<8)+128;
    public static int OLIVE  =(128<<16)+(128<<8)+  0;
    public static int PURPLE =(128<<16)+(  0<<8)+128;
    public static int RED    =(255<<16)+(  0<<8)+  0;
    public static int SILVER =(192<<16)+(192<<8)+192;
    public static int TEAL   =(  0<<16)+(128<<8)+128;
    public static int WHITE  =(255<<16)+(255<<8)+255;
    public static int YELLOW =(255<<16)+(255<<8)+  0;

    //変数
    private Graphics offGra;//グラフィクス
    private Canvas   canvas;//キャンバス
    private int      oriX;  //原点X座標
    private int      oriY;  //原点Y座標

    //コンストラクタ
    public IGraphics(Graphics offGra,Canvas canvas) {
        this.offGra=offGra;
        this.canvas=canvas;
        offGra.setFont(Font.getFont(Font.FACE_MONOSPACE,
            Font.STYLE_PLAIN,Font.SIZE_SMALL));
    }
    
    //原点の指定
    public void setOrigin(int oriX,int oriY) {
        this.oriX=oriX;
        this.oriY=oriY;
    }

    //文字列の描画
    public void drawString(String str,int x, int y) {
        offGra.drawString(str,x+oriX,y+2+oriY,offGra.LEFT|offGra.BASELINE);
    }

    //イメージの描画
    public void drawImage(Image image,int x,int y) {
        offGra.drawImage(image,x+oriX,y+oriY,offGra.LEFT|offGra.TOP);
    }
    
    //イメージの一部描画
    public void drawImage(Image image,int dx,int dy,int sx,int sy,int width,int height) {
        int cx=offGra.getClipX();
        int cy=offGra.getClipX();
        int cw=offGra.getClipWidth();
        int ch=offGra.getClipHeight();
        dx+=oriX;
        dy+=oriY;
        sx+=oriX;
        sy+=oriY;
        offGra.setClip(dx,dy,width,height);
        offGra.drawImage(image,dx+oriX-sx,dy+oriY-sy,offGra.LEFT|offGra.TOP);
        offGra.setClip(cx,cy,cw,ch);
    }

    //ラインの描画
    public void drawLine(int x1,int y1,int x2,int y2) {
        offGra.drawLine(x1+oriX,y1+oriY,x2,y2);
    }

    //矩形の描画
    public void drawRect(int x,int y,int width,int height) {
        offGra.drawRect(x+oriX,y+oriY,width,height);
    }

    //矩形の塗り潰し
    public void fillRect(int x,int y,int width,int height) {
        offGra.fillRect(x+oriX,y+oriY,width,height);
    }

    //円弧の塗り潰し
    public void fillArc(int x,int y,int width,int height,
        int startAngle,int arcAngle) {
        offGra.fillArc(x+oriX,y+oriY,width,height,startAngle,arcAngle);
    }

    //フォントの設定
    public void setFont(IFont font) {
        offGra.setFont(font.font);
    }

    //色の取得
    public static int getColorOfName(int name) {
        return name;
    }

    //色の取得
    public static int getColorOfRGB(int red,int green,int blue) {
        return (red<<16)+(green<<8)+blue;
    }

    //色の設定
    public void setColor(int color) {
        offGra.setColor(color);
    }

    //ロック
    public void lock() {
    }

    //アンロック
    public void unlock(boolean forced) {
        canvas.repaint();
        canvas.serviceRepaints();
    }
    
    //クリッピングのクリア
    public void clearClip() {
        offGra.setClip(0,0,240,240);
    }
    
    //クリッピング
    public void clipRect(int x,int y,int width,int height) {
        offGra.setClip(x,y,width,height);
    }

    //クリッピング
    public void setClip(int x,int y,int width,int height) {
        offGra.setClip(x,y,width,height);
    }
}


ICanvas.java
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import java.io.*;
import java.util.*;

//iアプリのCanvasクラスのラッパー
public class ICanvas extends Canvas
    implements CommandListener {

//====================
//初期化
//====================
    //コンストラクタ
    public ICanvas() {
        setCommandListener(this);
    }


//====================
//キー
//====================
    //キー定数
    public final static int SOFT_KEY_1=0;
    public final static int SOFT_KEY_2=1;
    public final static int KEY_NONE  =-999;

    //キー変数
    private int       keypadState;             //キー状態
    private String[]  softLabel=new String[2]; //ソフトラベル
    private Command[] softKey  =new Command[2];//ソフトキー

    //ソフトラベル指定
    public void setSoftLabel(int key,String label) {
        //初期化
        if (softKey[0]==null) {
            softLabel[0]="";
            softLabel[1]="";
            softKey[0]=new Command("",Command.SCREEN,0);
            softKey[1]=new Command("",Command.SCREEN,1);
            addCommand(softKey[0]);
            addCommand(softKey[1]);
        }
        //ソフトキー1・2変更
        if (key==SOFT_KEY_1) {
            if (softLabel[0].equals(label)) return;
            removeCommand(softKey[1]);
            removeCommand(softKey[0]);
            softLabel[0]=label;
            softKey[0]=new Command(label,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 Command(label,Command.SCREEN,1);
            addCommand(softKey[1]);
        }
    }

    //ソフトキーイベント
    public void commandAction(Command c,Displayable s) {
        if (c==softKey[0]) {
            processEvent(IDisplay.KEY_PRESSED_EVENT,IDisplay.KEY_SOFT1);
        } else {
            processEvent(IDisplay.KEY_PRESSED_EVENT,IDisplay.KEY_SOFT2);
        }
    }

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

    //キーリリースイベント
    public void keyReleased(int keyCode) {
        int key=getKey(keyCode);
        if (key>=0 && (keypadState&(1<<key))!=0) keypadState-=(1<<key);
        processEvent(IDisplay.KEY_RELEASED_EVENT,key);
    }

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

    //キーパッド状態の取得
    public int getKeypadState() {
        return keypadState;
    }

    //イベント処理
    public void processEvent(int type,int param) {
    }


//====================
//描画
//====================
    //ダブルバッファリング
    private Image     offImg=Image.createImage(240,240);
    private IGraphics g=new IGraphics(offImg.getGraphics(),this);
    private boolean   redraw=true;

    //描画
    public final void paint(Graphics g) {
        if (redraw) {
            g.setColor((10<<16)+(10<<8)+10);
            g.fillRect(0,0,getWidth(),getHeight());
            redraw=false;
        }
        if (offImg!=null) {
            g.drawImage(offImg,(getWidth()-240)/2,
                (getHeight()-240)/2,g.LEFT|g.TOP);
        }
    }
    
    //グラフィックスの取得
    public IGraphics getGraphics() {
        return g;
    }
}


S!アプリ(P型)のJADファイル
ActionGame.jad
MIDlet-1: A, , A
MIDlet-Jar-Size: 9085
MIDlet-Jar-URL: ActionGame.jar
MIDlet-Name: ActionGame
MIDlet-Vendor: My Vendor
MIDlet-Version: 1.0
MicroEdition-Profile: MIDP-1.0
MicroEdition-Configuration: CLDC-1.0
MIDlet-Application-Range: 0,0



−戻る−