SOLVED: How do I fool the while loop iteration limit?

Started by Hernald, Fri 05/07/2013 00:18:07

Previous topic - Next topic

Hernald

I am trying to write a function creates a map of the hotspots in a room and sends it to a .bmp file.
The function GrabHotspots(); is placed in the code of room to be mapped to run after the room has become visible.
The trouble is that if the room is much larger than 320*240 pixels the process crashes as the iterations exceed 150,000.
I've tried to fool it by having the code in blocks and breaking out when the room has been scanned - returning instead of using a while loop; but it still doesn't work. Any suggestions?

Code: AGS

DynamicSprite* theroom;
DrawingSurface* themask;

int roomwidth;
int roomheight;

Hotspot* hot;

function DrawBlock(int xfrom, int yfrom, int xto, int yto) {
	int xcount;
	int ycount;
	
	xcount = xfrom;
	while (xcount<xto) {
		ycount = yfrom;
		while (ycount<yto) {
			hot = Hotspot.GetAtScreenXY(xcount, ycount);
			themask.DrawingColor = hot.ID;
			themask.DrawPixel(xcount, ycount);
			ycount++;
		}
		xcount++;
	}
}

function BlocksAcross(int ystart) {
	int thiswidth;
	
	int thisheight=ystart+240;
	if (roomheight<thisheight) thisheight = roomheight;
	
	int xstart = 0;
	thiswidth = 320;
	if (roomwidth<thiswidth)thiswidth = roomwidth;
	DrawBlock(xstart, ystart, thiswidth, thisheight);
	if (thiswidth==roomwidth) return;
	
	xstart+=320;
	thiswidth +=320;
	if (roomwidth<thiswidth)thiswidth = roomwidth;
	DrawBlock(xstart, ystart, thiswidth, thisheight);
	if (thiswidth==roomwidth) return;	
	
	xstart+=320;
	thiswidth +=320;
	if (roomwidth<thiswidth)thiswidth = roomwidth;
	DrawBlock(xstart, ystart, thiswidth, thisheight);
	if (thiswidth==roomwidth) return;	
	
//repeat  this  if the room is any wider
						
}

function GrabHotspots() {

	theroom = DynamicSprite.CreateFromBackground();
	themask = theroom.GetDrawingSurface();
	

	roomwidth=theroom.Width;
	roomheight=theroom.Height;

// The next two operations mess up the game; Fix this later.
	int hcount = 1;
	while (hcount<50) {
		hotspot[hcount].Enabled=true;
		hcount++;
	}
	
	SetViewport(0, 0);

	BlocksAcross(0);
	if (roomheight>=240)BlocksAcross(240);
	if (roomheight>=(240*2)) BlocksAcross(240*2);
// add lines if the room is any deeper	
		
	themask.Release();
	theroom.SaveToFile("RoomHotspots.bmp");
	theroom.Delete();
}

Ryan Timothy B

#1
This one is easy.  :-D

Code: ags
function noloopcheck DrawBlock(int xfrom, int yfrom, int xto, int yto) {
  // etc
}

Or rather putting it on the function that exceeds 150k loops.

Hernald

#2
Spot on! Thanks Ryan!
If anyone's interested; here is the simplified code.
Code: AGS

DynamicSprite* theroom;
DrawingSurface* themask;
Hotspot* hot;

function noloopcheck DrawHots(int xfrom, int yfrom, int xto, int yto) {
    int xcount;
    int ycount;
   
    xcount = xfrom;
    while (xcount<xto) {
        ycount = yfrom;
        while (ycount<yto) {
            hot = Hotspot.GetAtScreenXY(xcount, ycount);
// To-do: Fix drawing colours to shades of blue so its easy to convert to gif and re-import.
            themask.DrawingColor = hot.ID;
            themask.DrawPixel(xcount, ycount);
            ycount++;
        }
        xcount++;
    }
}


function GrabHotspots() {

    theroom = DynamicSprite.CreateFromBackground();
    themask = theroom.GetDrawingSurface();
 // To-do: Save hotspots.Enabled values and Viewport coordinates to restore later.  
    int hcount = 1;
    while (hcount<50) {
        hotspot[hcount].Enabled=true;
        hcount++;
    }
   
    SetViewport(0, 0);

    DrawHots(0, 0, theroom.Width, theroom.Height);
       
    themask.Release();
    theroom.SaveToFile("RoomHotspots.bmp");
    theroom.Delete();
}

Khris

Are you using the hotspots bmp within the game?
Because if you just wanted to export the hotspots, you could also change the room background to all white and take a screenshot.

Hernald

I'm after exporting the whole room, not just the visible screen after I have updated it in the AGS editor, so that I can convert it to a gif file and then reimport it if anything unfortunate happens to the in-game version.
My next challenge is getting up to forty-nine shades of blue (with no green).

Khris

I'm talking about a screenshot of the editor, not an in-game one.
Unless you're using extremely large room graphics, you should be able to see the entire background in the editor if you set the zoom to 100%, right?
Turn down the transparency and you have all hotspots in varying shades of grey.

Hernald

That's one option Khris, what I have done is add the magic number 65536 (from the TruBlu module) to the hotspot ID and it gives the map in shades of blue which I can port back into AGS when I need to, only having to change it to a gif.
The only downside of my method is that I need to call the function from the room in-game.

Here is the completed code:
Code: AGS

DynamicSprite* theroom;
DrawingSurface* themask;
Hotspot* hot;

function noloopcheck DrawHots(int xfrom, int yfrom, int xto, int yto) {
    int xcount;
    int ycount;
   
    xcount = xfrom;
    while (xcount<xto) {
        ycount = yfrom;
        while (ycount<yto) {
            hot = Hotspot.GetAtScreenXY(xcount, ycount);
            if (hot.ID==0) themask.DrawingColor = 0;
            else {
                if (Room.ColorDepth==32) themask.DrawingColor = 65536+hot.ID;
                else {
                    if (hot.ID<32) themask.DrawingColor = 31+hot.ID;
                    else themask.DrawingColor = 224+hot.ID;
                }
            }
            themask.DrawPixel(xcount, ycount);
            ycount++;
        }
        xcount++;
    }
}


function GrabHotspots() {
  bool isenabled[50];
    int    xviewstore = GetViewportX();
    int yviewstore = GetViewportY();
    theroom = DynamicSprite.CreateFromBackground();
    themask = theroom.GetDrawingSurface();
   
    int hcount = 1;
    while (hcount<50) {
        isenabled[hcount]=hotspot[hcount].Enabled;
        hotspot[hcount].Enabled=true;
        hcount++;
    }
   
    SetViewport(0, 0);

    DrawHots(0, 0, theroom.Width, theroom.Height);

    hcount = 1;
    while (hcount<50) {
        hotspot[hcount].Enabled=isenabled[hcount];
        hcount++;
    }
   
    SetViewport(xviewstore, yviewstore);
   
    themask.Release();
    String filename;
    filename = String.Format("Room%dHotspots.bmp",player.Room);
    theroom.SaveToFile(filename);
    theroom.Delete();
}


SMF spam blocked by CleanTalk