怎样实现快速动画,并且图象不闪烁(50分)

  • 主题发起人 主题发起人 孟庭苇
  • 开始时间 开始时间
单从你的问题而言,可以用OPENGL来做,肯定不会有闪烁。但是我不知道这是否
合乎你的要求。我现在正在用OPENGL,动画还算不错。
 
A、在内存中保存下一个位置的背景两份拷贝(理论上越小越好);
B、在在上一步骤中保存的一幅内绘动画;
C、把前一次保存的背景拷回原位置(相当于把动画抹掉);
D、把绘好的动画拷到下一个位置;
我已试过N次了效果很不错的。
 
孟庭苇?
可以设置一下属性。
 
有一个怪现象:将windows设成大字体有时会闪烁!
 
这个东西确实好的很,没有闪烁了。
{------------------------关键之处-----------------------}
procedure TFlickerFreePaintBox.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
Message.Result := 1;
end;

windows message的工作原理是什么呢?
这个message 有什么意义呢?

 
我在前面说过的办法不行么?但我一直应用的很好。
闪烁的出现,主要的原因在于在刷新的过程过长(也就是抹掉原图与完成新图所需时间过长),消除闪烁,只需缩短时间,方法无非是:
A、尽可能小的图象;
B、使用更底层的工具,象TPaintBox就比TImage快几个数量级;
B、在绘图前先保存下一个位置的背景,抹掉时只需拷贝回来;
C、绘图时不是直接绘制,而是先在内存中绘制完成后再拷贝过去;
D、为缩短抹掉与绘图完成之间的时间,应注意顺序:
a、拷贝整个背景图->MemoryBitmap0;
b、拷贝下位置的背景->MemoryBitmap1;
c、在MemoryBitmap1中绘制完成所需图象;
d、把前一次保存的背景MemoryBitmap0拷贝回去(抹掉);
e、把绘制好的图象MemoryBitmap1拷到下一位置;
f、如果需要,转到步骤b再来;
注:在步骤a中拷贝整个背景是可行的,但并非最好的(但比较简单些,如果背景不是很大,这还可以),事实上,你可以只拷贝下一位置的背景便可,也就是需要三个位图,一个用于保存当前位置的背景,一个保存下一位置的背景,另一个先存有下一位置的背景再用于绘制。这对于背景较大的情形下好一些,但控制复杂一点点。
以上办法本人已应用于N(N>=32)次了,一直感觉不错。

 
喂!孟田尾。
下面是我用一个星期搞的类,它能够自动生成,还有 moveto/setposition等功能。
如果要快速移动的话,只要改变sleep中的参数,而且还没有闪烁感。
 给我分吧,thank you.
unit TcarUnit;

interface
uses
Windows,SysUtils,Classes,Graphics,dialogs,Controls,Forms,Extctrls;


Type
TCar=class(TBitmap)
private
FPos:TPoint;
FPortTime:integer;
Findex:integer;
//procedure cartimertimer(sender:Tobject);
published
property index:integer read findex write findex;
property Pos:Tpoint read Fpos write Fpos;
property PortTime:integer read FportTime write FPortTime;
Public
constructor Create;override;
Destructor Destroy;override;
procedure MoveTo( Form1:TForm;x,y:integer);
procedure SetPosition(Form1:Tform;x,y:integer);
end;
implementation
constructor TCar.Create ;
begin
inherited create;
pos:=point(10,100);
height:=20;
width:=20;
porttime:=100;

end;
destructor Tcar.Destroy ;
begin
inherited destroy;
end;
procedure TCar.MoveTo( Form1:Tform;x,y:integer);
var


m,n,i,dest:integer;
begin
dest:=trunc(sqrt(sqr(x-pos.x)+sqr(y-pos.y)));
sleep(20);
form1.canvas.draw(pos.x,pos.y,self);

for i:=1 to dest do
begin

m:=trunc(pos.x+i*(x-pos.x)/dest);
n:= trunc(pos.y+i*(y-pos.y)/dest);
sleep(5);
form1.canvas.draw(m,n,self);

form1.Canvas.Pen.Color :=form1.Color ;
with form1.canvas do
begin
if(pos.y<y)and(pos.x=x) then
begin
moveto(m,n-1);
lineto(m+width,n-1);
end;
if(pos.y>y)and(pos.x=x) then
begin
moveto(m,n+height+1);
lineto(m+width,n+height+1);
end;
if(pos.x<x)and (pos.y=y)then
begin
moveto(m-1,n);
lineto(m-1,n+height+1);
end;
if(pos.x>x)and(pos.y=y)then
begin
moveto(m+width,n);
lineto(m+width,n+height+1);
end;
if(pos.x>x)and(pos.y>y) then
begin
moveto(m,n+height);
lineto(m+width,n+height);
lineto(m+width,n);
end;
if(pos.x<x)and(pos.y<y) then
begin
moveto(m-1,n+height-1);
lineto(m-1,n-1);
lineto(m+width,n-1);
end;
if(pos.x<x)and(pos.y>y) then
begin
moveto(m,n);
lineto(m,n+height);
lineto(m+width,n+height);
end;
if(pos.x>x)and(pos.y<y) then
begin
moveto(m,n);
lineto(m+width,n);
lineto(m+width,n+height);
end;
end;

end;
form1.canvas.CopyMode :=cmsrccopy;
pos:=point(x,y);
end;
Procedure TCar.SetPosition (Form1:TForm;x,y:integer);
begin
form1.canvas.Brush.Color :=form1.color;
Form1.canvas.fillrec(rect(pos.x,pos.y,pos.x+width,pos.y+height));
pos:=point(x,y);
form1.canvas.draw(x,y,self);
end;



end.
 
接受答案了.
 

Similar threads

回复
0
查看
690
不得闲
回复
0
查看
978
不得闲
回复
0
查看
863
不得闲
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部