Discuss Scratch

caesarion
New Scratcher
15 posts

ScratchX Extension: How to provide concurrent execution of hat nodes when certain event occurs!

Hello guys,

having a look at the alarm_extension.js (see: https://github.com/LLK/scratchx/blob/master/alarm_extension.js) revealed that in case there are multiple hat blocks of type “when alarm goes off” only one of them is executed, since the variable “alarm_went_off” is set to false. I have a similiar problem in my extension project: When receiving a certain message, the hat block should be executed. But if there are multiple hat blocks, only one is executed. Is there any way to solve this, for example is there a way to find out how many block instances were created by the user?

thx
caesarion
Znapi
Scratcher
500+ posts

ScratchX Extension: How to provide concurrent execution of hat nodes when certain event occurs!

Sounds like a bug in ScratchX to me, or just a very weird design decision, because for all non-extension hat blocks like “when green flag clicked” and "when I recieve ", every instance of them in a project is executed.
khanning
Scratcher
34 posts

ScratchX Extension: How to provide concurrent execution of hat nodes when certain event occurs!

Hmm, since the when_alarm() function is responsible for checking and toggling the boolean variable, it makes sense that only one hat block is being executed. A simple workaround might be to include a delay before setting alarm_went_off to false to give the other hat blocks a chance to return true.

ext.when_alarm = function() {
// Reset alarm_went_off if it is true, and return true
// otherwise, return false.
if (alarm_went_off === true) {
// Wait 100ms before changing boolean
setTimeout(function() {
alarm_went_off = false;
}, 100);
return true;
}
return false;
};
caesarion
New Scratcher
15 posts

ScratchX Extension: How to provide concurrent execution of hat nodes when certain event occurs!

@khanning: Unfortunately your solution does not solve the problem properly, since I don't see how you can make sure that every block is executed within your given time period. Furthermore, (as in my case) an extension could be time critical and should not be allowed to wait.
@Znapi: yes it seems like a design flaw to me.

In all non-extension blocks the execution is done synchronously, e.g. when the space-key is pressed, this event is not consumed by one, but by all hat blocks :
when [ space] key pressed
change [ v2 by (1)
when [ space] key pressed
change [ v1 by (1)

in this case, both variables are increased synchronously. I need exactly this behavior with my extension-hat-block..
khanning
Scratcher
34 posts

ScratchX Extension: How to provide concurrent execution of hat nodes when certain event occurs!

The non-extension hat blocks don't appear to be executed synchronously either. Try the following example. The sprite will say whichever block was moved/modified last.

when [ space] key pressed
say [Hello]

when [ space] key pressed
say [World]

In the alarm example, all hat block functions receive the event, but since they are executed asynchronously only the first one is able to return true. You could wait to set alarm_went_off to false until the set alarm block is called again. This would allow all hat blocks to execute, but introduces a new issue since all new hat blocks would be executed immediately upon having something attached to them.

I agree that there should be a better way to handle this so I submitted an issue on the ScratchX GitHub repo.

I think the best workaround would be some combination of the above strategies:
new (function() {
var ext = this;
var alarm_went_off = false; // This becomes true after the alarm goes off

var reset_timer = null;

// Cleanup function when the extension is unloaded
ext._shutdown = function() {};

// Status reporting code
// Use this to report missing hardware, plugin or unsupported browser
ext._getStatus = function() {
return {status: 2, msg: 'Ready'};
};

ext.set_alarm = function(time) {
if (reset_timer) {
clearTimeout(reset_timer);
reset_timer = null;
alarm_went_off = false;
}
window.setTimeout(function() {
alarm_went_off = true;
}, time*1000);
};

ext.when_alarm = function() {
if (alarm_went_off === true) {
if (!reset_timer) {
setTimeout(function() {
alarm_went_off = false;
reset_timer = null;
}, 1000);
}
return true;
}

return false;
};

// Block and block menu descriptions
var descriptor = {
blocks: [
['', 'run alarm after %n seconds', 'set_alarm', '2'],
['h', 'when alarm goes off', 'when_alarm'],
]
};

// Register the extension
ScratchExtensions.register('Alarm extension', descriptor, ext);
})();

I just wanted to point out that this isn't an issue in all hat block situations. Here's an example from the Arduino extension where all hat blocks get executed properly since they don't depend on a single boolean variable:
ext.whenInput = function(name, op, val) {
var hw = hwList.search(name);
if (!hw) return;
if (op == '>')
return analogRead(hw.pin) > val;
else if (op == '<')
return analogRead(hw.pin) < val;
else if (op == '=')
return analogRead(hw.pin) == val;
else
return false;
};

Last edited by khanning (June 17, 2015 12:39:49)

caesarion
New Scratcher
15 posts

ScratchX Extension: How to provide concurrent execution of hat nodes when certain event occurs!

Thx for setting up the issue!
bobbybee
Scratcher
1000+ posts

ScratchX Extension: How to provide concurrent execution of hat nodes when certain event occurs!

IIRC this is an effect of how Scratch itself implements threading (Scratch itself is single-threaded, and just emulates different scripts as threads, which causes esoteric behaviour like this at times).

Powered by DjangoBB