その9ー1 《総集編》 ロールプレイングゲームの作成 マップの表示

いよいよ、ロールプレイングゲームを
プログラミングで作っていきます



これまでの章での知識を活かせば
ロールプレイングゲームは作れます




丸写しでゲームが動くようにプログラムを作ります


が、コピペはできません

打ち込みでの丸写しは面倒だとは思いますが
コピペだと流れ作業になってしまい、頭には入りません



自身でコードを打つほうが

「こんな関数、そういえばあったな」

と思い出したりと
しっかりと技術として身に付くと思います




プログラミングは水泳(泳ぐこと)と同じだと言われています
1度自分の身に付いた技術は
一生忘れることはなく、脳が記憶しているそうです






ちなみに、ゲームプログラミングと
普通のアプリケーションプログラミング
実は何も違いはありません

ゲームプログラミングを学べば
それだけアルゴリズムの幅が広がり
プログラミングを行う上で活かせるものも多くなります



 マップの作成 



5-1で作成したマップを、そのまんま使ってマップを作ります

今回は記号ではなく
ビットマップを表示していきます





マップチップを作ります


「マップチップ」とは、
記号の代わりに表示するマップ
上の画像は、その集まりです


画像左から、
  0 (平地)  
■ 1 (壁)   
□ 2(カウンター)
◆ 3 (柱)   
# 4 (柵)   
~ 5 (丘・山) 
▼ 6 (柱)   
▲ 7 (柱)   
↑ 8 (装飾)  
ψ 9 (装飾)  
§ 10(装飾)  
【 11(扉)   
】 12(扉)   
《 13(壁)   
》 14(壁)   
? 15(人)   


とりあえず30×30ドットで16個作成して並べてください


後でちゃんと描けばいいので
今は単色で塗りつぶしたものを16個でも良いと思います





int  map[20][30] = {
{1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5},
{1,0,15,0,1,15,2,0,0,15,0,1,0,5,5,5,5,0,0,5,5,5,0,0,0,0,15,0,5,5},
{1,0,0,0,1,0,2,0,0,0,0,1,0,5,5,0,0,0,5,5,5,5,5,5,0,0,0,0,0,5},
{1,1,0,1,1,1,0,0,0,0,15,1,0,5,5,5,0,0,0,5,5,5,0,0,0,0,0,5,5,5},
{5,4,0,4,4,1,0,0,0,0,0,1,0,0,5,5,5,0,0,0,5,5,0,0,0,0,0,0,5,5},
{5,5,0,0,0,1,1,3,0,3,1,1,0,4,4,4,5,5,0,0,0,0,0,0,0,0,0,0,0,5},
{5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,5,0,0,0,0,0,0,0,0,9,0,9,0,5},
{5,5,5,0,0,0,0,0,0,0,0,0,0,15,0,4,5,5,5,5,0,0,1,1,1,1,0,1,1,1},
{5,5,5,5,4,4,0,4,4,4,4,4,0,0,4,4,5,0,0,0,0,0,1,0,0,0,0,0,0,1},
{5,5,5,5,5,0,0,5,5,5,5,0,0,0,5,5,0,0,0,0,0,0,1,0,15,0,0,0,0,1},
{5,5,5,5,0,0,0,0,5,5,5,5,5,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1},
{5,5,5,0,0,0,0,0,0,5,5,5,5,1,0,0,0,0,0,1,0,0,0,0,0,1,10,15,10,1},
{5,0,0,0,0,0,0,0,5,5,5,5,5,1,0,0,15,0,0,0,0,0,0,0,0,1,0,0,0,1},
{0,15,0,0,0,0,0,0,0,0,0,5,5,1,0,0,0,0,0,0,0,0,0,0,0,1,14,0,13,1},
{0,0,0,0,5,5,0,0,0,0,0,0,5,1,0,0,0,0,0,1,0,0,15,0,0,1,0,0,0,1},
{5,5,0,0,0,5,5,0,0,0,8,8,8,1,1,12,0,11,1,1,1,12,0,11,1,1,14,0,13,1},
{5,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,13,1},
{5,5,0,0,0,0,0,15,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,1},
{5,5,5,5,5,5,0,0,0,0,8,8,8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};


マップの配列変数は
5-1のものをそのまんま使います


for (i= 0;i < 20;i++) {
  for (j= 0; j < 30; j++) {

    //マップ表示かキャラ表示の条件分岐
    if(y==i & &x==j) {
      std::cout < < " “;
    }
    else if(map[i][j]==1){
      std::cout < < " “;//壁表示
    }
    else if(map[i][j]==2){
      std::cout < < " “;//お店のカウンター表示
    }
    else if(map[i][j] == 3) {
       std::cout < < " “;//柱表示
    }
    else if(map[i][j] == 4) {
      std::cout < < " “;//柵表示
    }
    else if(map[i][j] == 5) {
      std::cout < < " “;//丘表示
    }
    else if(map[i][j] == 6) {
      std::cout < < " “;//柱表示
    }
    else if(map[i][j] == 7) {
      std::cout < < " “;//柱表示
    }
    else if(map[i][j] == 8) {
      std::cout < < " “;//装飾表示
    }
    else if(map[i][j] == 9) {
      std::cout < < "ψ “;//装飾表示
    }
    else if(map[i][j] == 10) {
      std::cout < < "§ “;//装飾表示
    }
    else if(map[i][j] == 11) {
      std::cout < < " “;//扉表示
    }
    else if(map[i][j] == 12) {
      std::cout < < " “;//扉表示
    }
    else if(map[i][j] == 13) {
      std::cout < < " “;//壁表示
    }
    else if(map[i][j] == 14) {
      std::cout < < " “;//壁表示
    }
    else if(map[i][j] == 15) {
      std::cout < < " “;//人表示
    }
    else{
      std::cout < < "  ";//歩ける場所表示
    }
    //ここまで

  }
  std::cout < < "¥n “;
}


で、肝心の表示のための上のプログラムですが
記号を表示させる部分を
ビットマップ表示に変えていく必要があります


まずは、8章のビットマップ表示プログラミングに
マップチップのビットマップを追加します





デバイスコンテキスト
dcMem2
を追加してビットマップを読み込む準備をしましょう





続いて、初期化の関数InitInstance()内で
マップチップのビットマップをリソースに追加し
デバイスコンテキスト
dcMem2
に割り当てます

これでマップチップのビットマップは
いつでも呼び出すことができます



ついでに、上の方にあるCreateWindowW()関数の
第6第7引数を
916、659に変えてください


これは実際にウィンドウを作る関数なのですが
第6引数:ウィンドウの幅
第7引数:ウィンドウの高さ
となっています


マップチップ1つの大きさが30×30ドット
マップの配列変数は、x30個、y20個
マップチップを並べて表示すると、
幅30が30個で900ドット
高さ30が20個で600ドット
になります

ですが、CreateWindowW()関数は
絶対座標の数値でウィンドウを作成してしまうので
タイトルバーや枠などを含んだ幅と高さになってしまい、
この数値だとマップが見切れます


作業領域のみの座標の取り方もあるのですが
長くなるので今回は割愛します






マップチップを並べて表示していきます


準備ができたので
記号を表示させるプログラムを
ビットマップ表示のプログラムに変えます




この1行のみになります


え??
5-1の記号の時はあんなに長かったのに?!

if条件式もいらないの?




これが、WindowsAPIの強みです

BitBlt()関数は
第2、3引数:表示させるx、y座標      
第4,5引数:表示させる幅          
第7、8引数:デバイスコンテキストにある画像の
       どの位置からの画像を表示させるか
を指定できるので、こんなに簡単で済みます

このプログラムをLRESULTCALLBACKWndProc()関数内の
caseWM_PAINT:
内に入れて下さい





実行結果




うおマジか!!
ゲーム画面になった



お疲れ様でした
次章9-2ではマウスクリックで
キャラクターを移動させてみましょう





ソースコード