JAVAプログラミング講座 宇宙のJAVAさん 第2部

- 第2話 くまさん、恋のあと -


 

くま先生 はろー、みなさん!!

ミャンちゃん はろー、クマ先生

うし君 早速プログラムをやろうも〜

くま先生 えーと、今回は前回予告したとおり「 JAVAアドベンチャー 」の続きを作ります。

ミャンちゃん ??? RPG じゃなかったみゃあか???

うし君 そうだも〜

くま先生 あ! そうでした!

くま先生 最近「 酸素欠乏症 」にかかってしまって、記憶が曖昧なんです・・・

うし君 また解りずらいギャグだも〜

ミャンちゃん にゃんでここで、 テム・レイ ???


くま先生 さて、<HR> も記入したことですし、まじめに行きます。

ミャンちゃん また解りずらい・・・

くま先生 さて、前回ランダムでマップを作りましたね・・・

くま先生 今回はそのマップの中で、キャラクターを動かしてみましょう。
さしあたり、(300 x 300)のマップの周りを海で囲みましょう。

くま先生 今後プログラムを追加していって、海には入れないようにします。
そうしたら、キャラが画面からはみ出すことが無くなりますので・・・

うし君 では、init() のランダムマップをつくる部分に追加するも〜か??

くま先生 そうです。 for文で 変数 xx と yy を変化させてマップを作っているわけですが、ここにプログラムを追加します。

        map = new int[300][300];

        for (int yy=0; yy<300; yy++){
            for (int xx=0; xx<300; xx++){
                map[xx][yy] = (int) (4 * Math.random());
                if( xx<4 ) map[xx][yy] = 4;
                if( xx>295 ) map[xx][yy] = 4;
                if( yy<4 ) map[xx][yy] = 4;
                if( yy>295 ) map[xx][yy] = 4;

            }
        }
              
    } // init()


くま先生 たとえば、

if( xx<4 ) map[xx][yy] = 4;

のプログラムでは、xx が4よりも小さかったら、せっかくランダムで求めた背景番号をやめて、必ず背景番号4(海)にします。
これによりマップの左端(X座標0〜3)は海になります。

くま先生 同様に、マップ右端、上部、下部を海(背景4)にするプログラムを書きます。

うし君 これって、まとめられんじゃないかも〜???

くま先生 お!良いことを言いますね・・・
そうです、この4行はまとまられます。 次の1行になります。

if ( xx<4 || xx>295 || yy<4 || yy>295 ) map[xx][yy] = 4;

ここらへんはC言語の文法と一緒です。
今回はより解りやすく、4行でプログラムしました。

くま先生 次にキャラクターの座標を考えます。

ミャンちゃん キャラクターは常にマップの中心じゃないかみゃん??

くま先生 それは表示の時の話です。
マップを移動する以上、今マップのどこにキャラクターがいるか変数を用意する必要があります。

くま先生 グローバル変数に追加します。 変数名は cx cy です。

public class MapPaint extends Applet {
   
    // グローバル変数
   
    Image haikei[];
    Image player1, player2;

    int map[][];

    int cx, cy;

くま先生 次に今作ったキャラクター座標( cx , cy )に初期値を入れます。
さいしょキャラは 50 , 50 の所からスタートするようにします。
init() で変数に数字を代入します。 さっきのマップ作成プログラムの下に追加します。

        map = new int[300][300];
  
        for (int yy=0; yy<300; yy++){
            for (int xx=0; xx<300; xx++){
                map[xx][yy] = (int) (4 * Math.random());
                if( xx<4 ) map[xx][yy] = 4;
                if( xx>295 ) map[xx][yy] = 4;
                if( yy<4 ) map[xx][yy] = 4;
                if( yy>295 ) map[xx][yy] = 4;
            }
        }
       
        cx=50; cy=50;
       
    } // init()

くま先生 さて、paint() で画面が表示されるのですが、キャラは最初 50 , 50 の場所にいなくてはなりません。
ゲーム画面上では背景画像が 縦9個、横9個 表示されます。
キャラは真中に表示されるので、ゲーム画面中央のマップの座標が 50 , 50 となります。
するとゲーム画面左上の座標は、 50-4 , 50-4 となります。 つまり 46 , 46 ですね・・・
主人公の座標は変数 cx , cy なので、ゲーム画面左上のマップ座標は cx-4 , cy-4 となります。
そして右下のマップ座標は cx+4 , cy+4 となるわけです。

ミャンちゃん みゃ、みゃ、みゃ。 むずかしいみゃ・・・

くま先生 たしかに結構難しいですね・・・
つまり、「中央の cx , cy というマップ座標を中心に、背景画像を作画する」と考えてください。
paint() のプログラムを次のように変更します。

    // -----------------------------------------------------------
    public void paint(Graphics g) { // 作画処理
       
        int no, mx, my;
       
        for ( my=0; my<9; my++) {
            for ( mx=0; mx<9; mx++) {
               no = map[cx-4+mx][cy-4+my];
                g.drawImage( haikei[no], mx*40, my*40, this);
            }
        }
   
        g.drawImage( player1, 4*40, 4*40, this);
       
    } // paint()

くま先生 これで、キャラ座標 cx cy を中心に背景が作画されるようになりました。

うし君 やったもー。 では、早速 cx cy を変化させて、キャラをうごかすも〜!!

くま先生 ところが、ここで1つ問題があります。

うし君 また始まったも〜

ミャンちゃん 必ず問題が出るみゃん・・・

くま先生 マウスでクリックした方向に動かしたいのですが、クリックした場所がどっちの方向か解らないのです。

うし君 マウスをクリックした時、マウスのX座標とY座標は取れるんだも〜??
それで何とかならないかも〜??

くま先生 キャラを左右にだけ動かすなら、マウスクリックされたX座標を見て、ある値より大きかったら右方向、小さかったら左方向に動かします。
同様に上下にしか動かないなら、マウスクリックされたY座標を見ます。
しかし、今回は上下左右に動かしたいのです。

st202_1.gif (1517 バイト)

くま先生 この図のように、キャラを中心としてどちら方向でマウスが押されたかが知りたいのです。

うし君 どうするも〜???

くま先生 今回は正道で行きます。
マウスクリックされた場所のX,Yを利用して、方向を計算で割り出す関数を作ります。

うし君 本格的だも〜!!

くま先生 関数名は checkDirection() です。
ソースプログラムの最後( End of Class の上)に追加してください。


    public int checkDirection(int mx, int my) {
        boolean c1=false;
        boolean c2=false;
        Dimension dim = this.size();
        my = dim.height-my;
        double dx = (double)dim.width;
        double dy = (double)dim.height;
        if(my>(int)((dy/dx)*mx)) c1=true;
        if(my>(int)(dy-(dy/dx)*mx)) c2=true;
        if (c1&&c2) return 1;
        if (!c1&&c2) return 2;
        if (!c1&&!c2) return 3;
        if (c1&&!c2) return 4;
        return 0;
    } // checkDirection()

   
// ===============================================================
} // End of Class

ミャンちゃん みゃん!!!!! すごい関数だみゃん!!!! むずかし〜

くま先生 算数を駆使して作りました。

うし君 普通、「数学を駆使して・・」じゃないかも〜???

くま先生 面倒なので、この関数のプログラム的説明は省きます。

くま先生 使い方ですが、この関数にクリックされたマウスのX座標とY座標を渡すと、返り値としてクリックされた場所の方向を数字で返してきます。

上:1 右:2 下:3 左:4 が返り値として返ってきます。

くま先生 さて、これでもう安心ですね。
この関数にマウスクリックの座標を渡して、1だったらキャラを上に動かします。
同様に、2だったら右に、3だったら下に、4だったら左に動かします。

くま先生 では早速作りましょう。 マウスを押して動かしたいので、mouseDown() にプログラムします。

    public boolean mouseDown(Event e, int x, int y) { // マウスダウン
       
        int pos;
       
        pos = checkDirection( x, y);
       
        if (pos == 1) cy--;
        if (pos == 3) cy++;
        if (pos == 2) cx++;
        if (pos == 4) cx--;
       
        repaint();

       
        return true;
    } // mouseDown()

くま先生 こうなります。
まずどちら方向に動くのか、先ほどの関数 checkDirection( ) を使って調べます。
調べた結果は変数 pos に入れます。
さきほど言ったとおり、この値が
1だったらキャラを上に動かします。
2だったら右に、3だったら下に、4だったら左に動かします。

くま先生 cy-- というのは、「cy の値を1つ減らせ」という命令です。
これでキャラのY座標が1つ減るので、キャラは上に1つ進むわけです。
キャラの座標を動かしたら、再作画をして画面を描き換えます。

くま先生 これで移動プログラムは完成です! MapPaint.javaMapPaint.classDIR

うし君 わーい。 動くも〜

ミャンちゃん RPGだみゃ〜

ミャンちゃん 本当だ! 周りは海だみゃ〜

くま先生 ちなみにキャラの初期状態のマップ座標が 50 , 50 なので、左か上に50歩動くと、マップの端に行けます。

・・・

・・

ミャンちゃん はうあ!!!

くま先生 みゃあちゃん、どうしました?

ミャンちゃん 海に入ったら、エラーを出してとまってしまったにゃん!!

くま先生 それはキャラが画面からはみ出てしまったんですよ。

st201_2.gif (5428 バイト)

くま先生 これは第一話の説明図ですが、マップ座標 300 x 300 (黒い四角)の中を 9 x 9 の表示画面(赤い四角)が動きまくって、キャラを動かしているんです。

くま先生 あまりマップの端のほうに行くと、マップデータが存在していない場所に行ってしまうんです。
つまり、赤い四角黒い四角からはみ出るんです。
これだと画面作画ができないので、エラーで止まってしまいます。

ミャンちゃん なるほどみゃん! どうするみゃん!!

くま先生 次回の第3話では、海と山にキャラを入れないようにしましょう!!
このマップは海で囲まれているので、こうすればキャラがマップの外に飛び出すことはなくなります。

ミャンちゃん 次の講座が楽しみだみゃん・・・

うし君 ももももも・・・

くま先生 では、みなさん。 さようなら〜

うし君ミャンちゃん 先生、さようなら〜

 

 

- 第3話につづく -


戻る