Is this safe: Cancelling blocking actions

Started by SSH, Thu 08/06/2006 14:43:40

Previous topic - Next topic

SSH

I wondered if it would be safe to create code like this:

Code: ags

int storebutton;
int count;

function repeatedly_execute_always() {
	if  (count>1) count--;
	if (count==1 && (mouse.IsButtonDown(eMouseRight) || mouse.IsButtonDown(eMouseLeft)) && player.Moving) {
	  player.StopMoving(); // Cancel wahtever blocking action was going on
	}
}


function on_mouse_click(MouseButton button) {
  storebutton=button;
  count=15;
}


Why wouldn't it be? Well, if you had an interaction that did:

Code: ags

function hotspot1_a() {
  // script for Hotspot 1 (Hotspot 1): Interact hotspot
  player.Walk(hotspot[1].WalkToX, hotspot[1].WalkToY, eBlock);
  player.Say("Done");
}


then stopping the character walkign in rep_ex_always will leave the Say function never called. Does AGS build up some stack of "hung functions" when you do this, or does it just give up on them? Becasue it seems to work in a quick test (i.e. clicking during blocking stops the action) but maybe after 100 or 1000 cancelled walks, it would die?

12

Kweepa

You could simulate this by using (pseudo code)

Code: ags

rep_ex_always
if (!player.Moving) hotspot[1].RunInteraction(eCursorMode_Interact); else player.StopMoving();


and just let it run.
Still waiting for Purity of the Surf II

Pumaman

Yes, the code that you've posted is safe. By calling StopMoving in rep_exec_always, it will mark the character as Stopped, then the main thread will notice that the character has finished, and continue to run. I'm not sure why you claim that "Say" would never be called -- I just tried a sample game with this code and when StopMoving was called from rep_exec_always, the main scirpt resumed and the Say() was executed as expected.

For more on blocking scripts see here:
http://www.adventuregamestudio.co.uk/manual/BlockingScripts.htm

SSH

Well, in http://ssh.me.uk/cancel.zip you can click on the coloured bits at each end with the "interact" cursor and the following happens:

a) if you click away the "Doing" message, roger cancels his walk and says "Done", i.e. finishes the script
b) if you wait until he starts moving then click, he stops and doesn't say "Done"
c) if you set walkto points on the hotspots and then click to cancel, he doesn't even say "doing"

12

Gilbert

#4
I think I'd found the reason of your problem, actually no matter what the second "Done" message DID display.

The problem lies in here:
if (count==1 && (mouse.IsButtonDown(eMouseRight) || mouse.IsButtonDown(eMouseLeft)) && player.Moving) {

So, if you click while he's moving, when the StopMoving(); function is called it's obvious that you must still be holding the mouse button in that particular loop, when the Display() line is executed, it's registered as a mouse click so the text goes away immediately.

If you click it while "Doing" is displayed, when you click away the text the mouse click had been registered, if you're still holding the button it won't be considered as another click when "Done" is displayed.

You may test it by adding some visible effect which won't be clicked away after the player moves (like Rawprinting a message, etc.), and you'll see the subsequent actions are indeed called.

EDIT:
Another fast way to check is, that you insert another Display() after "Done" (like "Done2" say for example), and you'll see that when you click while walking it looks as if the first "Done" is not executed (actually you clicked the text away) but the second "Done2" is still visible.

Pumaman

Yes, Gilbert's explanation sounds plausible.

Because IsButtonDown is asynchronous, you will probably detect the mouse being down before AGS actually processes it as a click itself, therefore that will then click away the Say() line.

SSH

Also, clicks usually register on MouseUp
12

SMF spam blocked by CleanTalk