Discuss Scratch

Miner3141
Scratcher
56 posts

New sensing block?

I am trying to code my own photoshop program in scratch, where the person inputs a picture into a sprite, draws it with pen, and removes the sprite. Then, the colors are added to the pen to create a new photo.

The easiest way (and only) I can think to detect any color is by using

<touching color [#ffffff v] ?>
This would detect any color that a sprite or mouse is on.

However, is there a way to do this with the current scratch blocks?

Another block that would be handy is the
go to [1 v] block in [this script v]
This can be used to easily jump to the top of a script (or anywhere) so that unnecessary blocks are cut out of the “equation”.

Can I do this with the blocks we have now?
_nix
Scratcher
1000+ posts

New sensing block?

It's generally best to keep your different suggestions separated into multiple discussion topics; it might seem a little spammy, but it really isn't, and it helps keep discussion organized a lot better (since each topic is only used to discuss one suggestion).

In any case, some thoughts on the second suggestion:

Miner3141 wrote:

Another block that would be handy is the
go to [1 v] block in [this script v]
This can be used to easily jump to the top of a script (or anywhere) so that unnecessary blocks are cut out of the “equation”.

Can I do this with the blocks we have now?
I'm not totally sure what you mean by “unnecessary blocks”, but it sounds like you could probably just use an “if” block for that? A basic example:

when green flag clicked
ask [What's the code?] and wait
if <(answer) = [secret!!!]> then
say [Correct!] for (2) secs
repeat (10)
turn cw (36) degrees
end
else
say [Incorrect.] for (2) secs
end
say [Goodbye.] for (2) secs
Miner3141
Scratcher
56 posts

New sensing block?

I'm not totally sure what you mean by “unnecessary blocks”, but it sounds like you could probably just use an “if” block for that?

When I say this stuff, I mainly mean more advanced login systems or decrypting systems.

For example:
when green flag clicked
repeat (3)
ask [what is the password?] and wait
if <(answer) = (password)> then
say [Correct!] for (2) secs
else
say [Incorrect. Try again.] for (2) secs
end
end
would not work, because if you got the password right on your first attempt, it would still repeat 3 more times.

Instead, use:
when green flag clicked
set [tries v] to [1]
ask [what is the password?] and wait
if <(answer) = (password)> then
say [Correct!] for (2) secs
else
if <(tries) < (3)> then
say [Incorrect. Try again.] for (2) secs
change [tries v] by [1]
go to [3 v] block in [this script v]
else
say [You have run out of tries] for (2) secs
stop [all v]
end
end
This would allow the code to jump back to the 3rd block on every retry (the ask for block)

Another good example is a decryption system:
when green flag clicked
ask [Text to encrypt] and wait
broadcast [encrypt v]
when green flag clicked
add [a] to [alphabet v]
add [b] to [alphabet v]
add [c] to [alphabet v]
...
define find [letter] in list alphabet
...
when I receive [encrypt v]
repeat (length of (answer))
decrypt letter (letter (icon) of (answer))
...
end
define decrypt letter (letter)
find (letter) in list alphabet
go to ((output) + (2)) of [this script v]
convert [a] to (10)
convert [b] to (11)
...
define convert (letter) to (number)
...
In this way, it would automatically jump to the letter that needs converting

Last edited by Miner3141 (Jan. 20, 2018 13:45:07)

_nix
Scratcher
1000+ posts

New sensing block?

Miner3141 wrote:

I'm not totally sure what you mean by “unnecessary blocks”, but it sounds like you could probably just use an “if” block for that?

When I say this stuff, I mainly mean more advanced login systems or decrypting systems.

For example:
when green flag clicked
repeat (3)
ask [what is the password?] and wait
if <(answer) = (password)> then
say [Correct!] for (2) secs
else
say [Incorrect. Try again.] for (2) secs
end
end
would not work, because if you got the password right on your first attempt, it would still repeat 3 more times.
In this case a breakable loop would probably work. These aren't built right into Scratch, but there are ways to do it anyways. Here's an example which would work for your code:

when green flag clicked
attempt to log in
if <(logged in) = [false]> then
say [Failed to log in: too many attempts.] for (4) secs
stop [this script v]
else
say [Logged in!] for (2) secs

define attempt to log in
set [logged in v] to [false]
repeat (3)
ask [What is the password?] and wait
if <(answer) = (password)> then
set [logged in v] to [true]
stop [this script v] // the "break" part!
else
say [Incorrect. Try again.] for (2) secs
end
end

Alternatively, you could rewrite your code to use a “repeat until” block:

when green flag clicked
set [answer var v] to [(any incorrect value)]
set [count v] to [1]
repeat until <<(answer) = (password)> or <(count) = (4)>>
ask (join (join [Attempt ] (count)) [: What is the password?]) and wait
set [answer var v] to (answer)
change [count v] by (1)
end
if <(answer) = (password)> then
say [Logged in!] for (2) secs
end

(I use an “answer var” block so that the code doesn't remember the previously-entered answer. It would be better if we had a “do while” loop, of course – “do (ask for password) while (answer != password)” )

Miner3141 wrote:

Another good example is a decryption system:
It looks like you're using your “go to block” block to make a mapping of letters to special ID codes (maybe for encrypting text to be stored in cloud data). But I think I see a way to make your script a lot simpler.

You already have a “find letter in list alphabet” block, right? This returns (or rather, stores in the “output” variable) the index of the passed letter in the alphabet list. Well, why not use that index to get an item from another list - one containing the IDs of each letter?

when green flag clicked
delete (all v) of [alphabet v]
delete (all v) of [letter IDs v]
add [a] to [alphabet v]
add [10] to [letter IDs v]
add [b] to [alphabet v]
add [11] to [letter IDs v]
...

define get id of letter (letter)
find (letter) in list alphabet :: custom
set [letter ID v] to (item (output) of [letter IDs v]

But back to the suggestion itself, now that I understand it better (thanks for the examples!). I think that the “go to block” block is flawed in two big ways (but both of these are fixable, and I'll show how in a moment):

  1. What if you insert a block into the script? This would make the number in “go to (number) of this script” be wrong. For example, if I add the block “play sound (pop)” to “decrypt letter”, the entire “decrypt letter” block doesn't work anymore. If output = 1, it would do “go to 3 of this script”, which is the “go to output+2 of this script” block itself - and then it would run that block again, causing an unintentional infinite loop! Using a “go to (n) of this script” block would force you to be very careful with where you insert blocks in your script. Forgetting to change an index would cause bugs that are hard to find. As such, the block itself simply wouldn't be very friendly or easy to use.

  2. The number isn't clear. How do I know what block “3”, in your password-login example, refers to? I mean, obviously it means “the third block of the script”, but which is the third block? For example, I don't know if “when green flag clicked” counts as a block or not. Or maybe “go to #3 block in this script” means to jump to the third block within that “C” block; take a look at this script and tell me where block #4 is:

    when green flag clicked
    say [Press the mouse down to rescue me from the aliens!!]
    forever
    turn cw (15) degrees // spin effect, for fun
    if <mouse down?> then
    go to (4) of [this script v]
    end
    change y by (10) // move the sprite up- by a greater amount than the distance below, so the net +Y is +7, or up
    change y by (-3) // move the sprite down- when the mouse is pressed, the "move 10 up" block will be skipped
    end

    See, my code assumes block 4 of this script means “change y by -3”. So if the mouse is down, net Y is -3 (so the sprite is “pulled” down), and if the mouse is up, net Y is +7 (so the sprite rises). However, Scratch itself doesn't know what I'm trying to do, and another person viewing my code probably doesn't either. Scratch (and the other person) could read that “block 4” means any of these:

    a) Block 4 is “turn 15 degrees”: (1) When green flag clicked, (2) Say…, (3) Forever, (4) Turn 15 degrees.
    b) Block 4 is “if mouse down?”: (1) Say…, (2) Forever, (3) Turn 15 degrees, (4) If mouse down?.
    c) Block 4 does not exist: there is no block after the third block, “forever”.
    d) Block 4 does not exist: there is no fourth block inside “if mouse down?”.

    In fact, none of these are even the block we want (remember, it's change Y by -3). For Scratch to know it's that block, it would have to realize that we want it to be “go to (4) of the forever block”, but how is it supposed to know that? We could say “go to (4) of (3) of this script” ("go to the fourth block [change Y by -3] of the third block [forever] of this script"), but that's also rather confusing and doesn't have any clear meaning when just being read by a person viewing your code (which may well be a later you yourself!).

Okay, but, I told you there was a simple solution of sorts.

The common theme here is that the “(n)” input does not have a clear meaning. A number referring to a block is confusing.

So what do we want? For it to have a clear meaning!

How to do this itself, however, is not entirely simple. Two hypothetical solutions come to mind:

  1. Instead show a block inside that script. That would look like this:

    when green flag clicked
    forever
    if <mouse down?> then
    go to ({change y by (-3)} :: grey ring) :: obsolete
    end
    change y by (10)
    change y by (-3)
    end

    This makes it obvious what block would be jumped to. It also makes it a lot easier to program: no matter where I add a block to that script, it will still clearly jump to the “change y by -3” block.

    It's not perfect, though; what if I have two change y by (-3) blocks, which both look identical?

    when green flag clicked
    forever
    change y by (-3)
    if <mouse down?> then
    go to ({change y by (-3)} :: grey ring) :: obsolete
    end
    change y by (10)
    change y by (-3)
    end

    Now it's not clear which block it jumps to. I suppose you could make it highlight exactly what block it's referring to when you hover over the input, but that's not really intuitive. (An invisible link to another block which can only be seen when hovering over the input? That's surprising..) - And what if I made a book or a static document where you couldn't use your (effectively nonexistant) mouse to highlight which block?

  2. Use “labels” instead:

    when green flag clicked
    forever
    if <mouse down?> then
    go to label [go down]
    end
    change y by (10)
    label: [go down]
    change y by (-3)
    end

    Basically instead of jumping to a block by its appearance or by its index in the script, you jump to a particular label block. (I use text inputs for the “go to label” block, but it could instead be a “label” dropdown, which would work the same way as broadcast dropdowns; a list of all labels, and a “create a label” button.)

Oh, and one last thought I had: what would it mean to jump to a block inside a loop, especially if we were not already executing from within that loop? Here's an example script:

when green flag clicked
if <(days since 2000) > [5000]> then
go to label [past 5000 days]
end
forever
ask [What do you want to do?] and wait
if <(answer) = [cheat]> then
go to label [past 5000 days]
end
if <(answer) = [wait]> then
wait (5) secs
end
if <(days since 2000) > [5000]> then
repeat (8)
change x by (5)
label: [past 5000 days]
say [Wow!!!! It's been 5000 days since the year 2000!] for (1) secs
turn cw (90) degrees
end
stop [all v]
end
end

This script prompts the user what they want to do until it becomes at least 5000 days since 2000. If it's already been 5000 days since 2000 when the project starts, it immediately skips to the “past 5000 days” label. (The user can also skip there by entering “cheat”.)

My question for you is: when the label “past 5000 days” is jumped to, how many times does the sprite turn 90 degrees? And how many times does it move right 5 pixels? (Or, more specifically, what happens after “turn 90 degrees” runs? Does it loop 7 times more, or does it just stop? And if it does loop, from where does it loop – from “change x by 5”, or from the label we jumped to, “past 5000 days”?)



In essence, my thoughts so far have boiled down to this: Using this feature confuses me, and would probably confuse other people too. It has so far been seen that any script which uses it can be written without it, and often in a simpler way anyways.

Sorry for the colossal posts; thanks for bearing with my thoughts! This has been really interesting for me to think and write about.
Miner3141
Scratcher
56 posts

New sensing block?

Using this feature confuses me, and would probably confuse other people too. It has so far been seen that any script which uses it can be written without it, and often in a simpler way anyways.

I see what you mean…thanks!
TEAMWFS
Scratcher
100+ posts

New sensing block?

Miner3141 wrote:

I don't really wanna include this, because it is long and I wanna keep this post short.
Can't you just use:
when green flag clicked
broadcast [login v]
when I receive [login v]
ask [What is the password?] and wait
if <(answer) = (password)> then
say [Correct!]
else
say [Incorrect!]
change [tries v] by (1)
broadcast [login v]
end

Last edited by TEAMWFS (Jan. 21, 2018 23:07:17)

Powered by DjangoBB