第3回:画面表示(2) 立ちキャラ・メッセージウィンドウの表示



第2回では、背景を表示するところまで行いました。
第3回では、この上に立ちキャラとメッセージウィンドウを表示します。

外部設計で決めたサイズの立ちキャラ画像を用意してください。
解説では、dataフォルダにchara01.bmpを用意したので、こちらを使います。
他に用意される場合は、chara01.bmpのように透過する色を決めて、
透過する部分をその色(以後、透過色と呼びます)で塗りつぶしてください。

立ちキャラ画像も、背景画像と同様に裏画面に格納して、
必要に応じて表画面に描画します。
前回のコードのグローバル宣言部に立ちキャラサイズの定数と、立ちキャラ用裏画面、
その番号を格納する値、表示中かどうかを示すフラグ変数を宣言します。

            
implementation

const
  WIN_W : Integer = 640; //背景画像の幅
  WIN_H : Integer = 480; //背景画像の高さ
            
            
  CHARA_W : Integer = 350; //立ちキャラ画像の幅
  CHARA_H : Integer = 480; //立ちキャラ画像の高さ
            
            
var
  BackBmp : TBitmap; //背景を格納する裏画面
  CurBack : Integer; //表示中の背景の番号
            
            
  CharaBmp : TBitmap; //立ちキャラを格納する裏画面
  CurChara : Integer; //格納している立ちキャラの番号
  SetChara : Boolean; //立ちキャラを表示しているか
            

SetCharaは、立ちキャラを表示していればTrue、
していなければFalseを返すようにするためのフラグです。
実体生成処理をFormCreateイベントに書き足します(リスト3)。

(リスト3)
            
procedure TMainForm.FormCreate(Sender: TObject);
begin
   //変数の初期値を代入
   CurBack := 1;
            
            
   CurChara := 1;
   SetChara := False;
            
            
   //オブジェクトの実体を生成する
   BackBmp := TBitmap.Create;
   with BackBmp do
   begin
      Width := WIN_W;
      Height := WIN_H;
      PixelFormat := pf24bit;
      HandleType := bmDIB;
      LoadFromFile(Format('..\\..\\data\\bg%.2d.bmp',[CurBack]));
   end;
            
            
   CharaBmp := TBitmap.Create;
   with CharaBmp do
   begin
      Width := CHARA_W;
      Height := CHARA_H;
      LoadFromFile(Format('..\\..\\data\\chara%.2d.bmp',[CurChara]));
      Transparent := True;  --------------------------------------(4)
   end;
            
            
   //表画面に背景を転送
   PrimImage.Picture.Assign(BackBmp);
            
            
   //立ちキャラを表示
   DrawChara;  ---------------------------------------------------(5)
            
            
end;
            

(4)のTransparentプロパティをTrueにすることによって、
余白の透過色部分を表示時に透過してくれるようになります。

CharaBmpを動的に生成しているので、FormDestroyイベントにて

            
procedure TMainForm.FormDestroy(Sender: TObject);
begin
   //オブジェクトを解放
   BackBmp.Free;
            
            
   CharaBmp.Free;
            
            
end;
            

と、解放することもお忘れなく。

(5)の手続きDrawCharaは、立ちキャラの表示を行うMainFormクラスの自作メソッドです。
宣言をtype節に、実体をFormDestroyの下あたりに書きましょう(リスト4)。

(宣言)
            
type
  TMainForm = class(TForm)
    PrimImage: TImage;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private 宣言 }
            
            
    procedure DrawChara;
            
            
  public
    { Public 宣言 }
  end;
            

(リスト4)
            
//立ちキャラを表示する
procedure TMainForm.DrawChara;
begin
   //裏画面を転送して、表画面に描かれた画像を消す
   PrimImage.Picture.Assign(BackBmp);
   //立ちキャラ画像を表画面に描画
   PrimImage.Canvas.Draw((WIN_W - CHARA_W) div 2,
                         WIN_H - CHARA_H,
                         CharaBmp);  --------------------------(6)
   //フラグを立てる
   SetChara := True;
end;
            

(6)のDrawメソッドの引数は、
[描画先のx座標、描画先のy座標、描画するTBitmapオブジェクト]です。
(6)の場合は、(WIN_W - CHARA_W) div 2 = 145、WIN_H - CHARA_H = 0から、
表画面の座標(145,0)に立ちキャラ画像の左上の点が来るように描画されます。

ここで実行してみましょう。
第2回で表示した背景の上に、立ちキャラが表示されているでしょうか。



続いてメッセージウィンドウの表示を行います。
立ちキャラの表示と大きく変わることはありません。
が、メッセージウィンドウは表示・消去する回数が立ちキャラの比ではありません。
そして、メッセージウィンドウを表画面から消去するためだけに
裏画面から背景画像を転送→立ちキャラを描画のプロセスを取ると煩雑ですので
ここでは裏画面を2つ用意し、片方にはメッセージウィンドウ画像を単体で、
他方には背景+立ちキャラ+メッセージウィンドウ+メッセージ描画部分のフェードアウト
まで施した画像を格納しておきます。

図で示してみましょう。
表画面PrimImageに対して、メッセージウィンドウ画像を格納する裏画面をMesWinBmp、
背景+立ちキャラ+メッセージウィンドウ+フェードアウトした画像を
格納する裏画面をMesWinTempBmpとします。

PrimImage
下120ピクセルをMesWinTempBmpにコピー
MesWinTempBmp
 
MesWinBmp
透過して描画
MesWinTempBmp
 
メッセージ表示部分をフェードアウトする MesWinTempBmp
 
表画面の下120ピクセルにコピーする PrimImage

このように、テンポラリの裏画面を用意しておくことによって、
メッセージウィンドウ内に表示したメッセージを削除する際に
MesWinTempBmpを表画面にコピーするだけで済むようになります。

これを踏まえて、実装に入りましょう。
まずはグローバル宣言部で裏画面と、そのサイズの宣言です。

            
implementation

const
  WIN_W : Integer = 640; //背景画像の幅
  WIN_H : Integer = 480; //背景画像の高さ
  CHARA_W : Integer = 350; //立ちキャラ画像の幅
  CHARA_H : Integer = 480; //立ちキャラ画像の高さ
            
            
  MESWIN_H : Integer = 120; //メッセージウィンドウ画像の高さ
            
            
var
  BackBmp : TBitmap; //背景を格納
  CurBack : Integer; //表示中の背景の番号
  CharaBmp : TBitmap; //立ちキャラを格納
  CurChara : Integer; //格納している立ちキャラの番号
  SetChara : Boolean; //立ちキャラを表示しているか
            
            
  MesWinBmp : TBitmap; //メッセージウィンドウ画像を格納
  MesWinTempBmp : TBitmap; //背景にメッセージウィンドウ画像を転送した画像を格納
            

次に、実体の生成・初期化と解放の処理を書きます(リスト5)。

(リスト5)
            
procedure TMainForm.FormCreate(Sender: TObject);
begin
   //変数の初期値を代入
   CurBack := 1;
   CurChara := 1;
   SetChara := False;

   //オブジェクトの実体を生成する
   BackBmp := TBitmap.Create;
   with BackBmp do
   begin
      Width := WIN_W;
      Height := WIN_H;
      PixelFormat := pf24bit;
      HandleType := bmDIB;
      LoadFromFile(Format('..\\..\\data\\bg%.2d.bmp',[CurBack]));
   end;

   CharaBmp := TBitmap.Create;
   with CharaBmp do
   begin
      Width := CHARA_W;
      Height := CHARA_H;
      LoadFromFile(Format('..\\..\\data\\chara%.2d.bmp',[CurChara]));
      Transparent := True;
   end;
            
            

   MesWinBmp := TBitmap.Create;
   with MesWinBmp do
   begin
      Width := WIN_W;
      Height := MESWIN_H;
      LoadFromFile('..\\..\\data\\meswin.bmp');
      Transparent := True;
   end;

   MesWinTempBmp := TBitmap.Create;
   with MesWinTempBmp do
   begin
      Width := WIN_W;
      Height := MESWIN_H;
      PixelFormat := pf24bit;  -----------------------(7)
   end;
            
            

   //表画面に背景を転送
   PrimImage.Picture.Assign(BackBmp);
   //立ちキャラを表示
   DrawChara;
            
            
   //メッセージウィンドウを表示
   DrawMessageWindow;  -------------------------------(8)
            
            
end;

//-------------------------------------------------------

procedure TMainForm.FormDestroy(Sender: TObject);
begin
   //オブジェクトを解放
   BackBmp.Free;
   CharaBmp.Free;
            
            
   MesWinBmp.Free;
   MesWinTempBmp.Free;
            
            
end;
            

(7)のPixelFormatプロパティの設定は、このMesWinTempBmpで使用する画像が
24ビット画像であることを明示しているものです。
次のリスト6の(11)を行うためにここで設定しておきます。

(5)と同様にメッセージウィンドウを表示する手続きDrawMessageWindowを
メンバ関数として宣言し、(8)で呼び出します。
DrawMessageWindowの実体を書きます(リスト6)。

(リスト6)
            
//メッセージウィンドウの描画
procedure TMainForm.DrawMessageWindow;
var
   R : TRect;
   p : PByteArray;
   x,y : Integer;
begin
   //メッセージウィンドウを描画する矩形の設定
   R := Rect(0,WIN_H - MESWIN_H,WIN_W,WIN_H);

   with MesWinTempBmp do
   begin
      //表画面の一部をコピー
      Canvas.CopyRect(Canvas.ClipRect,PrimImage.Canvas,R);  -------(9)
      //メッセージウィンドウ画像を描画
      Canvas.Draw(0,0,MesWinBmp);  --------------------------------(10)
      //メッセージ描画部分を薄暗くする  -------------------------- (11)
      for y := 13 to 107 do                                  |
      begin                                                  |
         p := ScanLine[y];                                   |
         for x := 15*3 to 623*3 - 1 do                       |
            //RGB値を半分に(1ビット右シフト)する           |
            p^[x] := p^[x] shr 1;                            |
      end;  --------------------------------------------------
      //表画面に描画
      PrimImage.Canvas.CopyRect(R,Canvas,Canvas.ClipRect);  -------(12)
   end;
end;
            

上で示した流れと比べながら追っていきましょう。
(9)でまずMesWinTempBmpに表画面のウィンドウ表示領域(下120ピクセル)の画像をコピーします。
その後、(10)でメッセージウィンドウ画像meswin.bmpを格納しているMesWinBmpを
MesWinTempBmp(表画面ではありません!)に描画します。
(11)では、メッセージの表示領域を薄暗くしています。
このメッセージウィンドウ画像を使用した場合、
メッセージの表示領域座標は左上が(15,13)、右下が(623,107)となっています。
ScanLineによって画像の横一列のRGB値が入ったポインタを受け取り、
メッセージ表示領域のRGB値をそれぞれ半分の値にすることによって
この領域を薄暗くしています。
(RGB値が大きいほど明るく、小さいほど暗くなる)
最後に(12)で表画面に転送して、表示させます。

それでは実行してみましょう。
上の流れの最後にあるように、メッセージウィンドウが表示されて
その中が薄暗くなっていますか?


第4回へ
アドベンチャーゲーム設計論トップへ戻る
開発分室へ戻る
トップページへ戻る