0

我正在使用 Embarcadero C++ Builder(工程师而非程序员)

我发现睡眠功能只在调试模式下对我有用,在发布模式下不起作用。我在 StackOverFlow 中看到引用不使用睡眠,而是使用 TTimer。

我只是希望我的应用程序根据 Sleep(500) 在绘图对象之间暂停几秒钟;在下面的代码中,这样我就可以看到正在绘制的每个对象并可以检查它们是否正确,否则它恰好可以快速检查。

DrawSelectedShape(k,Side,AddOrDeduct,Color); 在下面的代码中,是需要暂停的过程

for (int n=0; n<LiquidLoads->TankBasicData->NoLiquidTypes; ++n){
  for (int m=0; m<LiquidLoads->TankBasicData->NumberOfTanks[n]; ++m)
  {
    for (int l=1; l<LongStrengths->TotalNumberOfParts+1; ++l)
     {
       if (LiquidLoads->TankHeaderArray[n][m]->GhsName == LongStrengths->PartHeader[l]->PartName)
       {

         for (int j=0; j<LongStrengths->PartHeader[l]->NoOfComponents; ++j)
         {
            int k = LongStrengths->PartData[l][j]->ShapeNumber;
            int Side = LongStrengths->PartData[l][j]->Side;
            float AddOrDeduct = LongStrengths->PartData[l][j]->Effectiveness;
            AnsiString Color = LiquidLoads->TankBasicData->LiquidTypeColor[n];
            DrawSelectedShape(k,Side,AddOrDeduct,Color);

            Canvas->TextOut(1200, 300+(n*25),LiquidLoads->TankBasicData->LiquidType[n]);
            Sleep(300);
         }
       break;
       }
   }
}  }

上面的代码在调试模式下完美运行,但在发布模式下,它通过将前几个形状绘制到画布上正常工作,然后你会得到一个旋转的鼠标光标一段时间,然后是一个空白画布。

所以我正在寻找睡眠的替代品。

使用 TTimer 时(没有经验)会使用 OnTimer 事件,并将重复运行的代码放置在与 Timer1 间隔相关的延迟的事件中,这与只是在中间寻找几秒钟的延迟不太一样一个for循环

这就是我的渲染的样子:

动画

任何建议,非常感谢。

4

2 回答 2

0

为了避免 for 循环和 if 语句,这是使用 Sleep 方法暂停循环绘制到画布的过程的一部分,我现在首先必须为 Struct 生成一个渲染序列,然后我可以将其与单个TTimer 中的顺序计数器

如下

//---------------------------------------------------------------------------
void __fastcall TShipGraphic::DrawSelectedTanksBtnClick(TObject *Sender)
{
    GenerateRenderSequence();
    Timer1->Interval = StrToInt(Edit1->Text);
    CloseButton->Enabled = false;
    render_ix=0; //Initialised globally

     Timer1->Enabled = true;

}
//---------------------------------------------------------------------------
void __fastcall TShipGraphic::Timer1Timer(TObject *Sender)
{
 render_ix++;
 Timer1->Interval = StrToInt(Edit1->Text);
 if (render_ix<=TankShapeCounter)
 {
    DrawSelectedComponentShape(render_ix); // render i-th object
    Canvas->Refresh();
 }
 else
 {
   Timer1->Enabled = false;
   CloseButton->Enabled = true;
 }
}
//---------------------------------------------------------------------------
void TShipGraphic::GenerateRenderSequence()
{
   TankShapeCounter = 0;

  for (int n=0; n<LiquidLoads->TankBasicData->NoLiquidTypes; ++n)
  {
    if ((CheckListBox1->Checked[n]) || (CheckListBox1->Checked[LiquidLoads->TankBasicData->NoLiquidTypes]))
    {
      for (int m=0; m<LiquidLoads->TankBasicData->NumberOfTanks[n]; ++m)
      {

        for (int l=1; l<LongStrengths->TotalNumberOfParts+1; ++l)
         {
           if (LiquidLoads->TankHeaderArray[n][m]->GhsName == LongStrengths->PartHeader[l]->PartName)
           {

             for (int j=0; j<LongStrengths->PartHeader[l]->NoOfComponents; ++j)
             {
                ++TankShapeCounter;
                int k = LongStrengths->PartData[l][j]->ShapeNumber;
                int Side = LongStrengths->PartData[l][j]->Side;
                float AddOrDeduct = LongStrengths->PartData[l][j]->Effectiveness;
                AnsiString Color = LiquidLoads->TankBasicData->LiquidTypeColor[n];
                RenderSequence[TankShapeCounter]->ShapeNumber = k;
                RenderSequence[TankShapeCounter]->Side = Side;
                RenderSequence[TankShapeCounter]->AddOrDeduct = AddOrDeduct;
                RenderSequence[TankShapeCounter]->Color = Color;
             }
           break;
           }
         }
      }
    }
  }
}
//---------------------------------------------------------------------------

我想用@Spectre 简洁的动画 gif 方法来展示结果,但是我的 Game Bar 太有气质了,无法将屏幕动画捕捉到视频中。“Win G”激活游戏栏是什么都不做。

感谢 Remy 和 Spektre 的宝贵建议。

于 2018-10-22T12:21:52.743 回答
0

从您发布的视频中可以看出,使用计时器的清晰动画是要走的路...

根据您的描述,您应该ix对船上的每个可见物体都有一些价值。告诉对象的图层或渲染顺序。

因此,为您的渲染代码添加一个render_ix值(全局或您要渲染的表单的成员),然后将您的绘图例程重新编码为:

int render_ix=0; // order/layer number for object to render up to

void draw()
 {
 // here clear&render background
 for (int i=0;i<objects;i++)
  if (object[i].ix<=render_ix)
   object[i].draw(); // render i-th object
 // here render HUD
 }

现在只是在你的计时器中的某个地方,具有所需的时间间隔

void OnTimerAnimation()
 {
 render_ix++;
 if (render_ix>=objects) render_ix=0;
 // here force repaint either by calling Paint, Refresh,Update ... or what ever way you are using
 }

您还可以render_ix通过滚动条或编程方式更改。如您所见,不需要SleepDelay不需要,因此不会阻止执行。

如果您的渲染不是基于对象的顺序,而是通过一些过滤而不是仅仅更改render_ix您正在过滤的变量。这样,您可以将更多变量(Volume、mass、position...)嵌套到嵌套if语句中。

另一个但非常有用的方案是使用选择。因此,创建要渲染的对象索引列表...并仅渲染/突出显示列表中存在的那些。这对于一次使用更多容器进行鼠标选择和操作非常有用。

于 2018-10-19T11:48:44.550 回答