Nested While loop problem

Started by CaptainD, Fri 15/07/2016 20:47:45

Previous topic - Next topic

CaptainD

Just can't seem to get my head round why this isn't working.  It's in a light cycles game and everything works fine (albeit my attempts at programming AI opponents sucks), and I want to have a crashed cycle and its trail "de-rez".  The function I've written to do this seems in principle to be pretty simple - it simply checks every pixel and overwrites it with black if it matches that particular cycle's colour - but it doesn't seem to actually do anything.  The game carries on as if nothing's happened even though I've checked to ensure the function actually is being called - something breaks down inside one (or both?) of the While loops.

Code: ags

function DeRez()
{if (DeRezzed[n]==true) return;

DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.DrawingColor = 0;
cy=0;
while (cy<200)
{   cx=0; 
    while (cx<320)
     {if (surface.GetPixel(cx, cy)==c[n]) surface.DrawPixel(cx, cy);
      cx++;}
      cy++;}
surface.Release();
DeRezzed[n]=true;
}

 

Snarky

Jesus, that indentation! :~(

Otherwise the logic looks correct. However, isn't DrawingColor 0 transparent rather than black? While I don't remember off the top of my head what happens when you draw with transparent in different circumstances, it seems plausible that in this case it would just leave the color that is already there. (AGS color handling is messed up, yo!)

This approach is extremely slow, BTW. It would probably be faster to simply wipe the screen and redraw all the other trails (which you'd have to keep track of, of course).

CaptainD

Sorry about the indentation, I got frustrated with it and just hacked away at different bits... :-[

I think I might actually ditch the idea.  I think either way might slow the game down... was thinking it might be acceptable, but maybe not.  Will check on the colour, was sure I'd used colour 0 to wipe everything before (but might be wrong...)

Hope the poor indentation doesn't result in another ban for me! (roll)
 

Matti

For everybody's convenience now with proper indentation ;)

Can't see a mistake, but maybe Snarky is right about the color.

Code: ags
function DeRez()
{
  if (DeRezzed[n] == true) return;
 
  DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
  surface.DrawingColor = 0;
  cy = 0;

  while (cy < 200)
  { 
    cx = 0; 
    while (cx < 320)
    {
      if (surface.GetPixel(cx, cy) == c[n]) surface.DrawPixel(cx, cy);
      cx++;
    }
    cy++;
  }
  surface.Release();
  DeRezzed[n] = true;
}

dayowlron

I don't think the problem is with the code itself, but the fact that it would be incredibly slow. It would probably take more than a minute to process the loops on a slow machine. It would have to execute the "if (surface.GetPixel(cx, cy) == c[n]) surface.DrawPixel(cx, cy);" line 64,000 times. I don't know how fast that line can execute but it could be long enough that it can't complete the loop 40 times a second (The refresh rate of the game).
Pro is the opposite of Con                       Kids of today are so much different
This fact can clearly be seen,                  Don't you know?
If progress means to move forward         Just ask them where they are from
Then what does congress mean?             And they tell you where you can go.  --Nipsey Russell

Snarky

Running slow is one thing, but if it's not working at all it would be interesting to find out exactly why. There are really only two possibilities: either the if (surface.GetPixel(cx, cy) == c[n]) test isn't returning true, or the surface.DrawPixel(cx, cy) command isn't actually drawing black on the background. It should be easy enough to figure out which one it is (e.g. instead of color 0, try with color 7; or put a debug message into teh body of the loop).

Anyway, this might be a simpler and more efficient solution: If you only have a few of these light cycle trails, and if they don't intersect or overlap in any complex way (i.e. one trail crossing in front of another trail in one place, but behind it in another), you could draw each of them on a separate object, and when it's de-rezzed you can just clear, delete or hide it.

CaptainD

I'm certain Colour 0 is Black not transparent, so it must be the checking part that doesn't work.  (I also tried it with a different colour just to check and that did nothing either.)  Somehow it's running and doing absolutely nothing, "if (surface.GetPixel(cx, cy) == c[n])" is clearly not doing what I thought it would do, but I'm not sure what error I've managed to introduce!

The speed isn't too much of an issue as it will only happen three times in total during a (4-player) game, but I will look at other options.  Did think of also having the game keep track of each player's minimum and maximum x / y coordinates traversed and only check between then.  Of course Snarky's idea may well be better than mine.  (With his encyclopaedic knowledge of AGS scripting I'm certain it is...)
 

dayowlron

a comment to make and a question.
Comment: Something you could try is separate the if statement onto 2 separate lines like this:
if (surface.GetPixel(cx, cy) == c[n])
    surface.DrawPixel(cx, cy);

Then put a breakpoint on the surface.DrawPixel function so you could tell if the if statement is EVER true. Might help you narrow down the problem.

Question: If the loop takes (lets say 2 seconds to run), during those 2 seconds does the game lock up or does it continue to redraw the screen. If so would that mess up the "surface" object?  I am not that familiar with GetPixel and DrawPixel but wondering what happens when loops take too long for the program to refresh the screen at 40 frames per second.
Pro is the opposite of Con                       Kids of today are so much different
This fact can clearly be seen,                  Don't you know?
If progress means to move forward         Just ask them where they are from
Then what does congress mean?             And they tell you where you can go.  --Nipsey Russell

Snarky

Quote from: dayowlron on Tue 19/07/2016 18:52:20wondering what happens when loops take too long for the program to refresh the screen at 40 frames per second.

AGS always runs all the code associated with each frame before displaying it. Once it's done, it checks if 1/40 second has passed (or whatever the game speed is), and if there's time left it waits until the right amount of time has elapsed, displays the frame, and starts processing the code (both AGS-internal and scripted) for the next frame.

So if the script takes more time than that, the game will simply hang until the script is complete, and then move on to the next frame immediately. If this happens every cycle, the effect will be that the game runs more slowly than the game speed (and it can cause the audio to break up, if the audio buffer runs out during the processing).

One caveat: There is a safety feature built in that ensures that if a loop repeats more than a certain number of times in a single cycle, it will break, closing the game, though it can be disabled with the keyword noloopcheck.

Monsieur OUXX

Quote from: CaptainD on Mon 18/07/2016 16:36:26
I'm certain Colour 0 is Black not transparent
I vaguely recall having had issues with that sort of reasoning in the past. Pro-tip: don't use hard-coded values. Use macros such as COLOR_BLACK or whatevs. Do test color 0.
 

Monsieur OUXX

I don't understand this function.
Is the game supposed to continue running during the derez?
Whether the answer is "yes", or "no", and unless I'm missing something, this code cannot work in any case -- since there is no surface release or game rendering after each pixel writing.
there should be a surface release and a Wait(1) for each pixel writing. Otherwise how do you expect to see anything reflected to the screen?

Also I don't understand what's array "c".
 

Snarky

Quote from: Monsieur OUXX on Wed 20/07/2016 18:01:01
Whether the answer is "yes", or "no", and unless I'm missing something, this code cannot work in any case -- since there is no surface release or game rendering after each pixel writing.
there should be a surface release and a Wait(1) for each pixel writing. Otherwise how do you expect to see anything reflected to the screen?

The effect, if it worked, would be the whole trail erased at once. The surface is released (line 19 in Matti's edited version) once the entire canvas has been processed. I assume that's the intended effect.

Quote from: Monsieur OUXX on Wed 20/07/2016 18:01:01
Also I don't understand what's array "c".

Presumably an array of color values for each trail.

CaptainD

Snarky is correct on both counts.
 

SMF spam blocked by CleanTalk