Author Topic: Slow Drawing, how can I improve it  (Read 994 times)

Dualnames

  • AGS Baker
  • Pretty Badass
    • Dualnames worked on one or more games that won an AGS Award!
    •  
    • Dualnames worked on one or more games that was nominated for an AGS Award!
Slow Drawing, how can I improve it
« on: 10 Feb 2019, 14:26 »
This basically creates a circle and saves each frame on a Dynamic Sprite array (size of 20).
I've noticed that this takes 2-4 seconds to execute, and the whole issue stands (i've commented parts of the code etc) inside the two while loops, is there a way I can make this faster/better?



Code: Adventure Game Studio
  1.  
  2. //CODE IS EXECUTED TILL 20 Dynamic Sprite FRAMES ARE CREATED.
  3.  
  4.   waveFrames[waveFrameC]=DynamicSprite.CreateFromExistingSprite(waveFrames[0].Graphic, true);//waveFrameC
  5.   DrawingSurface*area = waveFrames[waveFrameC].GetDrawingSurface();
  6.   DrawingSurface*refarea = waveFrames[0].GetDrawingSurface();//waveFrameC-1
  7.  
  8.       float Size=6.0;//2.0;
  9.       float IncX=2.6;
  10.       int CircleSize=((wvc+1)-waveFrameC);
  11.       int incBy=waveFrameC*FloatToInt(Size, eRoundNearest);//*6;
  12.      
  13.       int incByx=FloatToInt(IntToFloat(incBy)*IncX, eRoundNearest);
  14.      
  15.      
  16.       int CentralX=cEgo.x;
  17.       int CentralY=cEgo.y-150;
  18.      
  19.       int x=CentralX+(incByx);
  20.       int x2=CentralX-(incByx);
  21.      
  22.       int y=CentralY+(incBy);
  23.       int y2=CentralY-(incBy);//180-(incBy);
  24.      
  25.       int d=x2;
  26.       int d1=0;
  27.       int f=y2;
  28.       int f1=0;
  29.      
  30.      
  31.       float difX;
  32.       float difY;
  33.       float sum;
  34.       float distance;        
  35.       int checkDist;
  36.      
  37.       float gx=IntToFloat(waveFrameC)*Size*IncX;
  38.       int getXv=FloatToInt(gx, eRoundNearest);
  39.       int getX=CentralX-getXv;
  40.       int getY=CentralY-(waveFrameC*6);
  41.      
  42.       while (d < x && CircleSize>0)//while
  43.       {
  44.         f=y2;
  45.         f1=0;
  46.         while (f < y)
  47.         {
  48.           //CALCULATE DISTANCE BETWEEN TWO POINTS
  49.          
  50.           difX = IntToFloat(CentralX) - IntToFloat(d);
  51.           difY = IntToFloat(CentralY) - IntToFloat(f);
  52.           difX = Maths.RaiseToPower(difX, 2.0);
  53.           difY = Maths.RaiseToPower(difY, 2.0);
  54.           sum = difX+difY;
  55.           distance = Maths.Sqrt(sum);        
  56.           checkDist = FloatToInt(distance, eRoundNearest);
  57.          
  58.           if (checkDist<= incBy && checkDist>incBy-CircleSize)
  59.           {            
  60.             area.DrawingColor=refarea.GetPixel(getX+d1, getY + (f1-1));            
  61.             area.DrawPixel(d, f);
  62.           }
  63.          
  64.           f++;
  65.           f1++;
  66.         }
  67.         d1++;
  68.         d++;
  69.       }    
  70.  
  71.  
  72.   area.Release();
  73.   refarea.Release();
  74.   waveFrameC++;
  75.  
  76.  
  77. }
No more military army stuff. I'm alive and back.

Snarky

  • Global Moderator
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #1 on: 10 Feb 2019, 15:04 »
A common trick is to skip the square root and instead compare the squared distance to the square of the threshold(s).

Also, you don't need to do the difX/Y calculations as floats, do you?

Another approach might be to just use DrawingSurface.DrawCircle() and DynamicSprite.CopyTransparencyMask() to handle the masking, instead of drawing it manually. I'm not sure whether it's quicker, but it might be worth a try.
« Last Edit: 10 Feb 2019, 15:10 by Snarky »

Dualnames

  • AGS Baker
  • Pretty Badass
    • Dualnames worked on one or more games that won an AGS Award!
    •  
    • Dualnames worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #2 on: 10 Feb 2019, 15:06 »
The issue doesn't stand on the calculations, albeit those can be improved, the issue lies on the two nested while loops

Code: Adventure Game Studio
  1. while (d < x && CircleSize>0)
  2. {
  3.  f=y2;
  4.         f1=0;
  5.         while (f < y)
  6.         {        
  7.           f++;
  8.           f1++;
  9.         }
  10.         d1++;
  11.         d++;
  12.       }    
  13.  

Even like this, no drawing whatsoever, the frame rate drops to 10 for a solid 2 seconds.
No more military army stuff. I'm alive and back.

Snarky

  • Global Moderator
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #3 on: 10 Feb 2019, 15:16 »
Well, have you calculated or checked how many loops that works out to be? Trying to follow your code, it appears to depend on the player x/y position.

Dualnames

  • AGS Baker
  • Pretty Badass
    • Dualnames worked on one or more games that won an AGS Award!
    •  
    • Dualnames worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #4 on: 10 Feb 2019, 15:42 »
It takes about 3 seconds to finish executing the code, around 120-150 loops. I did your adjustments, but same problem, I'm afraid.
« Last Edit: 10 Feb 2019, 15:50 by Dualnames »
No more military army stuff. I'm alive and back.

Snarky

  • Global Moderator
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #5 on: 10 Feb 2019, 16:37 »
Even like this, no drawing whatsoever, the frame rate drops to 10 for a solid 2 seconds.

Well, you're a very good coder (better than I am, for sure), so you don't need me to tell you that the AGS framerate isn't gonna drop to 10 fps just because you're counting to 150 each game loop.

Which means that something is off in your analysis. Either you're counting wrong and it's way more loops than that (150 inside each loop, maybe?), or the main source of the slowdown is elsewhere.

Dualnames

  • AGS Baker
  • Pretty Badass
    • Dualnames worked on one or more games that won an AGS Award!
    •  
    • Dualnames worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #6 on: 10 Feb 2019, 16:38 »
I've noticed i was drawing a smaller circle than a rectangle, so now frames are at 29. 11 fps droprate.
No more military army stuff. I'm alive and back.

Jack

  • Think deviant
    • I can help with AGS tutoring
    • I can help with scripting
    • I can help with story design
    • Jack worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #7 on: 10 Feb 2019, 21:23 »
Unless it's changed recently, pixel operations are too slow in AGS to be used outside of AGI resolutions.

Re: Slow Drawing, how can I improve it
« Reply #8 on: 10 Feb 2019, 21:25 »
Unless it's changed recently, pixel operations are too slow in AGS to be used outside of AGI resolutions.

I'd say it's definitely not something you'd like to do every game tick.



The issue doesn't stand on the calculations, albeit those can be improved, the issue lies on the two nested while loops
<...>
Even like this, no drawing whatsoever, the frame rate drops to 10 for a solid 2 seconds.

In the end was this confirmed or something else is causing slowdowns?
Could you post the newer code after changes made by Snarky's advice?


Also, why are you writing your own circle drawing instead of using DrawCircle? It seems like you need to combine certain images?. TBH I am too tired right now to understand what the code is doing without comments...
« Last Edit: 10 Feb 2019, 21:31 by Crimson Wizard »

Snarky

  • Global Moderator
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #9 on: 10 Feb 2019, 21:47 »
If I understand the code correctly, it draws a sprite that's a copy of some given area, except that in a ring between an outer circle and an inner circle, the coordinates are offset somehow (by a fixed amount, it seems). The size of the circles depends on a formula that uses the position of the player as well as the index of the sprite in an array, but working out the details without seeing it in action is beyond me. The excerpt we're seeing draws a single frame, it presumably exists within a bigger loop.

My interpretation is that it's meant to draw some sort of animated bubbles (or similar).

Dualnames

  • AGS Baker
  • Pretty Badass
    • Dualnames worked on one or more games that won an AGS Award!
    •  
    • Dualnames worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #10 on: 10 Feb 2019, 22:50 »
This is what it's supposed to be doing


I altered the code to make it run to 40 fps or so and made the effect a bit more subtle.

&feature=youtu.be

Ignore the 2 characters, there are still WIP parts of this.
But you can see the frame drop is non existent.
No more military army stuff. I'm alive and back.

Dualnames

  • AGS Baker
  • Pretty Badass
    • Dualnames worked on one or more games that won an AGS Award!
    •  
    • Dualnames worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #11 on: 10 Feb 2019, 22:55 »
Code: Adventure Game Studio
  1.  
  2. int i=0;
  3. while (i <20)
  4. {
  5. while (d < x && CircleSize>0)
  6. {
  7.  f=y2;
  8.         f1=0;
  9.         while (f < y)
  10.         {        
  11.           f++;
  12.           f1++;
  13.         }
  14.         d1++;
  15.         d++;
  16.       }    
  17. i++;
  18. }
  19.  
  20.  

My main thing, is that the issues within AGS's inability to perform complex drawing stuff in real-time, isn't on the drawing functions. A big while like the one above, seems to be the problem in most cases. Like for example doing

Code: Adventure Game Studio
  1.  
  2. int x=0;
  3. while (x < width)//Width being 640 or 320 or whatever
  4. {
  5. int y=0;
  6. while (y < height)//same as above
  7. {
  8. y++;
  9. }
  10. x++;
  11. }
  12.  
  13.  

This loop without anything inside the while conditions, just as is, will cause framerate drop. I'm not sure if that's ameniable/fixable in any way, but I think it would solve a lot of issues. I wanted to use LUA for AGS but it's very risky given the state of that plugin. Regardless, I appreciate your work and I love you super hardcore <3.
« Last Edit: 10 Feb 2019, 22:58 by Dualnames »
No more military army stuff. I'm alive and back.

Jack

  • Think deviant
    • I can help with AGS tutoring
    • I can help with scripting
    • I can help with story design
    • Jack worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #12 on: 10 Feb 2019, 22:56 »
Very cool.

Gurok

  • Rottwheelers
  • When life hands you lemons, combine them with the mop
    • I can help with AGS tutoring
    • Best Innovation Award Winner 2016, for improving and extending the AGS scripting language
    • I can help with proof reading
    • I can help with scripting
    • Gurok worked on one or more games that won an AGS Award!
    •  
    • Gurok worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #13 on: 12 Feb 2019, 00:41 »
Jack suggested lowering the resolution on IRC. Another way to control the number of iterations would be to draw the radius of the circle at various angles like a bunch of tiny sectors instead of checking all possible x/y values for the ones that lie in the circle.

Re: Slow Drawing, how can I improve it
« Reply #14 on: 15 Feb 2019, 00:49 »
Just wanted to add that this is a very cool effect!

One way I can see it be emulated is creating a circle with the desired alpha for transitions and stuff in a bigger size, then resizing it, creating a new sprite in a square area from the background, copying the prepared circle alpha on this square area you just got from the background, and do another resize at a slightly bigger size. It's a bit tricky but would avoid the while and could possibly run with no frame drops - need to test though.

Kweepa

  • Mutated Guano Deviser
    • Best Innovation Award Winner 2009, for his modules and plugins
    • Kweepa worked on one or more games that won an AGS Award!
    •  
    • Kweepa worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #15 on: 16 Feb 2019, 00:51 »
It looks like you are modifying a ring about 150-200 pixels in diameter, so writing maybe 14000 pixels.
I seem to remember AGS was capable of updating 160x100=16000 pixels at about 20 FPS back in the day, so it should be able to manage 40 FPS now.
To ensure you are looping through the minimum number of iterations, I would work per scan line, and calculate the left and right extent of the circle, then decide if you are in a section with an inner unmodified part, and skip over the unmodified pixels, something like this:

// for a ring with small radius r and large radius R
for (y = (centerY - R) to (centerY + R))
   h = abs(y - centerY)
   halfOuterWidth = sqrt(R*R - h * h)
   if (h < r)
      halfInnerWidth = sqrt(r * r - h * h)
      // modify pixels from centerX-halfOuterWidth to centerX-halfInnerWidth and from centerX+halfInnerWidth to centerX+halfOuterWidth
   else
      // modify pixels from centerX-halfOuterWidth to centerX+halfOuterWidth
Still waiting for Purity of the Surf II

Snarky

  • Global Moderator
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #16 on: 16 Feb 2019, 06:52 »
I altered the code to make it run to 40 fps or so

I'd be interested to hear what you did to make that happen.

// for a ring with small radius r and large radius R
for (y = (centerY - R) to (centerY + R))

You don't need to run through the whole way from the top to bottom of the circle, because of symmetry; only the top half, then do the same operations except with the signs changed.

Kweepa

  • Mutated Guano Deviser
    • Best Innovation Award Winner 2009, for his modules and plugins
    • Kweepa worked on one or more games that won an AGS Award!
    •  
    • Kweepa worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #17 on: 16 Feb 2019, 17:55 »
You don't need to run through the whole way from the top to bottom of the circle, because of symmetry; only the top half, then do the same operations except with the signs changed.
Yeah, but the slow bit is the bit inside the inner loop, so it just complicates things.

This runs at 40 fps on my laptop.
I just move the ring in and out with a sin() for simplicity.

http://www.kweepa.org/step/ags/tech/Screech.zip

Code: Adventure Game Studio
  1. // room script file
  2.  
  3. DynamicSprite *unchangedBg;
  4.  
  5. float time = 0.0;
  6.  // when I made the ring 20 pixels thick it slowed down
  7. float ringThickness = 15.0;
  8.  
  9. function room_RepExec()
  10. {
  11.   time += 0.1;
  12.   DynamicSprite *newBg = DynamicSprite.CreateFromExistingSprite(unchangedBg.Graphic);
  13.   float bigR = 60.0 + 39.0 * Maths.Sin(time);
  14.   float weeR = bigR - ringThickness;
  15.   float x;
  16.   float y;
  17.   DrawingSurface *oldSurf = unchangedBg.GetDrawingSurface();
  18.   DrawingSurface *newSurf = newBg.GetDrawingSurface();
  19.   for (y = -bigR; y < bigR; y += 1.0)
  20.   {
  21.     float p = bigR*bigR - y*y;
  22.     if (p > 1.0)
  23.     {
  24.       float how = Maths.Sqrt(p);
  25.       float q = weeR*weeR - y*y;
  26.       if (q > 1.0)
  27.       {
  28.         float hiw = Maths.Sqrt(q);
  29.         for (x = -how; x < -hiw; x+= 1.0)
  30.         {
  31.           float d = 1.0 - 3.0 / Maths.Sqrt(x*x + y*y);
  32.           newSurf.DrawingColor = oldSurf.GetPixel(100 + FloatToInt(x*d), 100 + FloatToInt(y*d));
  33.           newSurf.DrawPixel(100 + FloatToInt(x), 100 + FloatToInt(y));
  34.         }
  35.         for (x = hiw; x < how; x+= 1.0)
  36.         {
  37.           float d = 1.0 - 3.0 / Maths.Sqrt(x*x + y*y);
  38.           newSurf.DrawingColor = oldSurf.GetPixel(100 + FloatToInt(x*d), 100 + FloatToInt(y*d));
  39.           newSurf.DrawPixel(100 + FloatToInt(x), 100 + FloatToInt(y));
  40.         }
  41.       }
  42.       else
  43.       {
  44.         for (x = -how; x < how; x+= 1.0)
  45.         {
  46.           float d = 1.0 - 3.0 / Maths.Sqrt(x*x + y*y);
  47.           newSurf.DrawingColor = oldSurf.GetPixel(100 + FloatToInt(x*d), 100 + FloatToInt(y*d));
  48.           newSurf.DrawPixel(100 + FloatToInt(x), 100 + FloatToInt(y));
  49.         }
  50.       }
  51.     }
  52.   }
  53.  
  54.   DrawingSurface *ds = Room.GetDrawingSurfaceForBackground();
  55.   ds.DrawImage(100, 50, newBg.Graphic);
  56.   newBg.Delete();
  57. }
  58.  
  59. function room_Load()
  60. {
  61.   Debug(4, 1);
  62.   unchangedBg = DynamicSprite.CreateFromBackground(0, 100, 50, 200, 200);
  63. }
  64.  
« Last Edit: 16 Feb 2019, 18:04 by Kweepa »
Still waiting for Purity of the Surf II

Dualnames

  • AGS Baker
  • Pretty Badass
    • Dualnames worked on one or more games that won an AGS Award!
    •  
    • Dualnames worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #18 on: 16 Feb 2019, 20:46 »
what a bastard, that's amazing, really nice idea on solving the thing with the circle from your previous post!
No more military army stuff. I'm alive and back.

Jack

  • Think deviant
    • I can help with AGS tutoring
    • I can help with scripting
    • I can help with story design
    • Jack worked on one or more games that was nominated for an AGS Award!
Re: Slow Drawing, how can I improve it
« Reply #19 on: 16 Feb 2019, 21:33 »
I was thinking, it might be the nested loops slowing it down. Maybe it will go better if you do one big loop for all pixels and use div and modulus to get the column and row indexes.