第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)で表画面に転送して、表示させます。
それでは実行してみましょう。
上の流れの最後にあるように、メッセージウィンドウが表示されて
その中が薄暗くなっていますか?