第4回:画面表示(3) メッセージの表示



画面表示の最後として、メッセージの表示を行います。

メッセージは、当然のことながら文字列です。
文字列は、文字列リストを格納できるオブジェクトTStringListに格納します。
TStringListに格納した文字列は、配列を参照するかのように、
一行ごとに中の文字列を取得できます。
取得した文字列を表示するには、立ちキャラ表示と同様にTBitmapを使用します。
TBitmapに文字列を画像として書き、表画面に透過転送して表示します。

グローバル変数宣言部でTStringListオブジェクトAllTextと、
TBitmapオブジェクトTextBmpを宣言します。
また、文字列リストAllTextのどのメッセージを取得するかを示す
変数TextPointと、最後に表示した行番号を格納する変数MToを宣言します。

            
implementation

const
  WIN_W : Integer = 640; //背景画像の幅
  WIN_H : Integer = 480; //背景画像の高さ
  CHARA_W : Integer = 350; //立ちキャラ画像の幅
  CHARA_H : Integer = 480; //立ちキャラ画像の高さ
  MESWIN_H : Integer = 120; //メッセージウィンドウ画像の高さ
            
            
  TEXT_W : Integer = 570; //メッセージ画像の幅
  TEXT_H : Integer = 20; //メッセージ画像の高さ
  TEXT_X : Integer = 30; //メッセージ画像を描画するX座標
  TEXT_Y : Integer = 376; //メッセージ画像を描画するY座標
  TEXT_SEP : Integer = 23; //メッセージ画像の行間
            
            
var
  BackBmp : TBitmap; //背景を格納
  CurBack : Integer; //表示中の背景の番号
  CharaBmp : TBitmap; //立ちキャラを格納
  CurChara : Integer; //表示中の立ちキャラの番号
  SetChara : Boolean; //立ちキャラを表示しているか
  MesWinBmp : TBitmap; //メッセージウィンドウ画像を格納
  MesWinTempBmp : TBitmap; //背景にメッセージウィンドウ画像を転送した画像を格納
            
            
  TextBmp : TBitmap; //メッセージ表示に使用
  AllText : TStringList; //メッセージを格納
  TextPoint : Integer; //表示するメッセージ番号を指す
  MTo : Integer; //最後に表示した行の番号
            

オブジェクトの実体生成とプロパティの設定をFormCreateで行い、
解放をFormDestroyで行います(リスト7)。

(リスト7)
            
procedure TMainForm.FormCreate(Sender: TObject);
begin
   //変数の初期値を代入
   TextPoint := 0;
   CurBack := 1;
   SetChara := False;
            
            
   TextPoint := 0;
            
            
   //オブジェクトの実体を生成する
   BackBmp := TBitmap.Create;

   (中略)

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

            
            
   TextBmp := TBitmap.Create;  -----------------------------(13)
   with TextBmp do
   begin
      Width := TEXT_W;
      Height := TEXT_H;
      Canvas.Font.Size := 15;
      Canvas.Brush.Color := clBlack; //塗りつぶし色は黒
      Canvas.Font.Color := clWhite; //文字の色は白
      Transparent := True;
   end;

   AllText := TStringList.Create;  -------------------------(14)
   AllText.LoadFromFile('..\\..\\data\\scenario.txt');
            
            

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

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

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

メッセージ表示に使用するTBitmapオブジェクトTextBmpの設定を(13)で行っています。
TextBmpには、メッセージを1行ずつ表画面に透過転送するという役割を持たせます。
(14)では、実体を生成したAllTextにシナリオのファイル
scenario.txtを読み込ませています。
このテキストの中をちょっとだけ読んでみましょう。
「1: 」などの表記は便宜上付けた行番号です。実際のテキストには書かれていません。

            
 1: 1
 2: 【葵依】
 3: ズイブン遅くなっちゃったね。
 4: 
 5: 
 6: 2
 7: 【上春】
 8: そうだな。
 9: 初日屋まで送っていこうか?
10: 
11: 3
12: 【葵依】
13: それよりお兄ちゃんの部屋に行きたいな。
14: 
15: 
(以下略)
            

シナリオは、一度に表示する量(これを1ページと言うことにします)が5行からなり、その構成は
1行目:ページ番号およびスクリプト
2〜5行目:表示するメッセージ
となっています。
ページ番号は、変数TextPointで参照し、
例えばTextPoint=3の時は3ページ目のメッセージを表示するようにします。
スクリプトとは、「CDの何トラック目を再生する」や
「何番の背景を表示する」といった命令文を指します。
スクリプト部分の説明は後に回すとして、メッセージの表示方法の説明に戻ります。

(15)で手続きOneStepを呼んでいます。
手続きOneStepでは、イベント処理の章で大きく書き足すことになりますが、
現在のところはメッセージポインタであるTextPointを1増加し、
メッセージを表示する手続きPutTextを呼んでいるだけです。
手続きOneStep及びPutTextをメンバ関数の宣言をして、実体を書いていきましょう(リスト8)。

(リスト8)
            
procedure TMainForm.OneStep;
begin
   //最後のページまで進んでいなければ
   if TextPoint < AllText.Count div 5 then
   begin
      //ページ番号を1増やす
      Inc(TextPoint);
      //TextPointページのメッセージを表示
      PutText(TextPoint);
   end;
end;

//メッセージを表示
procedure TMainForm.PutText(tp : Integer);
var
   i : Integer;
   str : string;
begin
   //既に書かれているメッセージを消去
   PrimImage.Canvas.CopyRect(Rect(0, WIN_H - MESWIN_H, WIN_W, WIN_H),
                             MesWinTempBmp.Canvas,
                             MesWinTempBmp.Canvas.ClipRect);  ----------(16)
   with TextBmp.Canvas do
   begin
      //1ページのメッセージ各行について
      for i := 0 to 3 do
      begin
         str := AllText[tp*5-4+i];  ------------------------------------(17)
         //その行が空でなければ表示する
         if str <> '' then
         begin
            //TextBmpを黒で塗りつぶす
            FillRect(ClipRect);
            //メッセージをTextBmpに書き出す
            TextOut(0,0,str);
            //表画面に転送
            PrimImage.Canvas.Draw(TEXT_X,TEXT_Y+TEXT_SEP*i,TextBmp);
            //表示した行を代入
            MTo := i;  -------------------------------------------------(18)
         end;
      end;
   end;
end;
            

(16)ではMesWinTempBmpを表画面に転送することによって
既に表示されているメッセージを消去しています。
(17)では指定されたページの各行について、1行ずつメッセージを取得して
文字列変数strに代入しています。
その文字列が空でなければ、TextBmpのCanvas.TextOutメソッドを用いて
TextBmpに文字列を書き出し、表画面に透過して転送します。
表画面に書き出す位置は、TEXT_XとTEXT_Yおよび行間を意味するTEXT_SEPから決定します。
(18)で、表示した最後の行を変数MToに代入します。
この変数MToは、イベント処理の章で使用します。

それでは実行してみましょう。
第2回の図2-1と同じになっていれば、これで画面表示のプログラムは一段落です。


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