Discuss Scratch
- Discussion Forums
- » Suggestions
- » Scratch Workaround Guide VII
- owlover2010
-
100+ posts
Scratch Workaround Guide VII
Why is a “mouse over report” detector disallowed? Or is this the wrong place to ask?
(mouse over [love v]:: sensing)
(mouse over [fave v]:: sensing)
(mouse over [report v])
Last edited by owlover2010 (March 23, 2023 06:14:06)
- yavuz61035
-
500+ posts
Scratch Workaround Guide VII
qas would probably be better to ask in Why is a “mouse over report” detector disallowed? Or is this the wrong place to ask?(mouse over [love v]:: sensing)
(mouse over [fave v]:: sensing)
(mouse over [report v])
but its disallowed because you could make it so you need to love and fave before playing a game or you could make it so if you reported you couldnt play the game
- mumu245
-
1000+ posts
Scratch Workaround Guide VII
Could you pass me this topic? I would really like to maintain this kind of sticky!
- 5_g
-
1000+ posts
Scratch Workaround Guide VII
wdym Could you pass me this topic? I would really like to maintain this kind of sticky!
- medians
-
1000+ posts
Scratch Workaround Guide VII
She is still maintaining it. Could you pass me this topic? I would really like to maintain this kind of sticky!
- INSERT-USER_NAME
-
1000+ posts
Scratch Workaround Guide VII
uh, what?(#165)nopeShe is still maintaining it. Could you pass me this topic? I would really like to maintain this kind of sticky!
- _nix
-
1000+ posts
Scratch Workaround Guide VII
Nobody needs to argue over whether or not I'm maintaining this. I can answer for myself, so please don't feel the need to tell people that I am or am not maintaining.
Are other stickies this sought-after, I wonder…
Anyway, I haven't been keeping up with this as much as I'd like to. That's my fault. I'm gonna set aside at least one hour a week (generally on Friday or the weekend) where I check in with the guide and see what needs adding or updating. We'll see if that's something I can keep up for a while, and go from there, alright?
Are other stickies this sought-after, I wonder…

Anyway, I haven't been keeping up with this as much as I'd like to. That's my fault. I'm gonna set aside at least one hour a week (generally on Friday or the weekend) where I check in with the guide and see what needs adding or updating. We'll see if that's something I can keep up for a while, and go from there, alright?
Last edited by _nix (March 31, 2023 19:51:10)
- _nix
-
1000+ posts
Scratch Workaround Guide VII
Thanks for the suggestion! Special information about clones was loosely on my radar, because there are a ton of workarounds and cool things you can do with clones and clone IDs. (I've used them a lot.) It's a more complicated subject, so I haven't really been sure how to fit it into the guide cleanly… And… I'm still not sure, but it's something I want to do! So I got started on writing the text, and I'll figure out the formatting to make it officially part of the guide later on, when more of it is done This may cross the line of being too complex for your guide but people are frequently asking about how to do this so it might help to have workarounds (or a few workarounds) included.

Like I said, I'll come back to the thread once a week and fill in more. I'm going to edit this post with the work-in-progress, but keep in mind that it's a rough draft, so lots of stuff may change before it becomes properly part of the guide. (I'm thinking about posting it to another discussion topic, in Help with Scripts, or right at the top of a following discussion page here, because the first page is super super huge and really laggy to browse on older computers.)
Please heavens if you're going to quote this post, snip out everything below this line.
⎯⎯⎯ WIP content, here be dragons (last updated 4/7) ⎯⎯⎯
✽ x position of clone, costume # of clone, etc
Scratch doesn't have any blocks for interacting with specific clones, but there are pretty simple workarounds for most blocks that might come in handy. They're all based on using a clone ID system. Every clone has its own ID, which is a “for this sprite only” variable that is a unique number for each clone. Clone data gets updated constantly in “for all sprites” lists, and accessed from those lists whenever needed.
This is a more complicated workaround, but once you learn how to use it, you'll have a very powerful tool for all kinds of projects involving clones!
The first step is to create “for all sprites” lists for each piece of information you'll want to track, like X position, Y position, direction, costume number, and so on. Make sure you delete all from each of these lists when the green flag is clicked, because restarting the project always deletes all clones, and you don't want any old data from the last time the project was run getting in the way.
when green flag clicked
delete all of [clone X v] :: list
delete all of [clone Y v] :: list
delete all of [clone direction v] :: list
delete all of [clone costume # v] :: list
Because the order Scratch evaluates blocks in the same frame can be hard to predict, you should use “wait 0 seconds” at the start of other “when flag pressed” scripts which are going to create clones.
Now you'll want to make a new custom block which replaces “create this clone”. Make a “for this sprite only” clone ID variable, too. The custom block will create a new clone, add the current information values to the list, and set the clone ID value to the length of the information lists.
when green flag clicked
set [clone ID v] to [0]
define create and track clone of myself
add (x position) to [clone X v]
add (y position) to [clone Y v]
add (direction) to [clone direction v]
add (costume [number v] :: looks) to [clone costume # v]
set [clone ID v] to (length of [clone X v])
create clone of [myself v]
set [clone ID v] to [0]
If you're going to have clones actually create clones of themselves, change the last part to restore the clone ID to its previous value instead of resetting it to zero. Use an additional “for this sprite only” variable:
define create and track clone of myself
... :: #c0c0c0
add (direction :: #8495dd) to [clone direction v] :: #d78c76
add (costume [number v] :: #a17edd) to [clone costume # v] :: #d78c76
add this: ({set [saved clone ID v] to (clone ID)} :: ring #f4f752) :: #4c97ff
set [clone ID v] to (length of [clone X v] :: #d78c76) :: #f19865
create clone of [myself v] :: #e7bd74
add this: ({set [clone ID v] to (saved clone ID)} :: ring #f4f752) :: cap #4c97ff
Next, you'll want to have each clone update the information in the “for all sprites” lists. You want this to happen every frame, so the latest information is always in the lists. A simple way is with a forever loop:
when I start as a clone
forever
replace item (clone ID) of [clone X v] with (x position)
replace item (clone ID) of [clone Y v] with (y position)
replace item (clone ID) of [clone direction v] with (direction)
replace item (clone ID) of [clone costume # v] with (costume [number v] :: looks)
end
If your project uses an “update” broadcast loop (such as “forever: broadcast update and wait” or “forever: broadcast tick and wait”), you can skip the forever loop and just put the “replace item” blocks at the bottom of the “when I receive update” script.
Now your project is good to go! If you run it, and show the clone information lists, it should automatically fill up with the details for each clone.
If you know the ID for a clone, you can get information about it by getting it from the lists. For example, ID 3 means that the third item of clone X, the third item of clone Y, the third item of clone direction, and so on, all are the information for that clone. Here's an example script:
when green flag clicked
wait (0) seconds :: control
create and track clone of myself :: custom
forever
set x to ((50) + (item (1) of [clone X v])
set y to ((50) + (item (1) of [clone Y v])
end
when I start as a clone
forever
glide (1) secs to [random position v] :: motion
end
The clone glides somewhere random, and the original sprite follows it.
✽ for each of my clones
You can use a “for this sprite only” list, called “my clones”, to keep track of the clone ID for each clone that a sprite or clone creates of itself. Change the “create and track clone of myself” block to add the new clone ID to that list.
when green flag clicked :: #d4a47a
add this: ({delete all of [my clones v] :: list} :: ring #f4f752) :: #4c97ff
delete all of [clone X v] :: #d78c76
delete all of [clone Y v] :: #d78c76
... :: #c0c0c0
define create and track clone of myself
... :: #c0c0c0
set [saved clone ID v] to (clone ID :: #f19865) :: #f19865
set [clone ID v] to (length of [clone X v] :: #d78c76) :: #f19865
create clone of [myself v] :: #e7bd74
add this: ({add (clone ID) to [my clones v]} :: ring #f4f752) :: #4c97ff // Keep track of the new clone ID before restoring it.
set [clone ID v] to (saved clone ID :: #f19865) :: #f19865
when I start as a clone :: #e7bd74
add this: ({delete all of [my clones v] :: list} :: ring #f4f752) :: #4c97ff // The clone gets its own list of clones!
... :: #c0c0c0
Now you can loop over each item in the “my clones” list. Use a repeat loop or a “for” loop. (Look at the workaround for “for each item of list”, in Variables & Lists, for more information.)
set [index v] to [1]
repeat (length of [my clones v])
set [my clone's ID v] to (item (index) of [my clones v])
set [my clone's X v] to (item (my clone's ID) of [clone X v])
set [my clone's Y v] to (item (my clone's ID) of [clone Y v])
... do something interesting ... :: grey
change [index v] by (1)
end
✽ clone that created me, parent ID
You might want a clone to be able to get information about the clone which created it! Track that information in the “create and track clone of” block:
define create and track clone of myself
... :: #c0c0c0
add this: ({set [saved parent ID v] to (parent ID)} :: ring #f4f752) :: #4c97ff // Like clone ID, we have to restore this when we're done.
set [saved clone ID v] to (clone ID :: #f19865) :: #f19865
add this: ({set [parent ID v] to (clone ID)} :: ring #f4f752) :: #4c97ff // Set parent ID to our own ID before getting a new ID for the new clone!
set [clone ID v] to (length of [clone X v] :: #d78c76) :: #f19865
create clone of [myself v] :: #e7bd74
add this: ({set [parent ID v] to (saved parent ID)} :: ring #f4f752) :: #4c97ff
set [clone ID v] to (saved clone ID :: #f19865) :: #f19865
(Alternate variable tracking which cuts out the need for “saved clone ID”, shout me out if you like assembly code)
define create and track clone of myself
... :: #c0c0c0
remove this: ({set [saved clone ID v] to (clone ID)} :: ring #321451) :: #FF661A
add this: ({
set [saved parent ID v] to (parent ID)
set [parent ID v] to (clone ID)
} :: ring #f4f752) :: #4c97ff
set [clone ID v] to (length of [clone X v] :: #d78c76) :: #f19865
create clone of [myself v] :: #e7bd74
remove this: ({set [clone ID v] to (saved clone ID)} :: ring #321451) :: #FF661A
add this: ({
set [clone ID v] to (parent ID)
set [parent ID v] to (saved parent ID)
} :: ring #f4f752) :: #4c97ff
✽ clones and other workarounds
You can use other workarounds to make working with the clone information easier. For example, this script has a clone rotate around its parent:
(todo)
✽ Give a newly created clone a command
You can't directly use blocks in the same script to tell a new clone exactly what to do. Instead, you can use the name of the costume, or a “for this sprite only” variable, to describe the clone:
// Using costume name
set [saved costume name v] to (costume [name v] :: looks)
switch costume to [asteroid v] // or...
switch costume to [alien v] // or...
switch costume to [shooting star v]
create clone of [myself v]
switch costume to (saved costume name)
// Using a variable
set [saved clone tag v] to (clone tag)
set [clone tag v] to [performance core] // or...
set [clone tag v] to [efficiency core] // or...
set [clone tag v] to [audio controller]
create clone of [myself v]
set [clone tag v] to (saved clone tag)
Then, in a “when I start as a clone” block, check if the costume name or variable matches a specific value, and run the right behavior:
// Using costume name
when I start as a clone
if <(costume [name v] :: looks) = [alien]> then
go to [random position v]
forever
point towards [player ship v]
move (10) steps
end
end
when I start as a clone
if <(costume [name v] :: looks) = [asteroid]> then
go to [random position v]
point in direction (pick random (-180) to (180))
forever
move (2) steps
if <touching [player bullet v]> then
explode :: grey
end
end
end
// Using a variable
when I start as a clone
if <(clone tag) = [performance core]> then
do some really high-speed computations :: grey
end
when I start as a clone
if <(clone tag) = [efficiency core]> then
do lower priority computations :: grey
end
✽ broadcast to specific clone
(todo)
Last edited by _nix (April 7, 2023 19:37:46)
- medians
-
1000+ posts
Scratch Workaround Guide VII
Maybe for broadcast to specific clone, have this?
when I receive [message v]Also, switch to costume is the 1.x name for the switch costume to block.
if <(cloneid) = [1]> then
...
end
Last edited by medians (March 31, 2023 22:23:43)
- vsmeekaryo
-
66 posts
Scratch Workaround Guide VII
switch to previous costume =
define previous costume
set [previous costume v] to ((costume #)- [1])
switch costume to (previous costume)
- medians
-
1000+ posts
Scratch Workaround Guide VII
This already is in the guide. switch to previous costume =define previous costume
set [previous costume v] to ((costume #)- [1])
switch costume to (previous costume)
- 5_g
-
1000+ posts
Scratch Workaround Guide VII
i have noticed that using this block:This already is in the guide. switch to previous costume =define previous costume
set [previous costume v] to ((costume #)- [1])
switch costume to (previous costume)
foreveris significantly faster than:
next costume
end
foreveris there any way to “load” a costume for fast access?
switch costume to ((costume #) + (1))
end
- INSERT-USER_NAME
-
1000+ posts
Scratch Workaround Guide VII
I don't know if this is the right place to put this, but I made a timer variable that can be incremented or decremented, and maybe even paused once I figure out how to do that.
This is the script:
I tested it a bit and it's even accurate to the original timer variable.
This is the script:
when green flag clicked
set [timer var v] to (0)
reset timer
forever {
set [timer var v] to ((timer var) + (timer))
reset timer
}@loopArrow :: control cap
I tested it a bit and it's even accurate to the original timer variable.
- INSERT-USER_NAME
-
1000+ posts
Scratch Workaround Guide VII
I believe if you quickly switch through all the costumes the sprite has, it should effectively “load” all the costumes. i have noticed that using this block:foreveris significantly faster than:
next costume
endforeveris there any way to “load” a costume for fast access?
switch costume to ((costume #) + (1))
end
I think there's a script for this as well.
define load
repeat (costumes the sprite has) {
switch costume to ((costume [number v] :: looks) + (1))
}@loopArrow :: control
- medians
-
1000+ posts
Scratch Workaround Guide VII
Hold on, did they add that dropdown in 3.0?define load
repeat (costumes the sprite has) {
switch costume to ((costume [number v] :: looks) + (1))
}@loopArrow :: control
I’ve done that before to keep the timer in the when stop sign workaround like this: This is the script:when green flag clicked
set [timer var v] to (0)
reset timer
forever {
set [timer var v] to ((timer var) + (timer))
reset timer
}@loopArrow :: control cap
I tested it a bit and it's even accurate to the original timer variable.
when gf clickedAlso, why not just change timer var by timer?
set [timer v] to [0]
broadcast [timer code v] //that same code
Last edited by medians (April 4, 2023 01:28:07)
- INSERT-USER_NAME
-
1000+ posts
Scratch Workaround Guide VII
YesHold on, did they add that dropdown in 3.0?define load
repeat (costumes the sprite has) {
switch costume to ((costume [number v] :: looks) + (1))
}@loopArrow :: control
Those two extra blocks show off my true coding skills /kindajokingwhy not just change timer var by timer? This is the script:when green flag clicked
set [timer var v] to (0)
reset timer
forever {
set [timer var v] to ((timer var) + (timer))
reset timer
}@loopArrow :: control cap
I tested it a bit and it's even accurate to the original timer variable.
Last edited by INSERT-USER_NAME (April 4, 2023 01:33:20)
- _nix
-
1000+ posts
Scratch Workaround Guide VII
A quick and incomplete 2.0-alike color palette hand-picked with chroma.js, for “transparent” blocks:
({
turn cw (25) degrees
point towards [Sprite2 v]
} #4a6cd4 [#4a6cd4] :: ring #c7c7c7) ({
turn cw (25) degrees :: #8495dd
point towards [Sprite2 v] :: #8495dd
} #8495dd [#8495dd] :: ring #c7c7c7) :: stack #eaeaea
({
switch costume to [Bat1 v]
paint (costume [name v] :: looks) :: #c0c0c0
} #8a55d7 [#8a55d7] :: ring #c7c7c7) ({
switch costume to [Bat1 v] :: #a17edd
paint (costume [name v] :: #a17edd) :: #c0c0c0
} #a17edd [#a17edd] :: ring #c7c7c7) :: stack #eaeaea
({
wait (1) secs
repeat (3)
end
} #e1a91a [#e1a91a] :: ring #c7c7c7) ({
wait (1) secs :: #e7bd74
repeat (3) :: motion #e7bd74
end
} #e7bd74 [#e7bd74] :: ring #c7c7c7) :: stack #eaeaea
({
when green flag clicked
broadcast [message1 v]
} #c88330 [#c88330] :: ring #c7c7c7) ({
when green flag clicked :: #d4a47a
broadcast [message1 v] :: #d4a47a
} #d4a47a [#d4a47a] :: ring #c7c7c7) :: stack #eaeaea
({
set [variable v] to [foobar]
move (speed) steps :: #c0c0c0
} #ee7d16 [#ee7d16] :: ring #c7c7c7) ({
set [variable v] to [foobar] :: #f19865
move (speed :: #f19865) steps :: #c0c0c0
} #f19865 [#f19865] :: ring #c7c7c7) :: stack #eaeaea
({
delete all of [my clones v] :: list
wave to (item (1 v) of [my clones v] :: list) :: #c0c0c0
} #cc5b22 [#cc5b22] :: ring #c7c7c7) ({
delete all of [my clones v] :: #d78c76
wave to (item (1 v) of [my clones v] :: #d78c76) :: #c0c0c0
} #d78c76 [#d78c76] :: ring #c7c7c7) :: stack #eaeaea
Last edited by _nix (April 7, 2023 19:24:10)
- _nix
-
1000+ posts
Scratch Workaround Guide VII
OK, I updated the early-draft clones documentation with a new kind of syntax. Something that's kind of inconvenient to convey in a forum post is adding, removing, or changing blocks in code you already told someone to write. Videos get the advantage of just showing adding, removing or changing blocks, but forum posts are basically static! So I tried using some scratchblocks tricks. All the blocks in the WIP post should be updated, but here's one example:
Let me know what you folk think, especially if anything about this type of writing is tricky to understand or unintuitive! I've never done it before but I also haven't had to talk much about changing existing code. Hopefully this works pretty well, and I'd be glad to experiment more if it could be better or if anyone has other ideas of how to give examples of adding new blocks to, or removing blocks from, existing code.
when green flag clicked :: #d4a47a
add this: ({delete all of [my clones v] :: list} :: ring #f4f752) :: #4c97ff
delete all of [clone X v] :: #d78c76
delete all of [clone Y v] :: #d78c76
... :: #c0c0c0
define create and track clone of myself
... :: #c0c0c0
set [saved clone ID v] to (clone ID :: #f19865) :: #f19865
set [clone ID v] to (length of [clone X v] :: #d78c76) :: #f19865
create clone of [myself v] :: #e7bd74
add this: ({add (clone ID) to [my clones v]} :: ring #f4f752) :: #4c97ff // Keep track of the new clone ID before restoring it.
set [clone ID v] to (saved clone ID :: #f19865) :: #f19865
when I start as a clone :: #e7bd74
add this: ({delete all of [my clones v] :: list} :: ring #f4f752) :: #4c97ff // The clone gets its own list of clones!
... :: #c0c0c0
Let me know what you folk think, especially if anything about this type of writing is tricky to understand or unintuitive! I've never done it before but I also haven't had to talk much about changing existing code. Hopefully this works pretty well, and I'd be glad to experiment more if it could be better or if anyone has other ideas of how to give examples of adding new blocks to, or removing blocks from, existing code.
- medians
-
1000+ posts
Scratch Workaround Guide VII
Uhm, why is it not:
delete (all v) of [list v]Also what’s the point of the new colors (just wondering)