こんばんは。

今日は個人的に忙しかったのと、マップエディタを製作中なのとで中々作業が進みませんでした。

同じJavaでもSEとMEでは使えるクラスが違って、実装も大きく異なってきますね。

特に、MEでは使えるクラスが少なくて不便に感じることが多いかもしれませんが、描画周りは本当に楽させてもらってるなぁという感じです。



さて、ネタも尽きてきましたが、J2MEでsplit関数でも実装してみましょう。



public static String[] split(String str,String sep) {

    Vector temp = new Vector();

    while(str.indexOf(sep) > 0){

      temp.addElement(str.substring(0,str.indexOf(sep)));

      str = str.substring(str.indexOf(sep)+sep.length());

    }

    temp.trimToSize();

    String[] result = new String[temp.capacity()+1];

    for(int i=0;i<temp.capacity();i++){

      result[i] = (String)temp.elementAt(i);

    }

    result[temp.capacity()]=str;

    return result;

}



単純な実装なので不明な点は無いと思います。あるとしたらVectorって0から入れてったら値の順序って保証されてるよね…?ってちょっと不安になるくらいですかね。

セパレータの位置をString.indexOf関数で探し、そこまでをString.substring関数で区切って一時保存用のVectorに放り込み…を繰り返して、最後に残った末尾も結果に加えてやる、という流れになっています。

携帯アプリでは未知の文字列が登場する機会自体が少ないので、split関数が要るかは若干疑問ですが…いざ必要なときのため実装しておくのも悪くないですね。







最近ドット絵の練習に明け暮れていて、中々コーディングが進みません…

ゲームに必要な素材という意味ではどちらも重要ですけどね!

さて、今日は昨日の続きで、マップチップ設定スクリプトの実装例を示してみましょう。






if(qf.searchLabel("MapChipDif")){

  temp = qf.readLine();

  Image temp_img = null;

  int col = 1;

  int row = 1;

  while(!temp[0].equals("EndDif")){

    if(temp[0].equals("loadImage")){

      temp_img = loadImage(temp[1]);

      col = Integer.parseInt(temp[2]);

      row = Integer.parseInt(temp[3]);

    }

    else if(temp[0].equals("ChipDif")){

      if(temp[4].equals("NONE"))

        mapchip[Integer.parseInt(temp[1])] =

        makeImageChip(temp_img,col,row,Integer.parseInt(temp[3]),Sprite.TRANS_NONE);



      else if(temp[4].equals("ROT90"))

        mapchip[Integer.parseInt(temp[1])] =

        makeImageChip(temp_img,col,row,Integer.parseInt(temp[3]),Sprite.TRANS_ROT90);



    }



    temp = qf.readLine();

    }

}





またもや自分のソースコードを載せるだけで恐縮なのですが…

qf.searchLabel →スクリプトから特定文字列をシークし、次の行に実行位置を移す関数

qf.readLine →スクリプトを改行まで読み込み、半角スペースで区切ってString[]を返す関数

です。

なお、makeImageChip関数はこの間と実装を変えて、元画像から特定部分を切り出して戻り値とする関数にしてあります。



肝心のスクリプトは

MapChipDif

loadImage mapchip1 5 5

ChipDif 0 as 0 NONE

ChipDif 1 as 1 NONE

ChipDif 2 as 1 ROT90

ChipDif 3 as 2 NONE

ChipDif 4 as 2 ROT90

ChipDif 5 as 2 ROT90

ChipDif 6 as 2 ROT90

ChipDif 7 as 3 NONE

EndDif



といった感じです。



実装例を示しただけで解説もロクにしておりませんが、恐らく問題になるところはないと思います…

もしかしたら、明日にでも簡単な解説を加えるかもしれません。



では、今日はこの辺で。




最近画像処理にかかりきりですが、画像はゲームの花形ですからね!仕方ないです。


いきなりですが、画像のパレット色を変更する関数を考えてみましょう。


public Image changePlteColor(byte[] temp,int plteid,int r,int g,int b){

  int index = new String(temp,0,temp.length).indexOf("PLTE")+4+ plteid*3;

  temp[index] = (byte)r;

  temp[index+1] = (byte)g;

  temp[index+2] = (byte)b;



  Image result = Image.createImage(temp, 0, temp.length);

  return result;

}


これを使えば、バイト列で表現された画像のパレット色を統一的に変更できます。渡されたバイト列のうち、「PLTE」チャンクを探してindexに修正位置を保存しています。この関数の場合、パレットNoは0から始まることに気をつけてください。



さて、実際に画像を扱う場合、マップなどの状態に依存した管理が求められることが多いと思います。

例としては、あるマップで使うマップチップや出現する敵の画像ですね。起動時に全て読み込んで保存しておくというのはメモリ効率が悪すぎます。



ここらを踏まえてスクリプトを書くとすると、



loadImageAsBytes nickname filename.png

createImage nickname01 local frombytes nickname

changePlteColor nickname 1 255 255 255

createImage nickname02 local frombytes nickname

release nickname

createImageChip nickname03 local from nickname02 4 4

defineEnemyImage 12 asChip nickname03 2

release local



といった感じになるでしょうか。

自分で適当に作ったスクリプトなので意味が分からないと思いますが、要は

・画像をバイト列として読み込む機能

・画像のパレット色を変更する機能

・画像からチップを切り出す機能

・切り出したチップを何かと関連付ける機能

・確保したメモリを、localなどのキーワードに応じて解放する機能

等が実装されていれば十分だと思います。なお、スクリプトの文字列から変数を指定することになるので、ハッシュを継承したクラス等が必要になりますね。