BG timer causing game to freeze

Started by Kinoko, Mon 01/03/2004 14:03:51

Previous topic - Next topic

Kinoko

I've got an animated background in one of my rooms that seems to dislike one of my animated sequences. I just -cannot- figure out what's wrong with the code, though I know it's probably something glaringly obvious. The code doesn't seem to like any blocking functions, and at the moment, it keeps freezing on the "int waitimer=100;" line. Here's the code, please let me know what stupid thing I've done wrong! ^_^


At the top of the room script:

int bgtimer,curbg;
int bgdelay[4];


First time player enter's screen:

bgdelay[ 0 ]=5;
bgdelay[1]=5;
bgdelay[2]=5;
bgdelay[3]=5;
curbg=0;
SetBackgroundFrame(curbg);
bgtimer=bgdelay[curbg];


Repeatedly Execute:

bgtimer--;
if (bgtimer==0) {
curbg++;
if (curbg>3) curbg=0;
SetBackgroundFrame(curbg);
bgtimer=bgdelay[curbg];
}


Function for object:

int waitimer=100;
while (waitimer){
Wait(1);
object0_a();
waitimer--;
}

waitimer=100;
int handle;
handle=MoveCharacterToObject (EGO, 3);
while (waitimer){
Wait(1);
object0_a();
waitimer--;
}

RickJ

#1
Are you recursively calling the object0_a() function?

function object0_a()
{
   int waitimer=100;

   while (waitimer) {
      Wait(1);
      object0_a();
      waitimer--;
   }
} 

Kinoko

Yep. That particular script is in the interaction editor for any click on that particular object.

RickJ

Generally speaking it's not a good practice to call event handler functions, let the AGS engine do that.  If you have functionality that is commmon to two or more events or situations define your own function that does that particular task and call it from the event handler function.

Kinoko

Well, this is the code given to me by others to solve the animating background problem I had earlier with blocking functions clashing with the bg animating.

Even when I take ALL that extra code away, and simply have a MoveCharacter function on "any click", and the standard animated background (without any scripting, just importing them into the room), the same thing happens. Actually, that's why I put the code there because I thought it would solve the problem by allowing functions to happen while the bg animated.

I've also noticed that the background stops animating and freezes (but doesn't freeze the game) when I'm having a conversation with a character and I get dialog options come up.

Whether it's a messy way of doing it or not (I don't know any other way), to my knowledge, it should be working. I just don't understand what's wrong.

RickJ

#5
Kinoko,

I'll try to explain as much as I can for you and perhaps others who  are wondering the same things.  

Quote
Well, this is the code given to me by others to solve the animating background problem I had earlier with blocking functions clashing with the bg animating.
I haven't seen the earlier thread of which you speak so I can't comment on that.

Quote
Even when I take ALL that extra code away ... , and simply have a MoveCharacter function on "any click", and the standard animated background (without any scripting, just importing them into the room), the same thing happens. ...
If you are still having this problem I'll try to help you with that.  I am not at my normal computer at the moment so I can't do any testing until later tonight.  

Quote
Whether it's a messy way of doing it or not (I don't know any other way), to my knowledge, it should be working. I just don't understand what's wrong.
Let me see if I can help you better understand what was wrong with the script you posted above.   You have a function named object0_a().  When a function is called, any memory space that it requires is allocated in a special area called a stack.  When the function finishes execution this meory is freed up.

If you can imagine a cafeteria where the dinner plates are stacked up and sit on a spring mechanism.  When you put more plates on top of the stack or take them away the spring mechanism keeps the top of the stack in the same place.   Stack meory areas are accessed in a similar manner.  

When a function is called, it's parameters are "pushed" on to the stack.  Variable declared inside the bounds of the function are allocated in the stack area as well.  

int waitimer=100;
So when your statement  "int waitimer=100;" creates a variable on the stack that is good only for the time the function is executing.  Whenever the function finishes that memory is free to be used by other functions or processes.   This also means that if you create a variable of the same name in another function, it will be a separate variable, a separate memory location.  

while (waitimer)
The while command will keep executing the code within the bounds of it's braces, {}, until the conditional expression evaluates to false.   I am not sure how AGS evaluates integer numbers other than zero or one.  It is generally considered bad practice to use integer values other than zero or one in such an expression.  A better, more reliable, more readable, way of writing this statement  would be "while (waitimer > 0)".    

Wait(1);
There is not much to say about this, other than read help to see what Wait() does.  :)  

object0_a();
Ouch!!!  This one hurts me for a couple of reasons.  I guess the worst thing is that you are calling the function object0_a() from within itself.  This situation is known as a recursive call.  The function is called from somewhere, and then it calls it self and that call calls itself,  etc.  It's sort of like placing two mirrors in fornt of each other, you get an infinite number of images.  In the case of a recursive function call you end of allocating an infinite amount of memory (remember the stack thing above).  Recursion is normally used to walk through hiearchical tree data structures (i.e. list all directories and sub-directories on the disk).  It works in this case because the number of recursive calls is limited to the depth of the hiearchy.   Although this kind of technique is not considered bad practice, it is seldom required in the scripting of an AGS game and is not recommended, IMHO.

The second thing that I don't like about this is that the function object0_a() is an event handler.  It was created by the AGS editor to be triggered by the game engine.   Although it's possible to do this and get away with it, the likelyhood of problems is greatly increased and it makes debugging difficult.  This is especially  when asking for help on the forums because it's something neither the game engine nor an experienced programmer would expect or anticipate.   Calling event handlers normally triggered by the game engine, I believe, is also considered bad practice.

waitimer--;
This statement decrements the variable "waitimer" by 1.  All is well here.

Bad Practice
When I use the term "Bad Practice"  I am referring to programming techniques that lead to errors, present and future.   It has been my experience that the most time consuming part of debugging a program is finding the bugs.  Once found and understood they are generally easy to  fix.   Bad programming practices make bugs more difficult to locate and to fix.  In addition, things that wok now may not work on a future version of the OS, game engine, compiler, etc...  Avoiding bad practices help avoid bugs in the first place which is the best way to debug a program, IMHO.

How would I do it?
Ok.  If I'm so darn smart then how would I have written this program?   I don't know what you were trying to accomplish by recursively calling the event handler so I can't address that specifically.  But I can show you what I would do in the case where  I wanted to perform the same operations as an event handler from somewhere else.

Original Version
function object0_a()
{
   int waitimer=100;

   while (waitimer) {
      Wait(1);
      object0_a();
      waitimer--;
   }
} 

Improved  Version
// Make our own function to do the common operations
function kinoko_stuff()
{
   int waitimer=100;

   while (waitimer>0) {   // Make sure expression evaluates to 0,1
      Wait(1);
      // object0_a();   don't know what this was supposed to accomplish, but whatever it was it doesn't do it.
      waitimer--;
   }
}

function object0_a()
{
   kinoko_stuff();          // Call function that does the common operations
} 

Original Problem
Kinoko, I know this doesn't help much with your original problem.  I hope it helps you understand a bit more of what is going on.   Post a link to the previous thread to which you are referring to and I will take a look at it later tonight.

Everyone else,  sorry for the lengtlhly explanation but I think that's what kinoko wanted.

Cheers
Rick

Kinoko

#6
Wow, thanks for the big description, Rick ^_^ (I feel so loved)

This is the original thread: http://www.adventuregamestudio.co.uk/yabb/index.php?board=6;action=display;threadid=11430

After all this, that particular room worked fine so I never had to think about the code again.

I'll have to read everything you said tomorrow though as uni has left me dead for now. Will get back to you tomorrow anyway, but thanks!

EDIT: The stupidest thing just happened. For some unbelievable reason, it now works. All I did was comment out all of that bg-related script and it works. It honestly just kept freezing before I put any of it in before! Oh, I feel a fool :)

I do still have the problem of the bg animation freezing when options in a dialog are presented to me. Any ideas on that one? ^_^ I really appreciate your help so far, so thanks a lot anyway.

EDIT 2: Just tried it again in general gameplay. It DOES freeze (the original bunch of actions after "any click" on a particular object) but only, it seems, when I enter the room normally through other rooms in normal gameplay. If I just make the game start in this room, and then I click on the object, the whole sequence works fine.

I don't know if this will just confuse matters further or make something clear.

RickJ

#7
Quote
Wow, thanks for the big description, Rick ^_^ (I feel so loved)
Hehe, I'm on a mission to make everyone be good programmers ...

Quote
This is the original thread: http://www.adventuregamestudio.co.uk/yabb/index.php?board=6;action=display;threadid=11430
I think Gilbot suggested trying to  call the repeatedly exeute event handler as a test to make sure that portion of the script was being executed.  He himself describes it as an "unclean" act.    Also I think the  the repeatedly execute he suggested can be improved by changing the "if" statment as shown below.  If bgtimer gets initialized to a negativ number for any reason iit will get reset to a correct value imediately instead of waiting for the counter to cycle through all valid numbers.
   bgtimer--;
   if (bgtimer<0) {
      curbg++;
      if (curbg>2) curbg=0;
      SetBackgroundFrame(curbg);
      bgtimer=bgdelay[curbg];
   }


Quote
... I do still have the problem of the bg animation freezing when options in a dialog are presented to me. Any ideas on that one? ^_^ I really appreciate your help so far, so thanks a lot anyway. ...

Just tried it again in general gameplay. It DOES freeze (the original bunch of actions after "any click" on a particular object) but only, it seems, when I enter the room normally through other rooms in normal gameplay. If I just make the game start in this room, and then I click on the object, the whole sequence works fine. ...

I don't know if this will just confuse matters further or make something clear.
Upload an example game and I'll take a look at what's going on. 

[edit]
Just had another look at the other thread and sure enough the bgtimer variable is not being initalized.   So the suggested improvement  of the "if" statement above should help make that script work better.  Yo may also want to add an initiakization to the variable declaration as follows:
 
   int bgtimer=0;

[/edit]


Kinoko

Righteo. The saga continues...

I created another game and created the basics of the room from scratch with all I needed to run the functions I wanted. Worked like a charm. I didn't include any of the BG timer code.

I went back to my actual game, got rid of all traces of that code from this particular room and tried again. I still had the problem of it not working if I walked into the room through normal gameplay, but working perfectly (functions being executed while BG animates) if I just teleported into the room.

It would always work in normal gameplay if I moved the character a little closer to the object though. Through a whole bunch of testing, I've realised what the problem was (but not really why this is a problem).

In that room, I have 3 regions on the floor (left, centre and right) so I can shift one characters eyes as my player character moves across the room. If I was on the same region as the object my character had to interact with, no problems. Everytime the character moved to another region (causing a FaceLocation function to occur in the other character), the sequence would finish one more function and then freeze.

So... I don't understand why fully, but the calling of another function in the middle of my sequence was interrupting it. Got rid of the regions on the floor, no more problems.

I'm really sorry you went to all the trouble of writing that big code explanation, but it DID help because I still use that code in another room :)

The only problem I have now is the BG animation stopping when options come up in a dialog. However, if there's no solution to this one, I can live with it.

THANKYOU again! ^_^

RickJ

Quote
In that room, I have 3 regions on the floor (left, centre and right) so I can shift one characters eyes as my player character moves across the room. If I was on the same region as the object my character had to interact with, no problems. Everytime the character moved to another region (causing a FaceLocation function to occur in the other character), the sequence would finish one more function and then freeze.
Hmmmm,  are you continously calling the FaceLocation() thing.   Probably you have a  continous loop going on there.  

Quote
I'm really sorry you went to all the trouble of writing that big code explanation, but it DID help because I still use that code in another room
I'm glad it helped.  I'm sure some other folks got some benefit as well.  

Quote
The only problem I have now is the BG animation stopping when options come up in a dialog. However, if there's no solution to this one, I can live with it.
Are you doing the animation from the script or are did you just let the game engine do it?  I thin global and room scirpts are blocked during dialogs but I don't thing the room animation is.  I am not certain though.  Maybe someone else knows?  


SMF spam blocked by CleanTalk