我正在使用Embarcadero C ++ Builder(不是工程师,而是工程师)
我发现“睡眠”功能仅在调试模式下对我有效,而在释放模式下不起作用。 我看到StackOverFlow中的引用不是使用Sleep,而是使用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循环中间
这是我的渲染效果:
任何建议,非常感谢。
答案 0 :(得分: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
。如您所见,不需要Sleep
或Delay
,因此不会阻塞执行。
如果渲染不是基于对象的顺序,而是经过某种过滤,则不只是使用要过滤的变量更改render_ix
。这样,您可以将更多变量(体积,质量,位置...)一起嵌套到嵌套的if
语句中。
另一个但非常有用的方案是使用选择。因此,创建对象索引列表以进行渲染...,并仅渲染/突出显示列表中存在的那些对象。这对于鼠标选择和一次使用更多容器的操作非常有用。
答案 1 :(得分: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动画方法来显示结果,但是我的游戏栏过于气质,无法将屏幕动画捕获到视频中。 “ Win G”激活游戏栏无济于事。
感谢雷米(Remy)和斯派克(Spektre)的宝贵建议。