Discuss Scratch

JediChickenD
Scratcher
8 posts

Faking cross-sprite procedure calls with broadcast - without lag how?

Long-time professional programmer here, but new to Scratch…

So I'm experimenting with custom blocks, no-refresh, broadcast / broadcast-and-wait,.. trying to figure out the best “work-around” for “calling” a procedure in one sprite, from another sprite, potentially many times, without incurring screen-refresh lag in between those calls.

PROBLEM DEFINED:

For example, let's say I have a “utility” sprite that handles bitmapped text for me (like this) and I'd like other sprites to be able to call it on demand without incurring screen-refresh lag.

I obviously need to be able to pass it some parameters (at least the text, x, and y positions), and if I were able to magically invent new functionality within Scratch, there'd be a version of the stack Custom Block that took a “target sprite” as well as the block's name within that sprite. Then I could just call:

[Font].Write text: [Hello World] at x: (50) y: (10) :: stack custom // BUT,.. this functionality doesn't actually exist

ATTEMPTED WORK-AROUNDS:

It seems the only cross-sprite communication method is broadcasts. Which then seems to require the transfer of parameters via global variables. But here I seem to be stuck…

1. On one hand, a plain broadcast won't lag because it's asynchronous, BUT that also means you can't be guaranteed that the global variables you just set up for THIS call aren't later wiped out by some OTHER call. So this method seems ruled out.

2. On the other hand, a broadcast-and-wait will process those variables “right now” so they won't be wiped out by other calls, but will introduce screen-refresh lag. So this method seems ruled out too.

The approach below is about the best I've been able to come up with so far, but I can't seem to get rid of the screen-refresh lag:

// in SomeOtherSprite:
set [gText v] to [Hello World!]
set [gX v] to [50]
set [gY v] to [10]
broadcast [FontWrite v] and wait

// in Font:
when I receive [FontWrite v]
Write text: (gText) at x: (gX) y: (gY) :: stack custom

declare Write text: [text] at x: (x) y: (y) :: hat custom // set to run without refresh
...

About the only thing I can think of to try next is a sort of “just one sprite” approach, where one single sprite has all the graphics and code all mashed together, with many differently-costume'd clones of itself (and a bunch of code logic to separate out their functionality by type of sprite). Because then cross-sprite communication becomes a moot point. But that seems like it'd be a spaghetti-code nightmare!

FINALLY, THE ACTUAL QUESTION!:

So, are there any other “tricks” that might work here? Thanks!!

Last edited by JediChickenD (April 19, 2019 14:27:11)

14152cool
Scratcher
100+ posts

Faking cross-sprite procedure calls with broadcast - without lag how?

This is a very, very interesting question. Indeed, it would become a spaghetti code nightmare if you tried to pack everything into one sprite, I've tried it before. I had to throw it all out and start clean because it got too confusing. For this, we turn to Snap!. Snap! is a programming language that allows telling a specific sprite to run something without changing the variables, and such you could close all issues at once by doing this:
tell[Font v]to({Write text:[SampleText] at x:(10)y:(20)::pen}@addInput::grey ring)@addInput::control
which does not set any variables to anything and runs it normally without any screen refresh. The grey ring around the Write text: command is basically a reporter only in snap that reports the block that is within it itself, instead of running it.

But since Snap! is not Scratch, I do not know if there is a way to make throwaway variables that only exist for one instance of a script (which is also a thing in snap.)

which is a shame, because that is something I could really use.

Annoyingly, my signature was eaten by a small, white dog. How annoying.




powercon5
Scratcher
1000+ posts

Faking cross-sprite procedure calls with broadcast - without lag how?

I've struggled a lot with the best way to communicate with a text engine. I usually end up using a list instead of variables for the text information. Using that to store the information for multiple pieces of text and once and then sending a single “write all text” broadcast that writes all the text for that screen refresh, that's in the list at once.

Last edited by powercon5 (April 19, 2019 15:15:14)




Witty signature.





JediChickenD
Scratcher
8 posts

Faking cross-sprite procedure calls with broadcast - without lag how?

14152cool wrote:

telling a specific sprite to run something

Yes, exactly, I wish Scratch had some version of a “tell” block!

Some languages have similar “with” constructs for establishing “scope”, but I assume either approach must somehow be “fundamentally difficult” to incorporate into Scratch or else it'd surely be there in some form already, since it's such a basic programming concept.

powercon5 wrote:

using a list instead of variables for the text information … then sending a single “write all text” broadcast

Thanks! That hadn't occurred to me, and does seem like it could get around the problem.

In fact, it might set me up to solve a couple of other related problems - assume there are other such “utility” sprites, not just “Font”, so they could perhaps have their own “to-do lists” of parameters, and I could broadcast a single “EverybodyGoDoYourDeferredRenderingNow” -type message.

But wonder if I'd run into any list-processing performance issues? Guess I'll have to solve that problem next, when I get to it.


Thanks all!

Last edited by JediChickenD (April 19, 2019 15:49:07)

Powered by DjangoBB