I get this error "Script appears to be hung (a while loop ran 150001 times). The problem may be in a calling function; check the call stack."when I try to run the code below:
while (iY1 < dsSourceGraphic.Height) //768
{
while (iX1 < sSourceGraphic.Width) //1024
{
//iAlpha = GetAlpha(dsLongGrass.Graphic, iY1, iX1);
//ds.DrawingColor = Game.GetColorFromRGB(iAlpha,iAlpha,iAlpha); //this is a grey color representing the alpha.
//ds.DrawPixel(iX1,iY1); // draw the alpha to the copy.
iX1++;
}
iY1++;
iX1 = 0;
}
I've been using that "while snippet" throughout my game, but it only works when the dynamic sprite "dsSourceGraphic" is square (70x70, for example). How do I get it to work with a rectangle? (1024x768)
Its being used to go through the dynamic sprite's pixels to copy the alpha channel.
You put dsSourceGraphic.Height but sSourceGraphic.Width, so maybe it's referencing a different, much larger sprite? That's off the top of my head, just looking at the code for a sec as I'm strapped for time, but maybe that's it!
768 * 1024 = 786432
And that is larger than 150001, is it.
Thing is, that AGS counts consecutive loops as one loop. That is because it is not loop iterations on their own that matters, but the time that it takes to make one pass in script and return back to engine. Engine wants to be sure that it does not hang, making game to halt completely.
Add "noloopcheck" keyword to the function declaration:
function noloopcheck function_name
@DKH: Oups, I made a typo while transcribing it to the forums, thanks for catching that :)
@Crimson Wizard: Wow, cool! Didnt know that. It definitely fixed the error problem, although I now have a new problem related to the AGSBlend plugin...plus its way too slow processing the whole screen pixel by pixel for what I want it to do...I believe I need to rethink this :)
Im gonna try to debug that part, but might post a follow-up question if I cant figure it out.
Thanks for your help guys!
Quote from: General_Knox on Thu 22/11/2012 02:29:14
I now have a new problem related to the AGSBlend plugin...plus its way too slow processing the whole screen pixel by pixel for what I want it to do...
Yes, I was going to mention this, such pixel by pixel processing is really slow if done in script.
That's what plugins are for. You may make one on your own and put all tough drawing there.
Crap, I know I can't program my own plugin, so I'll have to figure out another solution for this I think. I'm thinking maybe make the surface area for the "cut grass mini-game" alot smaller than 1024x768.
I wish there was an easier/faster way to "paint" onto a sprite's alpha channel, using another sprite as the "brush" shape. I got it to work fine with the DrawLine though. Too bad I can't use "magic pink" with the DrawAlpha() function...it just draws to the RGB. DOh!
Quote from: General_Knox on Thu 22/11/2012 23:51:05
Crap, I know I can't program my own plugin,
Ask Calin :D.
Hehe...well maybe I will if I cant figure something out!
Ill even pay him if he wants...but guys keep refusing here! :)
Hey guys!
I found a solution for another problem I was fixing at the same time, and I think I can use that solution for this one (cutting the grass effect):
I wrote some scripts to enable shadows in multiply mode on the tractor (which I will re-use for the player character and driving module, yay). I can post them if anyone wants it.
I realized drawing all this stuff to a large 1024x768 sprite every loop is way too heavy + slow, so I divided up the "grass area" into 6 pieces of 340x340 each on its own object. Then I wrote a script that detects what zone (object) the tractor is in/over. If the tractor is in 4 zones (over 4 objects) at once (maximum), then redraw the shadow for those zones...obviously if the tractor is over just 1 zone, then that's when the script works the fastest.
For a non-programmer like me, man it feels good to get something like this to work, hehe! Very rewarding. Took me a whole freakin 3 days to figure it out, I bet Monkey/Khris/Wizard and the like would have taken 5 min.
Here is a video of the results, which now I will try to apply the same thing to "cutting the grass away"
View My Video (http://tinypic.com/r/2aakgif/6)
Almost there!! :)
Umm, can you elaborate, you mean you are redrawing the whole screen (or quarter of the screen) only to place that vehicle's shadow over? Am I missing something?
No, before I was doing that and getting 30fps drops!! Thats why now I decided to divide the screen into 6 zones of 340x340 objects. I just redraw the graphic of whatever object the tractor is currently over with the shadow in multiply mode.
Is there a even better way? Right now with this solution Im only getting a 5-10fps drop, so it seems much more efficient than before!
Usually, when there's a sprite moving around the screen and you do not want to redraw whole screen, there's this solution: remember previous coordinates of the tractor, and after it moves redraw only that small background piece, which was covered by tractor prior to movement. Then draw the tractor with shadow on a new place.
Basic algorythm is this:
1. Create a "buffer" sprite at the start of the game (or room).
2. Copy a part of background behind the tractor in its initial position on that buffer sprite, and draw the shadow.
Game loop:
3. Do not redraw if the tractor did not move.
4. If tractor moved,
4a. use buffer to redraw a small strip, which is a difference from position previously covered by tractor and not covered now,
4b. copy new part of background (behind new tractor position) to the buffer
4c. draw shadow on a new place.
Repeat.
E: hmm, actually, since it sounds like you have the background stored somewhere anyway, you may skip the buffer part.
What kind of spec is your PC? Per pixel calculation on the CPU is *very* slow and you need to be sure that your game will actually run on normal hardware.
@Calin:
Specs:
HP Workstation z400 Zeon W3530 2.8GHz
12 GB of RAM
NVIDIA GeForce GTX 560HP
I'm really trying to make "heavy" features toggable in the game settings, like turning off shadows, certain effects, etc...I really dont want to exclude low end/normal machines!!
@Wizard:
I've got a check that if the (!player.IsMoving), I dont redraw. I'm pretty sure Im already doing steps 1 to 4, but instead of drawing the shadow on the background, I draw the shadow to the object's graphic because Im guessing drawing the a smaller sprite 340x340 is better/fster than redrawing to the whole screen (?) Perhaps I dont understand something so forgive my ignorance!
Here is my code (without the global variables, small functions here and there, etc):
function room_RepExec()
{
if (bMoving) player.GetZones();
cShadow.Loop = player.Loop;
if (bShadowInitialize && !(player.Moving))
{
//in the game settings you can turn shadows on/off, when set to on, query the zone the player is over
if (bActivate_ZoneA) cShadow.ShadowInitialize(oLongGrass_A, 1);
if (bActivate_ZoneB) cShadow.ShadowInitialize(oLongGrass_B, 2);
if (bActivate_ZoneC) cShadow.ShadowInitialize(oLongGrass_C, 3);
if (bActivate_ZoneD) cShadow.ShadowInitialize(oLongGrass_D, 4);
if (bActivate_ZoneE) cShadow.ShadowInitialize(oLongGrass_E, 5);
if (bActivate_ZoneF) cShadow.ShadowInitialize(oLongGrass_F, 6);
}
if (player == cTractor && player.Moving)
{
if (!bMoving) bMoving = true;
iLoop = player.GetCharacterDirection(); //get the direction so we can adjust the mower's cutting width
if (bShowShadow && !bShadowOff)
{
if (bActivate_ZoneA) oLongGrass_A.DrawOnShadowReceiver(4769, 1);
if (bActivate_ZoneB) oLongGrass_B.DrawOnShadowReceiver(4779, 2);
if (bActivate_ZoneC) oLongGrass_C.DrawOnShadowReceiver(4780, 3);
if (bActivate_ZoneD) oLongGrass_D.DrawOnShadowReceiver(4781, 4);
if (bActivate_ZoneE) oLongGrass_E.DrawOnShadowReceiver(4782, 5);
if (bActivate_ZoneF) oLongGrass_F.DrawOnShadowReceiver(4783, 6);
}
}
if (!bShowShadow)
{
if (bShadowOff && player.Moving)
{
if (bActivate_ZoneA) oLongGrass_A.ClearShadowReceiver(4769);
if (bActivate_ZoneB) oLongGrass_B.ClearShadowReceiver(4779);
if (bActivate_ZoneC) oLongGrass_C.ClearShadowReceiver(4780);
if (bActivate_ZoneD) oLongGrass_D.ClearShadowReceiver(4781);
if (bActivate_ZoneE) oLongGrass_E.ClearShadowReceiver(4782);
if (bActivate_ZoneF) oLongGrass_F.ClearShadowReceiver(4783);
}
}
void ShowShadow(this Character*, Object* onWhat, int iZone)
{
if (bShowShadow == true)
{
cShadow.Loop = player.Loop;
//first clear any shadows on surface by reverting back to original object surface's sprite...in room script
dsSource = DynamicSprite.CreateFromExistingSprite(onWhat.Graphic, true);
if (iZone == 1) dsApplyShadow_A = DynamicSprite.CreateFromExistingSprite(onWhat.Graphic, true);
else if (iZone == 2) dsApplyShadow_B = DynamicSprite.CreateFromExistingSprite(onWhat.Graphic, true);
else if (iZone == 3) dsApplyShadow_C = DynamicSprite.CreateFromExistingSprite(onWhat.Graphic, true);
else if (iZone == 4) dsApplyShadow_D = DynamicSprite.CreateFromExistingSprite(onWhat.Graphic, true);
else if (iZone == 5) dsApplyShadow_E = DynamicSprite.CreateFromExistingSprite(onWhat.Graphic, true);
else if (iZone == 6) dsApplyShadow_F = DynamicSprite.CreateFromExistingSprite(onWhat.Graphic, true);
player.GetShadowSprite();
iShadowSpriteBkp = iShadowSprite;
iShadowAreaW = Game.SpriteWidth[iShadowSprite];
iShadowAreaH = Game.SpriteHeight[iShadowSprite];
getZoneAdjustment(iZone);
int iX = this.x - (iShadowAreaW/2) + iXzoneAdjust; //substract the length of the sprite + ifactor
int iY = this.y - (iShadowAreaH/2) + iYzoneAdjust + iYadjust;
if (iZone == 1) DrawSprite(dsApplyShadow_A.Graphic, iShadowSprite, iX, iY, eBlendMultiply, 0); //draw shadow on top
else if (iZone == 2) DrawSprite(dsApplyShadow_B.Graphic, iShadowSprite, iX, iY, eBlendMultiply, 0); //draw shadow on top
else if (iZone == 3) DrawSprite(dsApplyShadow_C.Graphic, iShadowSprite, iX, iY, eBlendMultiply, 0); //draw shadow on top
else if (iZone == 4) DrawSprite(dsApplyShadow_D.Graphic, iShadowSprite, iX, iY, eBlendMultiply, 0); //draw shadow on top
else if (iZone == 5) DrawSprite(dsApplyShadow_E.Graphic, iShadowSprite, iX, iY, eBlendMultiply, 0); //draw shadow on top
else if (iZone == 6) DrawSprite(dsApplyShadow_F.Graphic, iShadowSprite, iX, iY, eBlendMultiply, 0); //draw shadow on top
if (iZone == 1) onWhat.Graphic = dsApplyShadow_A.Graphic;
else if (iZone == 2) onWhat.Graphic = dsApplyShadow_B.Graphic;
else if (iZone == 3) onWhat.Graphic = dsApplyShadow_C.Graphic;
else if (iZone == 4) onWhat.Graphic = dsApplyShadow_D.Graphic;
else if (iZone == 5) onWhat.Graphic = dsApplyShadow_E.Graphic;
else if (iZone == 6) onWhat.Graphic = dsApplyShadow_F.Graphic;
iShadowSprite = iShadowSpriteBkp;
}
}
Quote from: General_Knox on Mon 26/11/2012 16:20:32
@Wizard:
I've got a check that if the (!player.IsMoving), I dont redraw. I'm pretty sure Im already doing steps 1 to 4, but instead of drawing the shadow on the background, I draw the shadow to the object's graphic
That does not matter, by saying "background" I meant anything beyond. Sorry for any confusion.
Quote from: General_Knox on Mon 26/11/2012 16:20:32
because Im guessing drawing the a smaller sprite 340x340 is better/fster than redrawing to the whole screen
Ofcourse it is, but redrawing an even smaller piece of about tractor's size is even faster.
What I mean is, you may have only 1 object for all room (this object represents long grass, right?) and don't redraw all of it, but redraw only small piece at previous tractor's position.
[imgzoom]http://img28.imageshack.us/img28/3843/tractork.png[/imgzoom]
You copy the object's graphic piece beyond the tractor.
When tractor moves you:
1. Paste stored graphic into zone 1.
2. Copy object's graphic piece from zone 2.
3. Draw shadow over zone 2.
And repeat.
Oooohhhh!! Ah ok now I see :)
Wow, yeah, thats even better! Ok, gonna try that out now.
Thanks!