imageコンポーネントで画像を変化させる際のちらつきを無くすには?

解決


tarodj  2002-01-23 05:40:28  No: 481  IP: [192.*.*.*]

bmpファイルを読み込んみタイマーで変化させゲーム中の動作(歩く、走る)など
処理してるのですが、どうもちらつきます。コンピュータの性能の限界でしょうか?もし少しでも改善できるのならば、ご教授下さい。

編集    削除
にしの  2002-01-23 09:38:34  No: 482  IP: [192.*.*.*]

> コンピュータの性能の限界でしょうか?
スペックを示されていないので、性能の限界かどうかはわかりません。
お使いのマシンで、(自作でない)ゲームなどの描画がちらつくようであれば、コンピュータの性能の限界ですね。

簡単なのは、ダブルバッファリングです。2つのキャンバスを用意して、見えないキャンバスに描画したあと、見えるキャンバスに一気にコピーするというものです。
ほかは、WM_ERASEBKGNDメッセージで処理させないようにするなどでしょうか。

どの程度、改善努力をしたかによって、次にできうることが変わります。
上の手法を既に使っているならば、あとは水平帰線割り込みですね。
Windowsではできないと思っていましたが、直接ポートを見ることによってできるみたいです。
# 未確認です。Windowsのすべてのバージョンで使えるかどうかも未確認です

編集    削除
便乗くん  2002-01-23 12:30:00  No: 483  IP: [192.*.*.*]

またまた便乗ですが、(^^ゞ 同様にチラツキに困っています。

フォーム全体にImage1を置いて、それに背景画像を読み込み、
別に作成した Bitmap1 にも同じ大きさの背景画像を入れておきます。
そして、ImageList1 に小さなコマ画像を入れます。

以下のようなサンプルコードで、マウスのドラッグによりコマ画像を動かすと、
Delphi2.0 でコンパイルして実行した場合は、全く画面のチラツキがありません。
でも、Delphi6 でコンパイルして実行すると背景がひどくチラツキます。

TImage コンポーネントの仕様が変更されたとしか思えないのですが、
Delphi6 でチラツキをなくす方法はないでしょうか。

------------------------------------------------
const
KOMA_WW = 40;  // コマ画像の幅
KOMA_HH = 48;  // コマ画像高さ

var
ShowX, ShowY : Integer;  // コマ表示位置
preMX, preMY : Integer;
DefX,  DefY  : Integer;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;  Shift: TShiftState; X, Y: Integer);
begin
  DefX := X - ShowX;  //マウスX座標とコマ左上X座標との差分
  DefY := Y - ShowY;  //マウスY座標とコマ左上Y座標との差分
  preMX := X;
  preMY := Y;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: shiftState; X,Y: Integer);
begin
  Restore_BackGround(preMX, preMY);  // 前の位置のコマを消す
  ImageList1.Draw(Image1.Canvas, X - DefX, Y - DefY, 0); // コマを描く
  preMX := X;
  preMY := Y;
end;

// Bitmap1の背景(一部分)をImage1にコピー
procedure TForm1.Restore_BackGround(mx, my : Integer);
var
  px, py : Integer;
  srcRect, dstRect : TRect;
begin
  px := mx - DefX;  // コマ左上のX座標
  py := my - DefY;  // コマ左上のY座標

  srcRect := Rect(px, py, px + KOMA_WW, py + KOMA_HH);
  dstRect := Rect(px, py, px + KOMA_WW, py + KOMA_HH);
  Image1.Canvas.CopyRect(dstRect, Bitmap1.Canvas, srcRect);
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  ShowX := X - DefX;
  ShowY := Y - DefY;
end;
----------------------------------------------------

編集    削除
kazu  2002-01-23 18:13:52  No: 484  IP: [192.*.*.*]

Form1.DoubleBuffered := True;
をTForm1.OnCreateにでも書けば、ちらつきがある程度押えられませんか?

でも、自分で作るとしたら「にしの」氏のやり方ですが...

編集    削除
tarodj  2002-01-24 07:00:33  No: 485  IP: [192.*.*.*]

Form1.DoubleBuffered := True;
を入力したら気にならない程度のちらつきにおさまりました。
にしの氏、kazu氏に深く感謝します。

編集    削除
便乗くん  2002-01-24 12:17:39  No: 486  IP: [192.*.*.*]

回答ありがとうございました。
>Form1.DoubleBuffered := True;
これを追加すれば確かにチラツキがおさえられますが…。
でも、TImageがバッファ機能を持っているのに、もうひとつのバッファを追加する
なんてことは kazzさんと同様に避けたい手段です。
Delphi6で何故TImageのバッファ機能が働かないのか不思議なんですが…

で、にしのさんの
>ほかは、WM_ERASEBKGNDメッセージで処理させないようにするなどでしょうか。
の方法を試してみました。
最初は TImageのWM_ERASEBKGNDメッセージを捕らえようとしてみたのですが、
やり方が分からず(@_@)、試しにFormのWM_ERASEBKGNDメッセージを無視させたら
なんとチラツキが無くなりました。(^^)
チラツキの原因は TImageではなく、Formにあったということでしょうか。
直接ポートを見る方法もぜひ知りたいところですが…

編集    削除
にしの  2002-01-24 18:22:18  No: 487  IP: [192.*.*.*]

http://www2.ten.ne.jp/treebbs2/log/14914.htm

ここに書いてありました。
もし試されるなら、自己責任の上でお願いします。
# ポート番号など、間違えないように気をつけてください。

編集    削除
便乗くん  2002-01-26 10:37:22  No: 488  IP: [192.*.*.*]

ありがとうございました。
直接ポートを見て垂直帰線期間に描画するようにしてみましたが、
垂直帰線期間内に描画処理が終わらないような遅いマシンでは
この方法はダメですね。(^^;; (一部チラツキが残ります)

編集    削除