Estoy usando Embarcadero C ++ Builder (ingeniero, no programador)

Encuentro que la función de suspensión solo me funciona en el modo de depuración y no en el modo de liberación. Veo referencias en StackOverFlow para no usar Sleep, y más bien para usar TTimer.

Simplemente quiero que mi aplicación se detenga durante unos segundos entre los objetos de dibujo según Sleep (500); en el código a continuación, para que pueda ver cada objeto que se dibuja y pueda verificar que sean correctos, de lo contrario, es rápido para verificar.

DrawSelectedShape (k, Side, AddOrDeduct, Color); en el siguiente código, es el proceso que necesita pausar

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;
       }
   }
}  }

El código anterior funciona perfectamente en el modo de depuración, pero en el modo de lanzamiento, funciona bien a través de las primeras formas que se dibujan en el lienzo, luego obtiene un cursor del mouse de rueda giratoria por un tiempo seguido de un lienzo en blanco.

Por eso estoy buscando una alternativa al sueño.

Cuando se usa un TTimer (sin experiencia), uno usaría el evento OnTimer y colocaría el código que se ejecuta repetidamente en el evento con un retraso relacionado con el intervalo Timer1, que no es lo mismo que buscar un retraso de unos segundos en el medio de un bucle for

Así es como se ve mi renderizado:

animation

Cualquier consejo, más apreciada.

0
BarryK 15 oct. 2018 a las 19:01

2 respuestas

La mejor respuesta

Bueno, desde el video que publicaste, su animación clara usando el temporizador es el camino a seguir ...

A partir de su descripción, debe tener algún valor ix para cada objeto visible en su barco. Indicar la capa o el orden de renderizado del objeto.

Así que agregue un valor render_ix a su código de renderizado (ya sea global o un miembro del formulario donde está renderizando) luego vuelva a codificar su rutina de dibujo a esto:

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
 }

Ahora solo en algún lugar de su temporizador con el intervalo deseado

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
 }

También puede cambiar render_ix mediante la barra de desplazamiento o mediante programación. Como puede ver, no se necesita Sleep o Delay, por lo tanto, no se necesita bloqueo de ejecución.

Si su renderizado no se basa en el orden de los objetos, sino más bien por algún filtrado, simplemente cambie render_ix con la variable que está filtrando. De esta manera, puede anidar más variables juntas (volumen, masa, posición ...) en declaraciones if anidadas.

Otro esquema muy útil es usar selecciones. Así que cree una lista de índices de objetos para renderizar ... y renderice / resalte solo aquellos que están presentes en la lista. Eso es muy útil para las selecciones del mouse y la operación con más contenedores a la vez.

0
Spektre 19 oct. 2018 a las 11:48

Para evitar los bucles for y las declaraciones if, que era parte del proceso de dibujar en el lienzo utilizando el método Sleep para pausar los bucles, ahora primero tenía que generar una secuencia de renderizado en una Struct, que luego podía usar con un solo contador secuencial en TTimer

Como abajo

//---------------------------------------------------------------------------
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;
           }
         }
      }
    }
  }
}
//---------------------------------------------------------------------------

Quería usar el elegante método de gif animados de @ Spectre para mostrar el resultado, pero mi barra de juegos es demasiado temperamental para capturar la animación de la pantalla en un video. "Win G" para activar la barra de juegos no hace nada.

Gracias a Remy y Spektre por los valiosos consejos.

0
BarryK 22 oct. 2018 a las 12:21