Discuss Scratch

iamunknown2
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

In other programming languages like JavaScript, there exists something called **prototyping** and **objects**. They work like clones, but with more abilities like storing variables which belong to the clone (which can get very useful).

After a bit of thinking, I think that the best way to implement this is through a c-block:

run as clone {
} :: control

Coupled with the ability to create and use clone variables (you would create a set of clone variables for a sprite, which would then be copied and used by each instance of clones.

How would this be better than the hat block we already have?

Since the hat block can't be put anywhere other than the front of a script, it suffers from limitations - for example, if I was making a game in which you had to battle many NPCs, I would be using one sprite as the “prototype” and use it as the source for all my clones. However, what if I wanted the NPCs to have different stats (health, attack, defence, speed)? What if I wanted the NPCs to use different costumes?

It could work like this:

What if I wanted custom starting HPs for each clone, based on the level of the game?

This sort of system would work best with something like this:

define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
run as clone {
set clone's [HP v] to (HP) :: variables
set clone's [ATK v] to (ATK) :: variables
set clone's [DEF v] to (DEF) :: variables
set clone's [SPD v] to (SPD) :: variables
more stuff here :: grey
} :: control

when gf clicked
forever
wait (5) secs
repeat (10)
Create Create ninja with ((level) * (30)) HP, ((level) * (50)) ATK, ((level) * (10)) DEF, ((level) * (5)) SPD :: custom
end
end

My idea for clone-only variables is simple; to use clone variables, you must enable “clonable” in the settings for the variable. When a clonable variable is cloned, the clone will be using its own version of the variable; if you change the clone-only version of the local variable, it will only affect the variable of the clone who changes it, and will not affect the original local variable or the variables of other clones.

Sort of like this:
Variable 1 (clonable)
|
|- Variable 1 clone, but belongs to clone 1; if you change this in clone 1, none of the other branches are changed
|
|- Variable 1 clone, but belongs to clone 2; if you change this in clone 2, none of the other branches are changed
|
|- Variable 1 clone, but belongs to clone 3; if you change this in clone 3, none of the other branches are changed
|
|- etc

Last edited by iamunknown2 (April 3, 2017 00:51:16)

duckboycool
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

You can set a varible to local, and do this.
when I start as a clone
set [Clone? v] to [true]

...
broadcast [run as clone v]

when I receive [run as clone v]
if <(clone?) = [true]> then
...
end
I assume this is how it would work anyway. If not, can you explain.
iamunknown2
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

duckboycool wrote:

You can set a varible to local, and do this.
when I start as a clone
set [Clone? v] to [true]

...
broadcast [run as clone v]

when I receive [run as clone v]
if <(clone?) = [true]> then
...
end
I assume this is how it would work anyway. If not, can you explain.
What if you had to do this for, say, HP (which is a range from, say, 1 to 100)? It would be quite inefficient for you to manually program all cases from HP = 1 TO HP = 100.

Last edited by iamunknown2 (April 2, 2017 01:52:23)

iamunknown2
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

BUMP
WolfCat67
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

iamunknown2 wrote:

duckboycool wrote:

You can set a varible to local, and do this.
when I start as a clone
set [Clone? v] to [true]

...
broadcast [run as clone v]

when I receive [run as clone v]
if <(clone?) = [true]> then
...
end
I assume this is how it would work anyway. If not, can you explain.
What if you had to do this for, say, HP (which is a range from, say, 1 to 100)? It would be quite inefficient for you to manually program all cases from HP = 1 TO HP = 100.
when I start as a clone
set [HP v] to [100]
forever
if <touching [something v]?> then
change [HP v] by (-1)
do HP calculations :: custom
end
end
define do HP calculations
if <(HP) > [80]> then
...
end
if <<(HP) < [81]> and <(HP) > [60]>> then
...
end
continue this pattern :: grey
iamunknown2
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

WolfCat67 wrote:

iamunknown2 wrote:

duckboycool wrote:

You can set a varible to local, and do this.
when I start as a clone
set [Clone? v] to [true]

...
broadcast [run as clone v]

when I receive [run as clone v]
if <(clone?) = [true]> then
...
end
I assume this is how it would work anyway. If not, can you explain.
What if you had to do this for, say, HP (which is a range from, say, 1 to 100)? It would be quite inefficient for you to manually program all cases from HP = 1 TO HP = 100.
...
What if I wanted custom starting HPs for each clone, based on the level of the game?

This sort of system would work best with something like this:

define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
run as clone {
set clone's [HP v] to (HP) :: variables
set clone's [ATK v] to (ATK) :: variables
set clone's [DEF v] to (DEF) :: variables
set clone's [SPD v] to (SPD) :: variables
more stuff here :: grey
} :: control

when gf clicked
forever
wait (5) secs
repeat (10)
Create Create ninja with ((level) * (30)) HP, ((level) * (50)) ATK, ((level) * (10)) DEF, ((level) * (5)) SPD :: custom
end
end

Last edited by iamunknown2 (April 3, 2017 00:29:49)

WolfCat67
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

iamunknown2 wrote:

WolfCat67 wrote:

iamunknown2 wrote:

duckboycool wrote:

You can set a varible to local, and do this.
when I start as a clone
set [Clone? v] to [true]

...
broadcast [run as clone v]

when I receive [run as clone v]
if <(clone?) = [true]> then
...
end
I assume this is how it would work anyway. If not, can you explain.
What if you had to do this for, say, HP (which is a range from, say, 1 to 100)? It would be quite inefficient for you to manually program all cases from HP = 1 TO HP = 100.
when I start as a clone
set [HP v] to [100]
forever
if <touching [something v]?> then
change [HP v] by (-1)
do HP calculations :: custom
end
end
define do HP calculations
if <(HP) > [80]> then
...
end
if <<(HP) < [81]> and <(HP) > [60]>> then
...
end
continue this pattern :: grey
What if I wanted custom starting HPs for each clone?
Replace all “create clone” blocks with this:
create clone of myself with () HP :: custom
define create clone of myself with (health) HP
set [HP v] to (health)
create clone of [myself v]

Last edited by WolfCat67 (April 3, 2017 00:27:56)

iamunknown2
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

WolfCat67 wrote:

iamunknown2 wrote:

WolfCat67 wrote:

iamunknown2 wrote:

duckboycool wrote:

You can set a varible to local, and do this.
when I start as a clone
set [Clone? v] to [true]

...
broadcast [run as clone v]

when I receive [run as clone v]
if <(clone?) = [true]> then
...
end
I assume this is how it would work anyway. If not, can you explain.
What if you had to do this for, say, HP (which is a range from, say, 1 to 100)? It would be quite inefficient for you to manually program all cases from HP = 1 TO HP = 100.
when I start as a clone
set [HP v] to [100]
forever
if <touching [something v]?> then
change [HP v] by (-1)
do HP calculations :: custom
end
end
define do HP calculations
if <(HP) > [80]> then
...
end
if <<(HP) < [81]> and <(HP) > [60]>> then
...
end
continue this pattern :: grey
What if I wanted custom starting HPs for each clone?
Replace all “create clone” blocks with this:
create clone of myself with () HP :: custom
define create clone of myself with (health) HP
set [HP v] to (health)
create clone of [myself v]
How would you keep track of the HP?
iamunknown2
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

*Deleted*

Last edited by iamunknown2 (April 3, 2017 00:41:46)

WolfCat67
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

iamunknown2 wrote:

WolfCat67 wrote:

iamunknown2 wrote:

WolfCat67 wrote:

iamunknown2 wrote:

duckboycool wrote:

You can set a varible to local, and do this.
when I start as a clone
set [Clone? v] to [true]

...
broadcast [run as clone v]

when I receive [run as clone v]
if <(clone?) = [true]> then
...
end
I assume this is how it would work anyway. If not, can you explain.
What if you had to do this for, say, HP (which is a range from, say, 1 to 100)? It would be quite inefficient for you to manually program all cases from HP = 1 TO HP = 100.
when I start as a clone
set [HP v] to [100]
forever
if <touching [something v]?> then
change [HP v] by (-1)
do HP calculations :: custom
end
end
define do HP calculations
if <(HP) > [80]> then
...
end
if <<(HP) < [81]> and <(HP) > [60]>> then
...
end
continue this pattern :: grey
What if I wanted custom starting HPs for each clone?
Replace all “create clone” blocks with this:
create clone of myself with () HP :: custom
define create clone of myself with (health) HP
set [HP v] to (health)
create clone of [myself v]
How would you keep track of the HP?
Make an HP bar part of the sprite, and then use my above method using the “do HP calculations” custom block to change the costume based on what it is.
TheMonsterOfTheDeep
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

…How is this different from what we have now?
define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
set [HP v] to (HP) //These are all "for this sprite only"
set [ATK v] to (ATK)
set [DEF v] to (DEF)
set [SPD v] to (SPD)
more stuff here :: grey
create clone of [myself v]

Last edited by TheMonsterOfTheDeep (April 3, 2017 03:27:33)

iamunknown2
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

TheMonsterOfTheDeep wrote:

…How is this different from what we have now?
define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
set [HP v] to (HP) //These are all "for this sprite only"
set [ATK v] to (ATK)
set [DEF v] to (DEF)
set [SPD v] to (SPD)
more stuff here :: grey
create clone of [myself v]
Wait, are the variables clone-only?
TheMonsterOfTheDeep
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

iamunknown2 wrote:

TheMonsterOfTheDeep wrote:

…How is this different from what we have now?
define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
set [HP v] to (HP) //These are all "for this sprite only"
set [ATK v] to (ATK)
set [DEF v] to (DEF)
set [SPD v] to (SPD)
more stuff here :: grey
create clone of [myself v]
Wait, are the variables clone-only?
Each clone has a copy of the value, if that's what you mean

Last edited by TheMonsterOfTheDeep (April 3, 2017 03:27:26)

kenny2scratch
Scratcher
500+ posts

Clone-restricted variables + "do in clone" c-block

TheMonsterOfTheDeep wrote:

define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
set [HP v] to (HP) //These are all "for this sprite only"
set [ATK v] to (ATK)
set [DEF v] to (DEF)
set [SPD v] to (SPD)
more stuff here :: grey
create clone of [myself v]
One small thing you're missing:
define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
set [publicHP v] to (health) //the variable blocks in this script all set variables that are "for all sprites"
set [publicATK v] to (attack)
set [publicDEF v] to (defence)
set [publicSPD v] to (speed)
...
create clone of [myself v]
when I start as a clone
set [HP v] to (publicHP) //the set variable blocks here all set "for this sprite only" variables
set [ATK v] to (publicATK)
set [DEF v] to (publicDEF)
set [SPD v] to (publicSPD)
...
_nix
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

kenny2scratch wrote:

define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
set [publicHP v] to (health) //the variable blocks in this script all set variables that are "for all sprites"
set [publicATK v] to (attack)
set [publicDEF v] to (defence)
set [publicSPD v] to (speed)
...
create clone of [myself v]
when I start as a clone
set [HP v] to (publicHP) //the set variable blocks here all set "for this sprite only" variables
set [ATK v] to (publicATK)
set [DEF v] to (publicDEF)
set [SPD v] to (publicSPD)
...
That would usually work, but what about a case like this?

  1. In a no-refresh custom block, we run “create ninja with (stats)” more than once, each time with different stats.
  2. After the no-refresh loop is finished, each clone runs our “when I start as a clone” script. However, they all have the same stats – the stats set by the final “create ninja” block.

So this doesn't quite work perfectly.

Here's what I'd normally do to make each clone have a unique identifier number:

define create ninja
change [total clone count v] by (1) // "total clone count" is a GLOBAL (not "for this sprite only") variable
set [my clone ID v] to (total clone count) // "my clone ID" is a LOCAL ("for this sprite only") variable
create clone of [myself v]
set [my clone ID v] to [--]

when green flag clicked
set [total clone count v] to [0]
repeat (3)
create ninja
end

So at the end we end up having these variables:

(Global variables)
- total clone count: 3

(Ninja sprite)
- my clone ID: --

(First ninja clone)
- my clone ID: 1

(Second ninja clone)
- my clone ID: 2

(Third ninja clone)
- my clone ID: 3

edit: Having stats would work basically the same way but it might not be necessary to set stats back to "--" after, depending on your case.

Last edited by _nix (April 3, 2017 14:34:26)

MegaApuTurkUltra
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

Clones clone the current state of the sprite. So they will contain a copy of the variables at the time the create clone block ran. So MonsterOfTheDeep's solution works perfectly fine, and it's pretty much what I use in all my clone handling systems.

People need to use their brains before making trivial suggestions
TheMonsterOfTheDeep
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

MegaApuTurkUltra wrote:

People need to use their brains before making trivial suggestions
I would understand why somebody wouldn't know about that particular feature of clones - but why post that it doesn't work without confirming that it does? Whenever I see something that I think needs correcting, I always go make a new project just to check that I'm not the one who is wrong. It literally takes like a minute but saves a whole lot of time fixing people's misconceptions.
iamunknown2
Scratcher
1000+ posts

Clone-restricted variables + "do in clone" c-block

MegaApuTurkUltra wrote:

Clones clone the current state of the sprite. So they will contain a copy of the variables at the time the create clone block ran. So MonsterOfTheDeep's solution works perfectly fine, and it's pretty much what I use in all my clone handling systems.

People need to use their brains before making trivial suggestions
I get your point, but your “smarter than thou” attitude is quite annoying.
1080GBA
Scratcher
500+ posts

Clone-restricted variables + "do in clone" c-block

TheMonsterOfTheDeep wrote:

define Create ninja with (health) HP, (attack) ATK, (defence) DEF, (speed) SPD
set [HP v] to (HP) //These are all "for this sprite only"
set [ATK v] to (ATK)
set [DEF v] to (DEF)
set [SPD v] to (SPD)
more stuff here :: grey
create clone of [myself v]
use a list bro, thats easy for you

Last edited by 1080GBA (May 25, 2022 14:55:51)

Powered by DjangoBB