ここまでの冒険を記録しますか?

長岡技大ソフトウェア開発サークルの開発ブログ

【ゲーム製作入門】C/C++で簡単なRPGを作る⑨【DXライブラリ】

書き手:肥田野

DXライブラリでRPGのベースになるマップ画面やデータ管理などのあれこれの制作に挑戦してみます。

RPGとして完成する保証はありませんが、途中経過だけでも参考になれば幸いです。

この連載は前回までの内容を理解していることを前提に進めていきます。

今回は、今後必要になってくるウィンドウの表示と、CheckHitKeyによって長押しを防ぐ処理について解説します。

特にウィンドウ回りの構成は今後どう転んでもついて回ってくるので、私もかなり頭を抱えて作りました(^_^;)

それではソースコードを見ていきましょう。

まずはキーの長押しを防ぐ処理です。

今回のメインであるウィンドウの表示とは関係ありませんが、今後必須になってくる処理なので今の内に実装してしまいます。

≪Function.h≫

#pragma once
#include<DxLib.h>

int viewX = 0;
int viewY = 0;
bool hitAnyKey = false;

void CameraDraw(int x1,int y1,int x2,int y2,int gh,int trans){
    DrawExtendGraph(x1-viewX,y1-viewY,x2-viewX,y2-viewY,gh,trans);
}

bool PushKey(int keyCode){
    if(CheckHitKey(keyCode)){
        if(!hitAnyKey){
            hitAnyKey = true;
            return true;
        }
    }
    return false;
}

前回作ったヘッダファイルに関数を追加します。

bool hitAnyKey = false;

グローバル変数を一つ増やしました。

これは書いて字の如く、キーボードのいずれかのキーが押されている間はtrue、すべてのキーから指が離されていたらfalseを返すように処理していきます。

bool PushKey(int keyCode){

こちらが新しく作った関数です。返り値はbool型で、引数に指定したキーを最初に押したときだけtrueを返します。

内部でCheckHitKeyを使っているので、ここでの引数もKEY_INPUT_○○の定数を使います。

処理を順に追うと、まず引数で指定したキーが押されているかを調べています。

ここで押されていなければそもそも論外なのでif文を抜けてfalseをreturnします。

指定のキーが押されていた時、今度はグローバル変数hitAnyKeyを調べます。

この時hitAnyKeyがfalseだったら、つまり直前までどのキーも押されていなかったということになりますから、trueをreturnします。さらにhitAnyKeyもtrueにしています。

≪WindowBox.h≫

#pragma once
#include<DxLib.h>
#include"Function.h"

class Waku{
public:
    int x,y,width,height,gh[9];
    
    Waku(int setx,int sety,int setwidth,int setheight){
        x = setx;
        y = sety;
        width = setwidth;
        height = setheight;
        LoadDivGraph("graphic\\WindowBase.png",9,3,3,6,6,gh);
    }
    void View(){
        DrawGraph(x,y,gh[0],TRUE);
        DrawExtendGraph(x+6,y,x+width-6,y+6,gh[1],TRUE);
        DrawGraph(x+width-6,y,gh[2],TRUE);
        DrawExtendGraph(x,y+6,x+6,y+height-6,gh[3],TRUE);
        DrawExtendGraph(x+6,y+6,x+width-6,y+height-6,gh[4],TRUE);
        DrawExtendGraph(x+width-6,y+6,x+width,y+height-6,gh[5],TRUE);
        DrawGraph(x,y+height-6,gh[6],TRUE);
        DrawExtendGraph(x+6,y+height-6,x+width-6,y+height,gh[7],TRUE);
        DrawGraph(x+width-6,y+height-6,gh[8],TRUE);
    }
};

新しいヘッダファイルを用意して、クラスを定義しました。

これがメッセージや選択肢を表示するための枠になります。

使用する画像はウディタの基本データから拝借しました。まあ18×18ピクセルであれば問題ないので、これぐらいはペイントでサクッと自作するのも楽しいでしょう。

f:id:NUT_SoftwareDevelopper:20150522174614p:plain

コンストラクタの引数でx、y座標と縦横のサイズを定義し、LoadDivGraphで分割読み込みします。

もう定番の処理ですね。詳しい説明は省きます。

void View(){

思わず目が眩みそうになるDrawGraph・DrawExtendGraphのラッシュですが、やっていることは9分割した画像をクラスのオブジェクトが持っているサイズに引き伸ばしているだけです。

画像を分割せずに引き延ばすとふちの部分が分厚くなってしまうので、わざわざパーツごとに拡大率を指定しているんですね。

≪Control.h≫

#pragma once
#include<DxLib.h>
#include"Map.h"
#include"Player.h"
#include"WindowBox.h"

class Control{
public:
    Player* pl;
    Map* map[3];
    int camX,camY;
    Waku* msg;

    Control(){
        camX = camY = 0;
        pl = new Player();
        map[0] = new Map("csv\\flame1.csv");
        map[1] = new Map("csv\\flame2.csv");
        map[2] = new Map("csv\\flame3.csv");
        pl->x = pl->targetX = CELL_WIDTH;
        pl->y = pl->targetY = CELL_HEIGHT;
        msg = new Waku(0,360,WINDOW_X,120);
    }

    ~Control(){
        delete pl;
        for(int i=0;i<3;i++){
            delete map[i];
        }
        delete msg;
    }

    void All(){
        if(!CheckHitKeyAll())hitAnyKey = false;

        if(pl->x>WINDOW_X/2 && pl->x<map[0]->width-WINDOW_X/2+CELL_WIDTH){
            viewX = pl->x-WINDOW_X/2;
        }
        if(pl->y>WINDOW_Y/2 && pl->y<map[0]->height-WINDOW_Y/2){
            viewY = pl->y-WINDOW_Y/2;
        }

        for(int i=0;i<3;i++)map[i]->BackView();
        pl->All(map);
        for(int i=0;i<3;i++)map[i]->FrontView();
        msg->View();
    }
};

Waku* msg;

Wakuクラスのポインタです。名前はmessageの略にしました。今回は表示のテストをするために一時的に実体化させるので、この辺りはそう凝らなくて大丈夫です。

if(!CheckHitKeyAll())hitAnyKey = false;

話が前後しますが、ここでグローバル変数hitAnyKeyを判定しています。

CheckHitKeyAllは初めて使う関数ですが、まあ名前で判りますね。全てのキーを調べて、押されているかどうかを1か0で返します。bool型の変数にそのまま代入しても大丈夫です。

さて、ウィンドウは表示できましたね?

次回はここにメッセージを表示させてみたいと思います。

普通に文字を打つだけならDrawFormatStringで事足りるのですが、それでは実用的ではないため、テキストファイルから読み込んでいく予定です。