Discuss Scratch

_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII


Scratch Workaround Guide Ⅶ
༺༻


Hi there, and welcome to the 7th-or-so guide to Scratch workarounds! Please use the table of contents below to skip to the forum post which has a block you would like to learn the workaround for. Keep reading past the table of contents to learn more!
Frequently Asked Questions

What does “workaround” mean?

If you’ve spent some time programming with Scratch, there is a pretty good chance that you’ve gone looking for a block which just doesn’t exist—some kind of action or utility that you can’t find in any of the existing blocks! The Scratch Team tries to keep the list of blocks minimal, so that it isn’t overwhelming or confusing for newer Scratchers (among several other reasons). That means we have to use the blocks we do have to come up with new behavior similar to the blocks we don’t have. That’s what a “workaround” is—using what you’ve got to make something new and useful!

Someone told me my suggestion has a workaround. Does that mean there’s something wrong or bad about my idea?

Nope! Actually, it means other Scratchers have had the very same idea as you (or one which is similar), and because the block you both thought of doesn’t exist in Scratch, they came up with a way to use the blocks that do exist to do something similar. There are a number of reasons the Scratch Team doesn’t often add new blocks to Scratch. Two big ones are that they don’t want Scratch to overwhelm younger or inexperienced students, and that they want to encourage Scratchers to come up with their own solutions instead of having blocks that give all the answers right away.

When someone tells you your suggestion has a workaround, it doesn’t mean there’s anything wrong with your idea. It just means you don’t have to wait for the block to get added (which might never happen or take a really long time)—because there are ways to do what you want with the blocks that Scratch already has. It’s good to read those workarounds and try to learn how they work, if you’re interested, because by doing that, you’re practicing solving problems and learning from how other people have figured out workarounds too!

Many blocks have workarounds, but that doesn’t mean they’ll never be added to Scratch. Several blocks which were added in Scratch 3.0, such as “apple contains a?” and “item # of item in list”, had known workarounds for a long time before they were added, but the Scratch Team decided they were worth adding to Scratch in the end.

There’s a block I’m sure has a workaround, but I can’t find it here. What do I do?

This guide is still pretty young, so please feel free to add a reply to this forum thread and I’ll do my best to reply with a workaround for the block you’re looking for and fit it into the guide when I can! I’m not active every day but I usually am multiple times a week, so I’ll do my best to get back to you shortly. Others, if they keep up with new replies, might reply with their own workarounds too!

I know a workaround, but it isn’t in this guide! Will you add it?

Probably! Please share it in a reply to this forum post. Keep in mind there are a few types of workarounds I’m not that interested in adding to the guide. Those are…
  1. Workarounds for blocks which actually do exist in Scratch. Even if the approach is really creative, this guide is all about blocks which don’t exist in Scratch. Check out the Scratch Wiki for info on workarounds for existing blocks - that’s a more fitting place than here!

  2. Extra workarounds for blocks that are already in the guide, unless they take a significantly different approach. I’m happy to share more than one method, but they have to be pretty different—for example, changing the code in “repeat for seconds” to use “days since 2000” instead of “timer” wouldn’t be a significant enough change. This is somewhat based on opinion, so I apologize if you feel a change is more significant than I do (but you’re welcome to explain your reasoning in a forum post or reply and I’ll do my best to listen and consider what you say!).

  3. Workarounds for blocks with super specific or complex behavior. Even though “platformer physics” and “esey multilayer” and “cloud lists” are all great ideas to create with the blocks Scratch has, they’re too big and involved to include in a to-the-point workaround guide. Later on, I may add links to tutorials (interactive Scratch projects or other forum threads and studios) which explain these ideas in more detail, but I’m not totally decided on that yet. (I want to give the guide some more time to grow with plain old workarounds first!)
If you suggest or share a workaround and you tell me you’d like it added to the main guide, you’re giving me permission to make adjustments so that it fits the look and feel of other workarounds here. I will always give credit and link back to your original post next to the workaround I include!

Where are the previous stickied Scratch workaround threads?

There are a bunch, and I might be missing some… in which case the title of this thread is inaccurate, sorry

Here are the ones I know of, though!
  1. (2016) Ultimate List of Workarounds And More by MathlyCat
  2. (2017) The Ultimate List of Workarounds and More ②.⓪ by openPoll
  3. (2019) Workarounds to frequently suggested blocks by Computer_Fizz
  4. (2020) The Workarounds to Frequently Suggested Blocks by BearSlothCoding
  5. (2020) Helpful Workarounds for Frequently Suggested Blocks! by shradibop
  6. (2022) Workarounds for Frequently Suggested Blocks! (vers. 4) by Nezon
  7. (2022) Scratch Workaround Guide VII by _nix (You are here!)

Last edited by _nix (Feb. 25, 2024 00:24:17)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

Full Table of Contents (Find a workaround here!)

Motion, Looks & Sound
  • point towards x: y:
  • rotate around sprite:
  • rotate around x: y:
  • is showing? / visible?
  • color effect reporter, whirl, mosaic, audio effect reporters, etc
  • hide all sprites
  • previous costume
  • last costume
  • list of costume names
  • # of costumes
  • random costume
Events & Control
  • when (any condition) is true
  • boolean: “I receive (message)”
  • wait until I receive message1
  • repeat until I receive message2
  • broadcast message1 to only sprite1
  • repeat for 2 seconds
  • while (condition)
  • do … while (do … until)
  • for each whole number between 5 and 10
  • stop all scripts in this sprite
  • stop scripts in another sprite
  • is a clone?
  • delete all clones
  • # of clones
Operators & Sensing
  • true, false
  • x <= y, x >= y
  • x XOR y (exclusive or)
  • letters x to y of string
  • hexadecimal to decimal
  • x is even? x is odd? x is divisible by y? x is multiple of y?
  • x is an integer/whole number? x is a decimal/fraction?
  • decimal part of x / fractional part of x
  • round to nearest 100, round to decimal digits
  • x to the power of y (exponentiation, x^y)
  • distance to x: y:
  • mouse clicked this sprite?
  • mouse dragging this sprite?
  • turbo mode enabled?
Variables & Lists
  • item (last) of list, second to last item, etc
  • item (random) of list
  • change item 1 of list by 10
  • delete last item of list
  • for each item of list
Miscellaneous
  • return / report (from custom block)
  • extra: demo - context “right click” / double click menu (by Hotwheels_Fan101)

Last edited by _nix (April 27, 2024 17:10:57)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

Motion, Looks & Sound

point towards x: y:

Method 1: dedicated “point towards” sprite

This method uses simple motion blocks, two variables, and a broadcast message to point towards a sprite which moves itself to the position you want to point towards. You’ll need to create a new sprite for this - it doesn’t need any costumes since it isn’t for showing anything on the stage!

// In any sprite you want to use “point towards”...

set [point towards x v] to [200] // These variables are “for all sprites.”
set [point towards y v] to [120]
broadcast [prepare point towards v] and wait
point towards [point towards sprite v]

// In the dedicated “point towards sprite”...

when green flag clicked
hide // You don’t want this sprite to be visible!

when I receive [prepare point towards v]
set x to (point towards x)
set y to (point towards y)

Method 2: trigonometric “point towards”

This method uses the trigonometry function “atan” to calculate the direction between your current position and the target with math.

define point towards x: (target x) y: (target y)
point in direction ([atan v] of (((target x) - (x position)) / ((target y) - (y position)))
if <(target y) < (y position)> then
turn cw (180) degrees
end

rotate around sprite: (thanks, @hill_walker123!)

Use the basic trigonometry blocks “sin” and “cos” to follow the path a circle would make around the target sprite. (You can get those by dragging out the “abs of” block at the bottom of Operators and changing its dropdown menu.)

define rotate (degrees) degrees around (sprite)
set [direction before custom block ran v] to (direction)
set [distance v] to (distance to (sprite))
point towards (sprite)
set x to (([x position v] of (sprite)) + ((distance :: variables) * ([sin v] of (((direction) + (180)) + (degrees)))
set y to (([y position v] of (sprite)) + ((distance :: variables) * ([cos v] of (((direction) + (180)) + (degrees)))
point in direction (direction before custom block ran)
turn cw (degrees) degrees // This helps the sprite look like it's following the circle.

This script uses geometry concepts to calculate where the sprite should end up. It works by calculating a circle whose center is exactly on the target sprite, and one of its points is where the running sprite is (so its radius is the distance from the running sprite to the target sprite). It uses that circle to calculate where the sprite would be if it followed an arc (of specified degrees) around the circle.

A lot of the blocks here have to do with converting between values that work for trigonometry math, and converting them back into the right values to put onto the actual screen.
  1. The “cos” and “sin” blocks expect a direction from 0 to 360 while Scratch's “direction” block goes from -180 to +180, so we add 180.
  2. “cos” and “sin” don't actually deal with distances at all, they just assume you're talking about a circle with radius 1, so we multiply the results by the distance between the running and target sprites to scale to the right radius.
  3. “cos” and “sin” also don't deal with position, they assume you're talking about a circle centered at (0, 0). So, we use normal addition blocks to translate (move) the point so it's relative to the target sprite.
(Note that this exact workaround will make jagged lines if you're drawing with pen blocks, since it moves in two steps. You can replace the “set x” and “set y” blocks with a single “go to x: y:” block and it'll work the same way.)

rotate around x: y:

Method 1: follow a circle from the current position (thanks, @1080GBA!)

This method combines the workarounds for “point towards x: y:” (earlier in this post) and “distance to x: y:” (see this post!) with a little bit of trigonometry. It's right if you want your sprite to rotate around some position, making a circle which includes where the sprite is already positioned!

define rotate (degrees) degrees around x: (x) y: (y)
set [direction before custom block ran v] to (direction)
get distance to x: (x) y: (y) :: custom // Check out the workaround for this!
point towards x: (x) y: (y) :: custom // Check out the workaround for this, too!
set x to ((x) + ((distance to position) * ([sin v] of (((direction) + (180)) + (degrees)))))
set x to ((x) + ((distance to position) * ([cos v] of (((direction) + (180)) + (degrees)))))
point in direction (direction before custom block ran)
turn cw (degrees) degrees // This helps the sprite look like it's following the circle.

Like with the workaround for rotate around sprite: (right above this one), we're adding +180 to Scratch's “direction” block, because “cos” and “sin” expect 0 to 360, and “direction” gives -180 to 180. We're also still multiplying by the distance, which makes the radius of the circle—and this time, we're using another workaround to calculate that distance! Finally, we use normal addition blocks to translate (move) the sprite to be centered around that position.

(If you're drawing with the pen, this will make jagged lines. Combine the “set x” and “set y” blocks into one big “go to x: y:” block and it'll draw a smooth circle.)

Method 2: make a totally new circle
(This method is a bit different to @Malicondi's workaround, but it's based on it—thanks!)

This method completely ignores the sprite's current position, so you specify the radius and current number of degrees around the circle yourself. It can be useful for making more complex animations!

define go to circle around x: (x) y: (y) direction: (dir) radius: (radius)
set x to ((x) + ((radius) * ([sin v] of (dir))
set y to ((y) + ((radius) * ([cos v] of (dir))

The direction input uses the same rules as Scratch's “point in direction” block: 0 is straight up, 90 is to the right, 180 is straight down, and so on.

(If you're drawing with the pen, this will make jagged lines. Combine the “set x” and “set y” blocks into one big “go to x: y:” block and it'll draw a smooth circle.)

is showing? / visible?

Method 1: set variable at the same time as hide/show

Scratch doesn’t let you directly know whether or not a sprite is visible, but you can keep track using variables.

define hide and remember
hide
set [visible? v] to [false]

define show and remember
show
set [visible? v] to [true]

Method 2: set variable first, show/hide later

If your project uses an “update” or “render” broadcast loop (like many Scratch games do), you can use a variable to represent whether the sprite is shown or not, and reflect the change just once at the end of the broadcast.

when I receive [update v]
...
if <some condition :: grey> then
set [visible? v] to [true]
else
set [visible? v] to [false]
end
...
if <(visible?) = [true]> then
show
else
hide
end

color effect reporter, whirl, mosaic, audio effect reporters, etc

You can use the same approaches for “visible?” for other attributes that Scratch doesn’t outright let you access, too.

Remember that some effects, like color, “loop” at a certain point - 100 is completely the opposite colors, 200 is back to normal, so 50 and 250 make the same result, for example.(note) You can use the “mod” operators block to keep the value within a specific range, as long as you know at what value it loops.

when green flag clicked
clear graphic effects
set [color effect v] to [0]
forever
change [color v] effect by (10) :: looks
change [color effect v] by (10)
if <((color effect) mod (200)) > [100]> then
set [mosaic v] effect to [10]
else
set [mosaic v] effect to [0]
end
end

Note: Technically, even though the color effect does loop at every multiple of 200, the value zero is “special” and disables the effect entirely. At color 100, whites and grays are tinted blue; at 200, they are tinted red. That repeats every 200: at 400, whites/greys are tinted red and at 300, they're tinted blue. If you want to check if, for example, the color effect is “reddish” or “close to normal”, you could do (color mod 200 < 40 or color mod 200 > 160) and (not color = 0). See this post for discussion.

Other effects don’t do anything different past a certain point: -50 brightness is dark, -80 is darker, and -100 is completely black; anything even further negative won’t make the sprite darker than pitch black. If you want, you can use a script like this to keep the variable constrained:

when green flag clicked
forever
if <(brightness effect) > [100]> then
set [brightness effect v] to [100]
else
if <(brightness effect) < [-100]> then
set [brightness effect v] to [-100]
end
end
end

hide all sprites

Use a broadcast:

broadcast [hide all sprites v] and wait

// Put this in every sprite:

when I receive [hide all sprites v]
hide

You can also use events like “when backdrop switches to (backdrop2)” and put them in only specific sprites to have more control over which sprites hide and show, and when they do.

previous costume

Method 1: subtract from costume number

Use the costume number block and subtract 1:

switch costume to ((costume [number v] :: looks) - (1))

You don't need to use a workaround for backdrops — the “switch backdrop to” block already has a “previous backdrop” option.

Method 2: put literal string “previous costume” in input (thanks, @musicROCKS013!)

Scratch also supports using the plain old text “previous costume” inside the input. You can't type it directly into the dropdown, but you can use a “join” block to make it fit:

switch costume to (join [previous c] [ostume])

You can also “trick” Scratch into putting the text “previous costume” in the input. Check out the details (or backpack the block!) in this project.

last costume / final costume

Switch to the costume numbered zero:

switch costume to ((0) + (0))

Scratch automatically “wraps” the current costume number when you go past the end or before the start. It’s a loop, so that “forever: next costume” works. It works in the other direction too: zero is one before the first costume, so it wraps back to the end.

list of costume names

You can automatically create a list of costume names by starting from the first costume and looping “next costume” until you reach the end and go back to the first, adding the current costume name to a list each time:

delete all of [costume names v] :: list
switch costume to ((0) + (1)) // So you can start at whatever is the first costume!
repeat until <<(costume [number v] :: looks) = [1]> and <(length of [costume names v]) > [0]>>
add (costume [name v] :: looks) to [costume names v]
next costume
end

We use “and length of costume names > 0” in the loop so that we don’t stop before we’ve even begun looping. On the first iteration, the list is always empty. We add an item to the list right away, so then we’re ready to stop as soon as we get back to costume 1. This works even if the sprite only has a single costume!

This will always switch the costume back to 1 in the end, so if you need to restore the original costume after running this code, keep the original costume in a variable:

set [original costume v] to (costume [name v] :: looks)
... // all the code in the previous script
switch costume to (original costume)

# of costumes

Method 1: length of list of costume names

If you’ve already collected a list of the sprite’s costume names (using the workaround for that), you can just get the length of the list.

set [# of costumes v] to (length of [costume names v])

Method 2: switch to last costume, then costume #

Switch to the last costume by switching to costume # zero, then get the costume #:

switch costume to ((0) + (0))
set [# of costumes v] to (costume [number v] :: looks)

This will obviously change the current costume, so if it’s important to restore the original costume, keep it in a variable:

set [original costume v] to (costume [name v] :: looks)
switch costume to ((0) + (0))
set [# of costumes v] to (costume [number v] :: looks)
switch costume to (original costume)

random costume (thanks, @medians!)

Method 1: reuse “# of costumes” variable

If you've already used one of the above workarounds to get the number of costumes the sprite has, you can reuse that variable:

switch costume to (pick random (1) to (# of costumes :: variables))

Method 2: switch to last costume, then random

This method doesn't need a variable at all:

switch costume to ((0) + (0)) // Scratch "wraps" the number 0 to mean "last costume"
switch costume to (pick random (1) to (costume [number v] :: looks))

You actually don't need to use either of these workarounds for backdrops, because “switch backdrop to” already has a “random backdrop” option!

Last edited by _nix (April 27, 2024 17:10:03)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

Events & Control

when (any condition) is true (thanks, @INSERT-USER_NAME!)

Scratch has a handy “when” block with a menu to activate something when certain conditions are true, but the only options are “timer” and “loudness”, so it's a little limited. Handily, though, the “timer” option is all we need to make it work for any other condition too:

when [timer v] > ((timer) - <(costume [name v] :: looks) = [costume4]>
say [Wowie wow! I look like a taco now!] for (3) seconds :: looks

Just put whatever condition you want inside the “minus” (-) block. This uses a trick where true conditions (booleans) are treated as 1, and false is treated as 0. So, if the custom condition you used is false, Scratch is basically doing this…

when [timer v] > ((timer) - (0))

The timer checks if it's greater than itself, and that's never true—the timer, like any normal number, is equal to itself!

As soon as the condition is true, now Scratch is subtracting 1, and the result will always be true: the timer is always greater than one less than itself.

Keep in mind, Scratch's “when” block only activates once when its condition becomes true. So watch out for something like this:

when [timer v] > <(timer) - <<(x position) = [50]> or <(x position) = [100]>>>

This will activate if the sprite goes to x = 50 or goes to x = 100—from any other x position. If it goes directly from 50 to 100, or from 100 to 50, it won't activate again: as far as Scratch is concerned, nothing changed, because the overall condition (“x = 50 or x = 100”) went from true to true. There needs to be at least one frame where the condition is false for the “when” block to run again.

You can use “repeat until” and other normal Scratch control blocks to keep doing something while the condition is true (you'll just have to copy the condition into the “repeat until” block—with a “not” block, so you repeat UNTIL the condition is FALSE).

boolean: “I receive (message)”

This block is rejected because its meaning is a little ambiguous. Check out one of the other blocks below for the specific behavior you’re looking for!

wait until I receive message1

Use a variable to keep track of whether or not you’ve received the broadcast. (Choose “for this sprite only” when you create it.) The important thing is that you reset it right when you start waiting - that way you’ll only stop waiting once you receive the broadcast again, if you’ve received it before!

set [have I received message1? v] to [false]
wait until <(have I received message1?) = [true]>
say [I received it!] for (1) secs

when I receive [message1 v]
set [did I receive message1? v] to [true]

repeat until I receive message2

Use basically the same approach as “wait until I receive”, but with the “repeat until” block instead:

set [have I received message2? v] to [false]
repeat until <(have I received message2?) = [true]>
turn cw (30) degrees
end
say [I received it!] for (1) secs

when I receive [message2 v]
set [did I receive message2? v] to [true]

broadcast message1 to only sprite1

Method 1: broadcast to one sprite (thanks, @yavuz61035!)

Set a variable to the name of the sprite you want to respond. Broadcasts are always received by every sprite, so every place where you use “when I receive” with that message, check if the variable matches the name of that sprite:

ask [Who's going to dance next?] and wait
set [who's receiving do a cool dance v] to (answer)
broadcast [do a cool dance v] and wait
play sound [Hooray! v] until done

when I receive [do a cool dance v] // in Gobo's code
if <(who's receiving do a cool dance) = [Gobo]> then
point in direction (45 v)
repeat (4)
repeat (10)
move (10) steps
end
turn cw (90) degrees
end
end

when I receive [do a cool dance v] // in Tera's code
if <(who's receiving do a cool dance) = [Tera]> then
set rotation style [left-right v]
repeat (5)
point in direction (90 v)
glide (1) secs to x: (50) y: (100)
point in direction (-90 v)
glide (1) secs to x: (50) y: (-50)
end
end

It's generally best if you use a different variable for each “targeted” broadcast. That way, if you broadcast two or more different messages at the same time, you'll make sure each message gets where it's going!

Method 2: broadcast to 2+ specific sprites at the same time

It's not possible to broadcast one message twice in the same Scratch frame—it'll just be received once. So if you want to broadcast to two specific sprites, you'll have to use a list:

delete all of [who's receiving sing along v] :: list
add [Dee] to [who's receiving sing along v]
add [Devin] to [who's receiving sing along v]
add [Sam] to [who's receiving sing along v]
add [Scratch Cat] to [who's receiving sing along v]
broadcast [sing along v]

when I receive [sing along v]
if <[who's receiving sing along v] contains [Scratch Cat]> then
set [pitch v] effect to (0) :: sound
repeat (3)
play sound [Meow v] until done
change [pitch v] effect by (20) :: sound
end
end

Method 3: without stopping/restarting broadcasts

Keep in mind that if you broadcast something which sprites are already responding to right now, Scratch will interrupt and restart all the “when I receive” scripts with the same message. If you want to make sure the sprites who already started keep going after you broadcast the message again (maybe to another sprite), you can use a variable and the “wait until” or “forever…if” blocks.

when I receive [join the team v]
if <(who's joining the team) = [Pico]> then
set [part of the team v] to [true] // local variable, "for this sprite only"
end

when green flag clicked
set [part of the team v] to [false]
wait until <(part of the team) = [true]>
forever
... follow the leader ... :: grey
end

In the example above, if you didn't use an extra variable (for this sprite only) and just put the forever block inside the if block, you would only ever have one sprite following the leader at once!

But remember: if you're making a different kind of project, it may find the way Scratch interrupts broadcasts useful! For example, a music project where one special instrument is in solo at a time: broadcasting again with a new sprite will stop the current solo and then start the new solo. And if you set the “who's receiving” variable to a sprite which doesn't exist (or just “nobody”), it'll stop the current solo without starting a new one!

repeat for 2 seconds

Method 1: timer variable and “repeat until” loop

Use a variable to add a number of seconds to the current timer. This variable represents the time when the repeat loop should stop. When the timer goes past that value, the loop stops.

set [when to stop v] to ((timer) + (2))
repeat until <(timer) > (when to stop)>
turn cw (10) degrees
change size by (2)
end

We use the “>” block instead of “=” because the timer is actually a pretty precise decimal value. For example, the timer might be 0.438 when we set the “when to stop” variable (to 2.438). Eventually the timer would reach something close to 2.438, but it might actually keep getting bigger without ever exactly equalling 2.438, because Scratch scripts don’t run 1000 times a second - only 30 times!

Method 2: wait block and broadcast interruption / canceling

If you’re using more loops inside your “repeat for seconds” block, or you have some other blocks which take time (like “glide”), you can use a special behavior of broadcasts to “cancel” the inside of the loop and stop whatever is being run in the loop, even if it’s only partway through.

set [loop finished? v] to [false]
broadcast [inside loop v] // note this is NOT a “broadcast and wait” block
wait (2) secs
set [loop finished? v] to [true]
broadcast [inside loop v]

when I receive [inside loop v] // make sure you use a different message for each loop
if <(loop finished?) = [false]> then
forever
... // the inside of the loop here, for example:
point in direction (90)
glide (0.75) secs to x: (100) y: (0)
point in direction (-90)
glide (0.75) secs to x: (-100) y: (0)
end
end

while (condition)

Method 1: “repeat until not” loop

Use the “repeat until” block and put a “not” block (from the Operators category) around the condition:

repeat until <not <(x position) < [150]>>
change x by (10)
end

“Repeat until” keeps going until the condition is true. “While” keeps going until the condition is false. Since they’re reverses of each other, you can use “not” to reverse the condition and get the same effect as using “while”.

Method 2: hacked “while” block

(!) Please note that although hacked blocks like this one are a functioning part of the Scratch language, their usage isn't officially supported by the Scratch Team. There is a chance that projects using hacked blocks may be marked NFE, preventing the project from appearing on the front page or under the Explore section.

Scratch 2.0 and Scratch 3.0 have a hidden, “hacked” block called “while”. It’s exactly what the typical “while” loop is in other programming languages:

while <(y position) < [120] :: operators> {
change y by (20)
} :: control loop
while <(y position) > [0] :: operators> {
change y by (-10)
} :: control loop

You can get the “while” block by dragging it to your backpack from another Scratch project, like this one.

do … while (do … until)

In other programming languages, it’s common to want to always perform the inside of a loop once, even if the condition starts out as false. You can get the same type of behavior by storing the condition in a variable and making the variable start out as true:

set [condition v] to [true]
repeat until <(condition) = [false]>
go to [random position v]
set [condition v] to <touching [mouse pointer v] ?>
end

for each whole number between 5 and 10

Method 1: “repeat” loop

Calculate the difference between the start and end, then increment a variable that many times:

set [number v] to (start :: grey)
repeat (((end:: grey) - (start :: grey)) + (1))
say (join [The number is: ] (number)) for (1) secs
change [number v] by (1)
end

We add 1 so that the loop is inclusive: if start is 5 and end is 10, this will count 5, 6, 7, 8, 9, 10. Or, if start and end are the same, it’ll still run the script, but only once, with just that one value!

Method 2: “repeat until” loop

Start at the initial position, then keep incrementing a variable until you pass by the end:

set [number v] to (start :: grey)
repeat until <(number) > (end :: grey)>
say (join [The number is: ] (number)) for (1) secs
change [number v] by (1)
end

We use “greater than” instead of “equals” so that the loop is inclusive. It’ll run the script for the start value, the end value, and everything in between.

This method also makes it easy to count up by a number other than 1, like counting by 0.25 or 10.

stop all scripts in this sprite

You can combine two “stop script” blocks to stop both all other scripts in a sprite and the current script at the same time:

...
if <some condition :: grey> then
stop [other scripts in sprite v]
stop [this script v]
end
do something :: grey

Note that if you plan on placing this at the end of a script, there’s no need to include “stop this script”, since that script doesn’t plan on doing anything after “stop other scripts in sprite” runs anyway.

stop scripts in another sprite

Use a broadcast:

// In sprite1...

broadcast [stop scripts in sprite2 v] and wait

// In sprite 2...

when I receive [stop scripts in sprite2 v]
stop [other scripts in sprite v]

You can also use blocks like “hide” here if you’re planning on “shutting down” the sprite and taking it away from the current scene.

is a clone?

Use a variable—and make sure you set it to “for this sprite only” when you create it!

when green flag clicked // this will only be run by the original sprite, not clones
set [is a clone? v] to [false]

when I start as a clone // this will only be run by clones (of course!)
set [is a clone? v] to [true]

Then you can use this variable when responding to broadcasts—compare it to false if there’s a broadcast you want only the original sprite to react to, not clones.

delete all clones

When you send a broadcast, all sprites and clones will react to it. You can use the “delete this clone” block connected to a broadcast to make all the clones of the sprite the “when I receive” is in get deleted when you send that broadcast.

broadcast [delete all clones v] and wait

when I receive [delete all clones v]
delete this clone

# of clones

Use a variable—make sure this is “for all sprites” (the default) when you create it. Increment it (add 1) whenever a clone is created, and decrement (subtract 1) whenever you delete it. You can make a custom “delete this clone and keep track” custom block to help remember:

when green flag clicked
set [# of clones v] to [0]

when I start as a clone // in every sprite which gets cloned
change [# of clones v] by (1)

define delete this clone and keep track
change [# of clones v] by (-1)
delete this clone

Last edited by _nix (Nov. 17, 2022 23:55:08)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

Operators & Sensing

true, false

It’s okay to just use the strings “true” or “false” most of the time:

set [I am a dog? v] to [true]
set [snakes are slimy? v] to [false]

Some Scratchers prefer to use 1 and 0 since they fit math expressions easier, and are more concise.

If you really need the boolean values specifically, you can use conditionals that you always know the value of. It’s handy to save these values in global variables (“for all sprites”) for use across a project:

set [true v] to <[5] < [10]>
set [false v] to <[5] > [10]>

set [true v] to <not <>> // Empty input is treated as false, not false = true
set [false v] to <not <not <>>> // not not false = not true = false

You can’t put variables or any round reporters directly in boolean slots, but you can use comparison blocks:

if <<touching [snake v] ?> and <(snakes are slimy?) = [true]>> then
start sounds [Scream1 v] :: sound
say [Yikes!!!] for (2) secs
end

x <= y, x >= y

Method 1: “not” block

Use the “not” block around the opposite condition:

<(answer) ≤ [20] :: operators> …is the same as… <not <(answer) > [20]>> :: grey

<(y position) ≥ [100] :: operators> …is the same as… <not <(y position) < [100]>> :: grey

For two numbers x and y, only one of these can be true: x is less than y, x is equal to y, x is greater than y. When you’re asking about two of those conditions, you’re really just ruling out the third, so we use the “not” block with that third condition to simulate checking for the other two.

Method 2: “or” block

Alternatively, you can use the “or” block:

<<(answer) < [20]> or <(answer) = [20]>>
<<(y position) > [100]> or <(y position) = [100]>>

This is more direct and might be easier to understand, but the downside is you have to write out the numbers/blocks twice.

x XOR y (exclusive or)

“Exclusive or” means “one condition is true, but not both” (compared to normal “or”, which means “one condition is true, or both conditions are true”).

Method 1: basic boolean blocks only

You can construct the same meaning out of plain old “and”, “or”, and “not” blocks together:

<<<x :: grey> or <y :: grey>> and <not <<x :: grey> and <y :: grey>>>>

Since this method involves writing out the conditions twice, and it's a bit of a hassle to read/write every time, you can use a custom block with boolean arguments to make it easier:

define exclusive <x> or <y>
set [xor v] to <<<x> or <y>> and <not <<x> and <y>>>>

Method 2: equals block (compare booleans)

Another way to understand “xor” is “are these two conditions different?” Because XOR means only one of the values is true, and the other is false. You can use boolean blocks inside the “=” block just like any other blocks, and then use “not” to ask “are they NOT the same?”:

<not <<x :: grey> = <y :: grey>>

Method 3: addition block (sum booleans) (thanks, @D-ScratchNinja!)

You can also treat booleans like numbers. If a boolean is true, it's treated as the number 1. If it's false, it's treated as 0 (zero). Thanks to that, you can use math blocks on booleans in clever ways:

<(<x :: grey> + <y :: grey>) = (1)>

The only way x + y = 0 is if both x and y are false (x = 0, y = 0). The only way x + y = 2 is if both are true (x = 1, y = 1).

There are two ways x + y = 1: either x is true and y is false (x = 1, y = 0) or x is false and y is true (x = 0, y = 1). Those are what we're looking for: x + y = 1 only if x and y are different, and that's what “exclusive or” means.

letters x to y of string

You can use a loop with an increasing variable to start at the first position and keep going until you move past the last position, appending the current letter to the end of a variable each time.

define get letters (start) to (stop) of (string)
set [substring v] to [] // Empty string
set [parse v] to (start)
repeat until <<(parse) > (stop)> or <(parse) > (length of (string))>
set [substring v] to (join (substring) (letter (parse) of (string)))
change [parse v] by [1]
end

hexadecimal to decimal

Scratch can turn hexadecimal numbers (like FF) to decimal numbers (like 255) just by putting the hexadecimal in any math block. Make sure you include the special two characters 0x (zero then X) before the number. You can’t type this in number inputs, but if you get it from blocks like “ask and wait”, a variable, or the “join” block, it will work.

ask [what is the number in hexadecimal?] and wait
set [hexadecimal v] to (join [0x] (answer))
set [decimal v] to ((1) * (hexadecimal))
say (join (join (hexadecimal) [ in decimal is ]) (decimal))

x is even? x is odd? x is divisible by y? x is multiple of y? (thanks, @medians!)

Method 1: “x mod 2” and zero-comparison

The “mod” operator, which is short for “modulo” (and usually represented by % in other programming languages), tells you the remainder of dividing the second number into the first. If it's zero, that means divisor divides into the dividend evenly. (10 mod 5 = 0, 13 mod 5 = 3, 13 mod 6 = 1.)

All even numbers are divisible by 2, and all odd numbers aren't, so you can compare the result of a “mod 2” with 0 to tell if a number is even:

<((5) mod (2)) = [0]> // false
<((316) mod (2)) = [0]> // true

You can use the “not” block to check if it's odd. But you can save a block by comparing with 1 instead of 0, since that's the only other possible remainder for x ÷ 2:

<((612) mod (2)) = [1]> // false
<((1025) mod (2)) = [1]> // true

Note that for “mod 2 = 1”, you'll only get proper results for integers (whole numbers). If what you're really interested in is “is this divisible by 2?”, compare with 0, which works for decimals as well (2.25 mod 2 = 0.25, which isn't zero, and 2.25 isn't divisible by 2).

Method 2: “x mod y” and zero-comparison

You can use the modulo operator to check other divisibility, too:

ask [How many eggs do we need?] and wait
if <<(answer) mod (12)> = [0]> then
say (join [OK, we will buy ] (join ((answer) / (12)) [ dozen!]))
end

You can use a “not” or “if/else” block to check if it isn't divisible. Like with 2, you can save a block, but it's different: the remainder when dividing by 5 could be 0, 1, 2, 3, or 4. So check if the answer is greater than zero to tell if it's any value besides zero (since the remainder is never negative):

ask [How many bugs will defend the fort?] and wait
if <(answer) > [100]> then
if <<(answer) mod (25)> > [0]> then
say [Sorry, only multiples of 25 if you want more than 100 please]
end
end

x is an integer/whole number? x is a decimal/fraction?

Method 1: Check if divisible by 1

Integers (and whole numbers) are all divisible by 1: if you divide 3 by 1 you don't have any remainder, while 3.25 divided by 1 gets you a remainder of 0.25. You can check the remainder of a division with the “mod” block:

<((32) mod (1)) = [0]> // 0 = 0: true
<((13.37) mod (1)) = [0]> // 0.37 = 0: false

Replace the equals block with greater than (>) if you're checking if the number isn't an integer.

Method 2: Compare with rounded value (thanks, @1080GBA!)

Compare the value with itself—but rounded—and use a “not” block if you're checking if it's a decimal:

ask [Choose graphics resolution 1 (blocky) to 10 (detailed):] and wait
if <not <(answer) = (round (answer))>> then
say [Whole number resolution only, please] for (3) seconds :: looks
stop [this script v]
end
... more answer validation ... :: grey

decimal part of x / fractional part of x

Method 1: remainder of division by 1

For positive numbers, you can use the “mod” block to divide your number by 1 and get the remainder:

((8) mod (1)) // 0
((8.25) mod (1)) // 0.25
((8.50) mod (1)) // 0.5
((8.75) mod (1)) // 0.75
((9) mod (1)) // 0

The “mod” block is a little more complicated when working with negative numbers. (It returns the amount the first number is above the previous greatest multiple of the second number, so -6 mod 3 = 0, -5 mod 3 = 1, -4 mod 3 = 2.)

If the number you're checking is (or might be) negative, use “abs” to make it positive before giving it to “mod”:

(([abs v] of (-1.125)) mod (1)) // 0.125

Method 2: subtract floor from entire number

If you're only working with positive numbers (including fractions between zero and positive one), use the Operators category “of” block to subtract the “floor” of a number from itself (“floor” means “round down”):

set [whole part v] to ([floor v] of (timer))
set [decimal part v] to ((timer) - (whole part))

// or just

((variable) - ([floor v] of (variable))

If the value is (or might be) negative, the same idea works if you make the value positive using the “abs” (absolute value) option:

(([abs v] of (variable)) - ([floor v] of ([abs v] of (variable))))

round to nearest 100, round to decimal digits

Method 1: round to nearest 5, 25, 100, 2, 0.25, etc

If you only want to display a value up to a certain amount of precision, you can use division, rounding, and multiplication (in that order) to get a rounded answer:

define round (number) to nearest (precision)
set [rounded v] to ((round ((number) / (precision))) * (precision))

Method 2: only get rid of small decimal values

The math system Scratch uses sometimes gives answers which are very tiny fractions of 1 off from the expected value (such as 0.1 + 0.2 = 0.30000000000000004). If you want to only keep a certain number of digits, you can use a combination of multiplication, rounding, and division (in that order) to get a rounded answer:

define round (number) to (digits) decimal digits
set [rounded v] to ((round ((number) * ([10 ^ v] of (digits)))) / ([10 ^ v] of (digits))

Keep in mind that this method only works for rounding off decimal places—the “round” block won’t do anything to values which are already whole numbers!

Replace “round” with “floor” if you want to truncate the decimals at the end without caring if they start with 5 or greater. (For example, if you want to bring 0.2468 to 3 decimal digits, using “round” will get you 0.247, and using “floor” will get you 0.246.)

x to the power of y (exponentiation, x^y)

Method 1: repeated multiplication/division (integer exponent only)

This method is simple and easy to understand. You can skip the “else” part if you don’t care about exponents which are negative. Keep in mind, though, that this will only work for integer (whole number) exponents, since you can’t repeat a loop 2.247 times, for example!

define raise: (base) to exponent: (exponent) (method 1)
set [power v] to [1]
if <<(exponent) = [0]> or <(exponent) > [-1]>> then
repeat (exponent)
set [power v] to ((power) * (base))
end
else
repeat (exponent)
set [power v] to ((power) / (base))
end
end

Method 2: logarithms

This method uses Scratch’s logarithm blocks, 10^/log and e^/ln, to calculate exponentiation. (The example uses 10^ and log, but you can swap them with e^ and ln; the result is the same.) The answer also may not be a perfect integer - if it’s crucial that the answer is a whole number (like if you’re comparing it to another whole number), make sure to use a “round” block on the result.

define raise: (base) to exponent: (exponent) (method 2)
set [power v] to ([10 ^ v] of ((exponent) * ([log v] of ([abs v] of (base)))))
if <(base) < [0]> then
set [power v] to ((-1) * (power))
end

distance to x: y:

You can use the “sqrt” block (square root) together with multiplication to perform the Pythagorean theorem in Scratch! It's easier than it sounds:

define get distance to x: (x) y: (y)
set [square of x difference v] to (((x) - (x position)) * ((x) - (x position))
set [square of y difference v] to (((y) - (y position)) * ((y) - (y position))
set [distance to position v] to ([sqrt v] of ((square of x difference) + (square of y difference))

This also works for getting the distance between any two points, if you change the “x position” and “y position” blocks. You don't need the extra variables, they're just to help you read: you can put those blocks right into the big sqrt equation if you want.

mouse clicked this sprite?

Method 1: separate variable with reset

Use a variable, and reset it right before you start waiting or repeating:

when this sprite clicked
set [mouse clicked? v] to [true]

say [Click me to continue.] :: looks
set [mouse clicked? v] to [false]
wait until <(mouse clicked?) = [true]>
say [] // say nothing
broadcast [continue v]

(Tip: You can use the same idea to wait or repeat until you receive a broadcast! Check the Events & Control section.)

Method 2: separate variable and wait until (thanks, @Little_Mittle12345!)

If you want to use a simple variable all on its own, you can put a “wait until” block after the “when this sprite clicked” code above:

when this sprite clicked
set [mouse clicked? v] to [true]
wait until <not <mouse down?>>
set [mouse clicked? v] to [false]

when green flag clicked
set [mouse clicked? v] to [false]

This variable will work just about anywhere, including forever loops!

Method 3: mouse touching and mouse down (thanks, @1080GBA!)

If you want to get something like the “click” effect but in a loop which is always running (maybe grouping other code for interactive stuff), you can use the Operators category “and” block with two Sensing blocks:

when green flag clicked
forever
... other game controls ... :: grey
if <<touching [mouse-pointer v] ?> and <mouse down?>> then
change size by (10)
turn cw (20) degrees
end
end

Note that this will still run the code if you started clicking somewhere else and then dragged the mouse over the sprite, so it's a little different from the “when this sprite clicked” block.

mouse dragging this sprite?

Method 1: wait until not mouse down
Please note: this method is NOT compatible with the “set drag mode: draggable” block.

If you want a reporter you can use anywhere, you can control a variable with one script—choose “for this sprite only” when you make the variable:

when this sprite clicked
set [mouse dragging this sprite? v] to [true]
wait until <not <mouse down?>>
set [mouse dragging this sprite? v] to [false]

when green flag clicked
forever
if <(mouse dragging this sprite?) = [true]> then
set [ghost v] effect to (50)
go to [mouse-pointer v]
else
set [ghost v] effect to (0)
end
end

If you don't want to use a new variable (maybe you only need to know about “dragging” in one part of the sprite), you can just use the more direct sensing and control blocks as part of your existing script:

when this sprite clicked
set [ghost v] effect to (50)
repeat until <not <mouse down?>>
go to [mouse-pointer v]
end
set [ghost v] effect to (0)

This method doesn't work if you are using “set drag mode: draggable”. That's because “drag mode: draggable” changes the way “when this sprite clicked” works, so that it only activates when you let go of the sprite (mouse up) and didn't start dragging the sprite at all (so you kept the mouse in just the one place after pressing it down).

Method 2: separate forever loop instead of “when this sprite clicked”

If you want to use the “set drag mode: draggable” Sensing block, it will work with this more complicated method:

when green flag clicked
set drag mode [draggable v] :: sensing
forever
if <<not <mouse down?>> and <touching [mouse-pointer v] ?>> then
wait until <<mouse down?> or <not <touching [mouse-pointer v] ?>>
if <touching [mouse-pointer v] ?> then
set [ghost v] effect to (50)
wait until <not <mouse down?>>
set [ghost v] effect to (0)
end
end
end

Every frame, this checks if the mouse is over the sprite, but not pressed. (This is called “hovering” over the sprite.) If so, it pauses and waits until either the mouse is pressed or the mouse is moved away. If the mouse didn't move away, we already know the mouse is pressed, because that's the only other way the “wait until” block ends. So that means a drag has started on top of this sprite.

You can use “repeat until (not mouse down)” instead of “wait until (not mouse down)” if you want to there to be some sort of fancy animation while the sprite is being dragged.

turbo mode enabled?

A variety of turbo mode detectors exist, but here’s a simple one:

when green flag clicked
repeat (10)
wait (0) secs
end
set [turbo enabled? v] to <(timer) < (0.1)>

It’s important to use the right comparison block - drag out “<”, timer less than 0.1.

This works because turbo mode takes blocks which usually cause Scratch to wait for one frame and makes them instantaneous. (Turbo mode tries to run as many frames of code as it can possibly fit in one actual frame—that’s why most animations go really fast when it’s enabled.) Ten frames is 10 * 0.33 = about 0.34 seconds, but with turbo mode it runs almost instantly, and you can detect that with the timer block.

Last edited by _nix (April 27, 2024 16:31:54)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

Variables & Lists

item (last) of list, second to last item, etc

Method 1: “length of list” block and subtraction

Use the “length of list” block:

(item (length of [my list v]) of [my list v])

You can also use the subtraction (minus) block to get an item that’s near the end, but not quite at it:

(item ((length of [my list v]) - (1)) of [my list v])

Method 2: put word “last” directly in item input

You can also just copy the word last and paste it right into the “item of” block. (Please note that you can’t type it in - you have to paste the whole word all at once.)

(item [last] of [my list v])

If you have a hard time getting this to work, you can drag the block into your backpack from another Scratch project, like this one.

item (random) of list

Method 1: “pick random” block

Use the “pick random” and “length of list” blocks:

(item (pick random (1) to (length of [my list v])) of [my list v])

Method 2: put word “random” directly in item input

You can also just copy the word random and paste it right into the “item of” block. (Like with “last”, you have to paste this word all at once.)

(item [random] of [my list v])

If you have a hard time getting this to work, you can drag the block into your backpack from another Scratch project, like this one.

change item 1 of list by 10

Method 1: operate in-place

This method is useful if you’re doing one simple operation, like increasing a value.

replace item (1) of [my list v] with ((item (1) of [my list v]) + (10))

Method 2: store in a variable, then put variable back in the list

This method is useful if you’re doing a more complex operation made out of multiple blocks (like other math-related custom blocks), or if you need to do something else with the value after you’ve changed it.

set [item value v] to (item (1) of [my list v])
change [item value v] by (10)
replace item (1) of [my list v] with (item value)

delete last item of list

Method 1: “length of list” block

Use the “length of list” block:

delete (length of [my list v]) of [my list v]

If you want to remember the value and use it for something else (like the “pop” function in other programming languages), you can store it in a variable before removing it from the list:

set [popped value v] to (item (length of [my list v]) of [my list v])
delete (length of [my list v]) of [my list v]

Method 2: put word “last” directly in item input

Like with the “item of” block, you can also just copy the word last and put it right into the “delete” block. (Like always with this trick, you have to paste the word all at once.)

delete [last] of [my list v]

If you have a hard time getting this to work, you can drag the block into your backpack from another Scratch project, like this one.

for each item of list

Method 1: “item #” variable and “repeat until” loop

Use an “item #” variable (also commonly called “parse” or “index”) and a loop:

set [item # v] to [1]
repeat until <(item #) > (length of [my list v])>
if <(item (item #) of [my list v]) = [something]> then
do something :: grey
end
change [item # v] by [1]
end

Please note that you’ll have to be careful if you decide to add or remove items to/from the list while you’re inside this loop.

Inserting an item will move all the items after where it was inserted over by 1. So, if you insert an item at where “item #” is, that means you’ll also process that item on the next iteration of the loop. If you want to skip the new item, make sure to use an extra “change item # by 1” when you insert it. Similarly, if you insert it before where “item #” is, you’ll end up looping over and over the same item, since the item you were on is now moved over 1 (it matches the movement of your item # variable).

Removing an item has the converse caveat: every item after where it was removed will move back by one. If you remove the item at the current item # (causing everything after it to shift left), and then increment item # before proceeding, you’ll end up skipping an item! Make sure to either “change item # by -1” when removing an item at or before the current item #, to cancel out “change item # by 1”, or just don’t run “change item # by 1” at all if you detected an item to be removed.

Method 2: hacked “for each” block

(!) Please note that although hacked blocks like this one are a functioning part of the Scratch language, their usage isn't officially supported by the Scratch Team. There is a chance that projects using hacked blocks may be marked NFE, preventing the project from appearing on the front page or under the Explore section.

Scratch 2.0 and Scratch 3.0 have a hidden, “hacked” block called “for each”. It counts from 1 up to the number provided. This is often perfect for counting through the items in a list:

for each [item # v] of (length of [my list v]) {
if <(item (item #) of [my list v]) = [something]> then
do something :: grey
end
} :: control loop

You can get the “for each” block by dragging it to your backpack from another Scratch project, like this one.

Conveniently, the “for each” block calculates the block in its number input each time. That means it works like “repeat until (item # = length of list)”, not just “repeat (length of list)”. Be careful, though: if you never stop adding items to the list, the loop will keep running forever (up to the max number of items in a list in Scratch 3.0, two hundred thousand).

Last edited by _nix (Feb. 13, 2023 11:26:35)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

Miscellaneous

return / report (from custom block)

Method 1: “stop this script”

If the main thing you want is to stop the custom block from running any blocks further, you can use the “stop this script” block. It will only stop the code of the custom block, not the script which is calling the custom block.

when green flag clicked
forever
determine if alive :: custom
if <(alive?) = [true]> then
player controls until dead
end
end

define player controls until dead
forever
determine if alive :: custom
if <(alive?) = [false]> then
stop [this script v]
end
… player controls stuff … :: grey
end

Method 2: variables

If you’re making a custom block which calculates something, you can use a variable to keep track of the result and access it from the script which is calling the custom block.

define get last letter of (string)
set [last letter v] to (letter (length of (string)) of (string))

define get a funny word
set [funny word v] to (item (pick random (1) to (length of [funny words v])) of [funny words v])

when green flag clicked
say (join [Hello ] (username)) for (2) secs
say [Let’s make you a code name!] for (2) secs
say [Your code name is...] for (2) secs
get last letter of (username)
get a funny word
say (join (join (letter (1) of (username)) (funny word)) (last letter))

Method 3: “return” list

If it’s important that you can run a custom block more than once and keep track of all the results easily, you can use a “return” list to save more than one result.

define check if custom control (control name) is pressed
set [index v] to (item # of (control name) in [custom control names v] :: list)
if <key (item (index) of [custom control keys v]) pressed?> then
add [true] to [return v]
else
add [false] to [return v]
end

forever
delete all of [return v] :: list
check if custom control [jump] is pressed
check if custom control [defend] is pressed
if <(item (1) of [return v]) = [true]> then
if <(item (2) of [return v]) = [false]> then
jump :: custom
end
end
...
end

extra: demo - context “right click” / double click menu by Hotwheels_Fan101

Visit the project! This is a simple context menu example which uses variables and a “when stage clikced” block (in the Stage) to detect clicking twice within a short time. Note that the Stage includes two example scripts, one which disables the context menu under certain backdrops and one which doesn't, so you'll have to choose the one which works for your project or remove one if you want to try it out.

Last edited by _nix (July 2, 2022 23:18:15)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

(One extra reserved post, just in case it comes in handy later on!)

══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
ScolderCreations
Scratcher
1000+ posts

Scratch Workaround Guide VII

So this is going to be the new sticky? Congratulations!

_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

ScolderCreations wrote:

So this is going to be the new sticky? Congratulations!
Thanks! Yup, it will be – with permission from the runner of the previous thread.

It'll take a little longer than I estimated (like 30 minutes instead of 15 ) to get the rest of the posts copied over, but the Motion, Looks & Sounds section is ready if you're curious what the thread will look like

══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

And…bam! The thread is good to go. Thanks to Nezon, the runner of the previous thread, for passing the thread on to me!

My goal with this new tutorial-style approach is to help Scratchers better learn and understand new workarounds, and maybe get them creatively thinking about solving problems and coming up with new approaches on their own.

I'm also happy to take suggestions for more workarounds to include here—just make sure to read the part about that in the FAQ. Hopefully we can help fellow forumers out here!

══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
musicROCKS013
Scratcher
1000+ posts

Scratch Workaround Guide VII

Reported to be stickied. Congrats!


Shift + Down arrow to see the rest of my signature

Hello Scratch Team. You have been pushing a liberal political agenda on this site for far too long. This site should stay out of politics. People should be able to still post their political opinions, but there shouldn’t be any “official” political stance or Scratch. The ST is not going to change this on their own, and shoot down any attempts asking them to change. Please put this in your signature if you agree that

Scratch should be politically neutral.

The ST’s biggest defense is that they’re being welcoming, but they can be perfectly welcoming of all people and stay out of politics. Scratch is about coding, and that should be the Scratch Team’s biggest concern to maintain.






This is my signature. I am allowed to adertize here.

_______________\/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/
Please Click —> This project is literally my life's work. <— Please Click
_______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Jenny LeClue is the best
RL1123
Scratcher
1000+ posts

Scratch Workaround Guide VII

Congratulations on the pending sticky, _nix! It seems like you've worked extremely hard on this, I'm glad that we had a great successor to Nezon's sticky and I really like the style of how it's structured.



through tough thorough thought, though














Signature #11
HeliosTheSuperior
Scratcher
100+ posts

Scratch Workaround Guide VII

here before stickied which isnt rlly an accomplishment but ya know

You see, sensei~
I love how deep your voice can get. I've been recording and collecting it as MP3s.
I've gone absolutely crazy. From the Internet, I downloaded Audacity.
Cutting, pasting, until it was complete.
“Sensei whispering his love to me.mp3” <3

Hello, I'm Helios and I use they/xe/he >:​​^)
I'm an artist and a writer and I do cool stuff. :​​P
I'm currently working on my first-person story Teacher's Pet Chronicles! The story is about a girl who tells on one student, and then becomes thirsty to tattle on them all! But some classmates aren't easy targets, some are almost impossible to tattle on. Can she remove all of them from the classroom? Will her teacher notice her actions? Hmm…
I'm also working on a collection of poems called “I Wish I Were Them”. It's about a boy who is obsessed with the lives of others.
k0d3rrr
Scratcher
1000+ posts

Scratch Workaround Guide VII

Just wanted to say, congratulations, before this gets stickied.

It's disappointing that the previous workarounds sticky was short-lived (only lasting 13 pages/244 posts), but by the looks of things, this will be an improvement on the previous sticky!

Rules that can only be seen on the forums:
Eagle138
Scratcher
500+ posts

Scratch Workaround Guide VII

Congrats on the sticky, this looks amazing! I like how you explain how the workarounds work instead of just listing them.

~ Eagle38
coder/artist/noob animator :: he/they :: unconventional :: comment ‘e’ on my profile if you see this
just call me Eagle
fancy signature banner coming…one day
yavuz61035
Scratcher
500+ posts

Scratch Workaround Guide VII

congrats on the sticky!

also, there is another method for (# of costumes)


set [old costume v] to (costume [number v] :: looks)
set [costumes v] to [1]
switch costume to ((0) + (0))
repeat (2)
next costume
end
repeat until <(costume [number v] :: looks) = [1]>
next costume
change [count v] by (1)
end
switch costume to (old costume)

Last edited by yavuz61035 (June 13, 2022 16:15:52)


i am yavuz61035!

i like birds (especially budgies) | my studio is here! | a project i was working on, mine game! | pronouns: he/him/they/blabla ok just use anything please stop reading this part | my 100th post! | be moist wet | musicROCKS013 predicts the future

fun fact: my pfp has pride month forever
a link

little social experiment corner:
increase gen thingy:
gen: 14
gen: 14
gen: 11
scratchgodo
Scratcher
1000+ posts

Scratch Workaround Guide VII

Thanks for the help reporting to be a sticky topic

Wow this topic is lagging my tablet

Last edited by scratchgodo (June 12, 2022 08:46:38)


(Thanks to butterfly_cat8 for part of the thumbnail for Cat TV used in this banner.)

Suggest purple things on my profile I can feed to Cat Posts, Cat Comments, Cat Replies or even better the Cat Profile in the link.
1080GBA
Scratcher
500+ posts

Scratch Workaround Guide VII

oh themn i have to wait for a takeover again
ive waited for a few rounds

yavuz61035 wrote:

congrats!

also, there is another method for (# of costumes)


set [old costume v] to (costume [number v] :: looks)
set [costumes v] to [1]
switch costume to ((0) + (0))
repeat (2)
next costume
end
repeat until <(costume [number v] :: looks) = [1]>
next costume
change [count v] by (1)
end
switch costume to (old costume)
i did it already in the old one
Better:
set [old costume v] to (costume [number v]::looks)
switch costume to (0)
set [count v] to (costume [number v]::looks)
switch costume to (old costume)

Last edited by 1080GBA (June 12, 2022 11:11:33)


Follow 1080GBA forever::#1080ba hat
⠀⠀⠀⠀
Made by 1080GBA. All copyrights reserved.
————————————————————————————————————————————————————————————————————

custom cat block fixed
————————————————————————————————————————————————————————————————————
3000th post

500th post
————————————————————————————————————————————————————————————————————
(((((((((((KING::#ff0000 ring)::#ff8800 ring)::#ffff00 ring)::#88ff00 ring)::#00ff88 ring)::#00ffff ring)::#0088ff ring)::#0000ff ring)::#8800ff ring)::#ff00ff ring)::#ff0088 ring)
————————————————————————————————————————————————————————————————————
<<<<<<<<1080GBA::#000>::#222>::#444>::#666>::#888>::#aaa>::#ccc>::#eee>
————————————————————————————————————————————————————————————————————
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

Thank you for all the congrats, everyone! I'm very grateful

yavuz61035 wrote:

also, there is another method for (# of costumes)

... snip ... :: grey
switch costume to ((0) + (0))
repeat (2)
next costume
end
repeat until <(costume [number v] :: looks) = [1]>
next costume
change [count v] by (1)
end
... snip ... :: grey
This is a clever idea (so thanks to 1080GBA for suggesting it in the earlier thread too!)—I like how the “repeat until” loop only needs one conditional. It reminds me that I could have used my own “do…while” workaround to calculate the list of costumes:

delete all of [costume names v] :: list
switch costume to ((0) + (1))
set [condition v] to [false]
repeat until <(condition) = [true]>
add (costume [name v] :: looks) to [costume names v]
next costume
set [condition v] to <(costume [number v] :: looks) = [1]>
end

This requires an extra variable, though

When I'm adding a workaround, I try to think of the simplest way to do it—the one which requires the least previous understanding of other topics. So like, these are great ways to use loops to calculate how many costumes there are (or to make a list of costume names), but a Scratcher reading it does need to understand how to use loops for stuff besides animation for the workaround to make sense.

That doesn't mean I don't want to teach new concepts with workarounds—that's actually the main point of this thread! But, I'm careful to pick and choose which new ideas I want to focus on. In the Control section, for example, talking about loops (and unique ways of using them) is really natural, because the person who is reading is already learning about control structures and different kinds of loops. But complex ways of using loops don't fit the Looks section quite as well, because there, the reader is probably way more interested in animating their sprites with handy blocks than anything to do with customized control structures.

That's why in the Looks section, I try to place a focus on unique behavior of Scratch looks blocks: I combine “switch to final costume” (switch costume to 0 + 0) with “costume number” because it's pretty intuitive when you think about it, and it shows a creative way to get more useful behavior from another workaround. I think it's an interesting solution to the problem which focuses on Looks behavior, teaching relevant new concepts and showing a different way of solving the problem than you might've thought of, hopefully helping spark new ideas and solutions to more involved problems later on

BTW, this is why a bunch of workarounds have more than one method, especially in the Control section where what you're doing is more abstract—if I can't decide between two approaches and they both show educational, focused ways to tackle the problem, I include ‘em both! So when the reader compares, they aren’t just choosing which one they like better…I'm also sneakily tricking them into noticing the differences and learning how they might choose between two solutions to their own unique coding challenges :D

══ trans autistic lesbian enbydoggirls // 16 17 18 19 20 21, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula

Powered by DjangoBB