热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一个游戏程序的画面,Delphi5中不闪烁,Delphi6中却闪烁,为什么?

我发现一个奇怪的问题。可以这样来做一个试验:在Delphi5中建立一个工程,先放入两个Image控件,设定Image1.Width600;Image1.Height600;Im
我发现一个奇怪的问题。
可以这样来做一个试验:在Delphi5中建立一个工程,先放入两个Image控件,设定
Image1.Width = 600; Image1.Height = 600; Image2.Width = 50; Image2.Height = 50;
并确定它们的Picture属性,指定两个图片。然后添加一个button,在点击事件中写:
procedure TForm1.Button1Click(Sender: TObject);
var
  X, Y: integer;
begin
  x := Random(600);
  y := Random(600);
  image1.Canvas.CopyRect(Rect(X, Y, X + 50, Y + 50),
    image2.Canvas,
    Rect(0, 0, 50, 50));
end;
分别在Delphi5和Delphi6下面编译这两个程序,我们可以发现,当不停的点击按钮时,
在Delphi6下面,图形不断的闪烁,而在Delphi5下面根本不闪烁。
不知道是为什么?
   
btw: 我在编译鞠大龙的推箱子小游戏时发现这个问题的,大家可以试试,在网上
搜索推箱子,很容易找到源代码,用delphi6一编译,问题就出来了,屏幕不断的闪烁。
而用Delphi5编译后的exe根本不闪烁!

18 个解决方案

#1



打开双缓存模式试试

将做image容器的控件的DoubleBuffered := true;

#2


image属性设置不对,以前我也遇到过的!

#3


我也遇到过。不知道怎么解决

#4


cleverboy(小虫)可不可以详细地说一下????
多谢了!

#5


是的,比如你的IMAGE放在Panel1上面,你可以这样试试


Panel1.DoubleBuffered := true;

#6


2312(007)兄说的是正确的!谢谢!
只是小虫弟说改image的属性倒是不知如何搞。

#7


使用DoubleBuffered,

另外,这个决不比鞠大龙的那个推箱子游戏差:
http://www.tonixsoft.com/index.php?mmenu_id=3&smenu_id=0025
sokoban

#8


好久没用了,可能是属性设置有问题!

#9


大家说说这个是什么原因啊?
我也遇到过

#10


这帖子怎么还没结呀?

楼上的,答案已经个给出了

就是调整 DoubleBuffered

#11


我刚刚试了下,没有发现这样的情况啊!

#12


DoubleBuffered设置为True后,显示速度特慢。应该不是正确答案

#13


把image 放到一个载体上pannel控件上,这样就解决了image在窗体移动时刷新不及时的问题

#14


错了,这种做法再在都不能用了。要获取位图1的内存DC,然后,再将位图2的内存DC合起来再放入内存3的DC,再读出来,也就是上面的双缓冲或多缓冲,具体的做法你可以看看《VC++游戏开发》或《游戏开发概论》

#15


doublebuffer,双缓冲,D5和D6不同,在D6需要设为true

#16


呵呵,推箱子啊,我也写了一个,绝对不闪,谁要?

#17


界面:1个 400 X 400 的panel,一个speedbutton。
源码:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Buttons;

const
  XCount = 20;
  YCount = 20;
  C_SPACE = 0;
  C_WALL = 1;
  C_MAN = 2;
  C_BOX = 3;
  C_POINT = 4; 
  C_ManPoint = C_MAN + C_POINT;
  C_BoxPoint = C_BOX + C_POINT;

type
  TWallImg = class(TImage)
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

  TActImg = class(TImage)
  public
    constructor Create(AOwner: TComponent; cType: Integer); reintroduce; virtual;
    destructor Destroy; override;
  end;

  TForm1 = class(TForm)
    Panel1: TPanel;
    SpeedButton1: TSpeedButton;
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure SpeedButton1Click(Sender: TObject);
  private
    CurMap: String;
    function TurnX(X: Integer): Integer;
    function TurnY(Y: Integer): Integer;
    function TurnNum(Num, Count: Integer): Integer;
    function check(a, b: integer): boolean;
    function checkway(way: integer): boolean;
    function checkwin: BOOLEAN;
    procedure DrawWall;
    procedure DrawAct;
    procedure FreeAll;
    procedure Ini(cMap: String);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Y: array[0..XCount - 1, 0..YCount - 1] of Integer;
  ManX, ManY: Integer;

implementation

{$R *.dfm}

#18


{ TWallImg }

constructor TWallImg.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Picture.Bitmap.LoadFromFile('Wall.bmp');
  Stretch := true;
  Height := 20;
  Width := 20;
end;

destructor TWallImg.Destroy;
begin
  inherited Destroy;
end;

{ TActImg }

constructor TActImg.Create(AOwner: TComponent; cType: Integer);
begin
  inherited Create(AOwner);
  case cType of
    C_MAN, C_ManPoint: Picture.Bitmap.LoadFromFile('People.bmp');
    C_BOX: Picture.Bitmap.LoadFromFile('Box.bmp');
    C_POINT: Picture.Bitmap.LoadFromFile('Target.bmp');
    C_BoxPoint: Picture.Bitmap.LoadFromFile('Box2.bmp');
  end;
  Stretch := true;
  Height := 20;
  Width := 20;
end;

destructor TActImg.Destroy;
begin
  inherited Destroy;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case key of
    37:
      if Checkway(1) then
        begin
          DrawAct;
          manx := TurnX(manx - 1);
        end;
    39:
      if Checkway(2) then
        begin
          DrawAct;
          manx := TurnX(manx + 1);
        end;
    38:
      if Checkway(3) then
        begin
          DrawAct;
          many := TurnY(many - 1);
        end;
    40:
      if Checkway(4) then
        begin
          DrawAct;
          many := TurnY(many + 1);
        end;
  end;
  if checkwin then
    begin
      Showmessage('你赢了');
      self.OnKeyDown := nil;
    end;
end;

function TForm1.check(a, b: integer): boolean;
begin
  result := false;
  case y[TurnX(manx + a), TurnY(many + b)] of
    C_SPACE, C_POINT:
      begin
        result := true;
        y[TurnX(manx + a), TurnY(many + b)] := C_MAN + y[TurnX(manx + a), TurnY(many + b)];
        y[manx, many] := y[manx, many] - C_MAN;
      end;
    C_WALL: result := false;
    C_BOX, C_BoxPoint:
      begin
        if (y[TurnX(manx + 2 * a), TurnY(many + 2 * b)] = C_SPACE)
          or (y[TurnX(manx + 2 * a), TurnY(many + 2 * b)] = C_POINT) then
          begin
            result := true;
            y[TurnX(manx + 2 * a), TurnY(many + 2 * b)] :=
              y[TurnX(manx + 2 * a), TurnY(many + 2 * b)] + C_BOX;
            y[TurnX(manx + a), TurnY(many + b)] :=
              y[TurnX(manx + a), TurnY(many + b)] + C_MAN - C_BOX;
            y[manx, many] := y[manx, many] - C_MAN;
          end
        else
          result := false;
      end;
  end;
end;

function TForm1.checkway(way: integer): boolean;
var
  a, b: integer;
begin
  a := 0;
  b := 0;
  case way of
    1:
      begin
        a := -1;
        b := 0;
      end;
    2:
      begin
        a := 1;
        b := 0;
      end;
    3:
      begin
        a := 0;
        b := -1;
      end;
    4:
      begin
        a := 0;
        b := 1;
      end;
  end;
  result := check(a, b);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
{  CurMap := '1111111111' +
            '1111111111' +
            '1111111111' +
            '1120000111' +
            '1100301411' +
            '1100300011' +
            '1400000011' +
            '1111111111' +
            '1111111111' +
            '1111111111'; }
             
  CurMap := '00000000000000000000' +
            '00000000000000000000' +
            '00001111100000000000' +
            '00001000100000000000' +
            '00001300100000000000' +

            '00111003110000000000' +
            '00100303010000000000' +
            '11101011014001111110' +
            '10001011011111000410' +
            '10303000000000004410' +

            '11111011101211004410' +
            '00001000001111101110' +
            '00001111111000000000' +
            '00000000000000000000' +
            '00000000000000000000' +
            
            '00000000000000000000' +
            '00000000000000000000' +
            '00000000000000000000' +
            '00000000000000000000' +
            '00000000000000000000';
  Ini(CurMap);
end;

function TForm1.checkwin: BOOLEAN;
var
  i, j: Integer;
begin
  for i := 0 to XCount - 1 do
    for j := 0 to YCount - 1 do
      if Y[i, j] = C_BOX then
        begin
          Result := false;
          Exit;
        end
      else
        result := true;
end;

procedure TForm1.DrawWall;
  procedure DrawWallAtPos(X, Y: Integer);
  var
    Wall: TWallImg;
  begin
    Wall := TWallImg.Create(Panel1);
    Wall.Left := X * 20;
    Wall.Top := Y * 20;
    Wall.Parent := Panel1;
  end;

var
  i, j: Integer;  
begin
  for i := 0 to XCount - 1 do
    for j := 0 to YCount - 1 do
      if Y[i, j] = C_WALL then
        begin
          DrawWallAtPos(i, j);
        end;
end;

procedure TForm1.DrawAct;
  procedure DrawActAtPos(X, Y, cType: Integer);
  var
    Act: TActImg;
  begin
    Act := TActImg.Create(Panel1, cType);
    Act.Left := X * 20;
    Act.Top := Y * 20;
    Act.Parent := Panel1;
  end;

var
  i, j: Integer;  
begin
  for i := Panel1.ComponentCount - 1 downto 0 do
    if Panel1.Components[i] is TActImg then
      TActImg(Panel1.Components[i]).free;
  for i := 0 to XCount - 1 do
    for j := 0 to YCount - 1 do
      if (Y[i, j] <> C_SPACE) and (Y[i, j] <> C_WALL) then
        begin
          DrawActAtPos(i, j, Y[i, j]);
        end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FreeAll;
end;

procedure TForm1.FreeAll;
var
  i: Integer;
begin
  for i := Panel1.ComponentCount - 1 downto 0 do
    if Panel1.Components[i] is TImage then
      TImage(Panel1.Components[i]).free;
end;

procedure TForm1.Ini(cMap: String);
var
  i, j: Integer;
begin
  if Length(cMap) <> XCount * YCount then
    begin
      ShowMessage('载入游戏地图失败!');
      Exit;
    end;
  FreeAll;
  for j := 0 to YCount - 1 do
    for i := 0 to XCount - 1 do
      Y[i, j] := StrToInt(cMap[j * XCount + i + 1]);
  ManX := Pos(IntToStr(C_MAN), cMap) mod XCount - 1;
  ManY := Pos(IntToStr(C_MAN), cMap) div XCount;
  DrawWall;
  DrawAct;
  self.OnKeyDown := FormKeyDown;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  Ini(CurMap);
end;

function TForm1.TurnNum(Num, Count: Integer): Integer;
begin
  Result := (Num + Count) Mod Count;
end;

function TForm1.TurnX(X: Integer): Integer;
begin
  Result := TurnNum(X, XCount);
end;

function TForm1.TurnY(Y: Integer): Integer;
begin
  Result := TurnNum(Y, YCount);
end;

end.

推荐阅读
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • Android源码中的Builder模式及其作用
    本文主要解释了什么是Builder模式以及其作用,并结合Android源码来分析Builder模式的实现。Builder模式是将产品的设计、表示和构建进行分离,通过引入建造者角色,简化了构建复杂产品的流程,并且使得产品的构建可以灵活适应变化。使用Builder模式可以解决开发者需要关注产品表示和构建步骤的问题,并且当构建流程发生变化时,无需修改代码即可适配新的构建流程。 ... [详细]
  • 抽空写了一个ICON图标的转换程序
    抽空写了一个ICON图标的转换程序,支持png\jpe\bmp格式到ico的转换。具体的程序就在下面,如果看的人多,过两天再把思路写一下。 ... [详细]
  • unitUnit1;interfaceusesWinapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,Syst ... [详细]
  • C#DataGridView控件中数据导出到Excel方法一:usingSystem;usingSystem.Collections.Generic;usingSys ... [详细]
  • 九、删除用户 并提交代码到git仓库
    (1)弹框询问用户是否删除数据 ... [详细]
  • 有没有一种方法可以在不继承UIAlertController的子类或不涉及UIAlertActions的情况下 ... [详细]
  • C# WPF自定义按钮的方法
    本文介绍了在C# WPF中实现自定义按钮的方法,包括使用图片作为按钮背景、自定义鼠标进入效果、自定义按压效果和自定义禁用效果。通过创建CustomButton.cs类和ButtonStyles.xaml资源文件,设计按钮的Style并添加所需的依赖属性,可以实现自定义按钮的效果。示例代码在ButtonStyles.xaml中给出。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • C#多线程解决界面卡死问题的完美解决方案
    当界面需要在程序运行中不断更新数据时,使用多线程可以解决界面卡死的问题。一个主线程创建界面,使用一个子线程执行程序并更新主界面,可以避免卡死现象。本文分享了一个例子,供大家参考。 ... [详细]
  • Visual C# TabControl中TabPage分离成若干个Form的小办法
    写Visual的同学们都会用到这个TabControl的控件,然后会分好几页的TabPage,每页都有很多控件和业务逻辑,但是每页的关系也 ... [详细]
  • 第一步:PyQt4Designer设计程序界面该部分设计类同VisvalStudio内的设计,改下各部件的objectName!设计 ... [详细]
  • VS2010MFC(对话框:为对话框添加控件)
    转自:http:www.jizhuomi.comsoftware151.html上一讲创建了一个名为“Addition”的工程,目的是生成一个实现加法运 ... [详细]
  • 转载:MFC 获得各类指针、句柄的方法
    2019独角兽企业重金招聘Python工程师标准转载:最近有些人在问MFC编程一些要点,有一些句柄的获取、指针的获取是 ... [详细]
author-avatar
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有