Hi, I am new to scratch, just started teaching my son the basics of programming with it.
I find scratch quite intuitive and clean, except for one problem - there seem to be no way to access sprite objects indirectly. In case you have multiple objects with common inter-object interaction algorithm (like bouncing balls) you have to replicate interaction code (like sensing blocks) using instance names for each pair. I can't simply write a script for a sprite with awareness of other sprites and then simply replicate the sprite. IMHO this defeats object reuse, which is what the software design is about.
Is there something I am missing as a novice ? Is there a discussion explaining why it was done this way and perhaps showing some different programming paradigm or workaround ?
Offline
What? I don't get that...
Offline
scimonster wrote:
What? I don't get that...
Suppose I am writing a script for a ball and I want it to sense other balls on the field (distance, touching, etc) and behave according to the changing environment. In other programming languages I will have a list of all other ball objects on the scene and write a simple loop, iterating over objects and asking them the location, speed, etc. Then script for this ball does something based on the query information.
In this scenario I do not need to be aware at the script writing time how many balls will be on the scene and how they are named, moreover the script for each ball will look exactly the same.
In scratch AFAIK I have to explicitly name all peer balls on the scene in the sensing commands to get their location, direction, etc. The script for each ball is slightly different because of static naming. And every time I add / remove a ball I have to change ALL ball scripts to add / remove sense block.
Offline
You could use a list will all the ball attributes (x, y, direction, etc.), and refer to the items in the list to get the information. To be able to use an arbitrary number of balls, put a script in each one such as:
[blocks]
<set{ place }to( item
<change{ item }by( 1
[/blocks]
where 'place' is a local variable, and 'item' is global. This give each ball a different number.
You can also name each ball a number ('1', '2', '3', etc.) and iterate through those values to access the balls' information, for example:
[blocks]
<set{ iter }to( 1
<repeat( number of balls
<say[ <distance to[ iter ]for( 0.5 )secs>
<change{ iter }by( 1
[/blocks]
Offline
Hmm, I can indeed create a local integer id variable like you said. But querying distance by integer index does not work as suggested. Not sure how it supposed to work as you are iterating over integers, not sprite names.
I guess one thing that should work as a workaround is creating global lists for every type of variable (direction, x position, y position etc) and let each ball continuously update it's local data in a global array indexed by id number inside forever block. Then the list can be queried by every object. Kind of kludgy but doable.
Offline
vladn wrote:
Hmm, I can indeed create a local integer id variable like you said. But querying distance by integer index does not work as suggested. Not sure how it supposed to work as you are iterating over integers, not sprite names.
I guess one thing that should work as a workaround is creating global lists for every type of variable (direction, x position, y position etc) and let each ball continuously update it's local data in a global array indexed by id number inside forever block. Then the list can be queried by every object. Kind of kludgy but doable.
Use the ({^ } of {^Sprite1}) block. I think.
Offline
floppy_gunk wrote:
[blocks]
<set{ place }to( item
<change{ item }by( 1
[/blocks]
where 'place' is a local variable, and 'item' is global. This give each ball a different number.
BTW, does scratch shell guarantee atomic execution of this bock pair ? If not there could be nasty race condition between sprites.
I got the hack working with global parameter lists updated continuously by each sprite. But it means that I can not use any "high level"/convenience sensing blocks. I have to write everything from ground up, like geometry based collision detection etc.
Offline
vladn wrote:
Pecola1 wrote:
Use the ({^ } of {^Sprite1}) block. I think.
Could you please clarify or point me to the right direction ?
This block is near the bottom of the sensing tab. It contains all the information such as size, position, costume number and such of every sprite local to the project. Yes, a bouncing balls project will require from-the-ground-up geometry coding and I'm surprised this is a project you want to use to introduce your son to programming. You much remember that Scratch is just that - an introductory language. A fair amount of things can be done with it, but it's not the fastest of most powerful of languages. It isn't first-class either and the two variable blocks will not run atomically as only one block at a time is run across the entire project.
If you are looking for a way to run atomic scripts or run long pieces of code several times or for each sprite seperately you should look at BYOB. Build-Your-Own-Blocks is a modified version of Scratch made by Jens Moenig (programs for MioSoft) and Brian Harvey (teacher at Berkley in America). It allows you to compile a script into one block that can then contain arguments for the script within it. It supports atomic script running and recursion as well as first class objects, I believe. Other than that - it's just like scratch! Read more about it here. If you're looking for example scripts for BYOB, the BYOB section of the block library is the place to go
EDIT: Though if you ask me, the best way to teach him about programming is to let him loose on the scratch site where he can learn by downloading projects and let him play around on Scratch himself for a couple of weeks. He can start making projects at a level he enjoys and it's amazing how fast you can learn it!
Last edited by sparks (2011-04-15 05:22:28)
Offline
sparks wrote:
Yes, a bouncing balls project will require from-the-ground-up geometry coding and I'm surprised this is a project you want to use to introduce your son to programming. You much remember that Scratch is just that - an introductory language.
Obviously this is not what we are doing with him. But I want to understand scratch programming paradigm myself, hence I am building few of my own pet projects
sparks wrote:
EDIT: Though if you ask me, the best way to teach him about programming is to let him loose on the scratch site where he can learn by downloading projects and let him play around on Scratch himself for a couple of weeks. He can start making projects at a level he enjoys and it's amazing how fast you can learn it!
It did not quite work this way on first attempt. I think I need to explain him a few things before he can swim here...
Offline
vladn wrote:
Pecola1 wrote:
Use the ({^ } of {^Sprite1}) block. I think.
Could you please clarify or point me to the right direction ?
here is some information.
Offline
My apologies. I figured out that it is indeed possible to use a string variable (or a string list entry) matching the name of the sprite in the sense blocks. This allows creating loops querying multiple sprites via sense blocks.
One more question - is there a way for a sprite to access it's own name (in a form of a string variable) ? This may sound stupid
, but it makes a clean way for multiple sprites to register themselves in a global name list (that can be used for query loops).
Offline
vladn wrote:
My apologies. I figured out that it is indeed possible to use a string variable (or a string list entry) matching the name of the sprite in the sense blocks. This allows creating loops querying multiple sprites via sense blocks.
One more question - is there a way for a sprite to access it's own name (in a form of a string variable) ? This may sound stupid, but it makes a clean way for multiple sprites to register themselves in a global name list (that can be used for query loops).
You would have to use the join block. But by a reporter, no. Unless you edit the system browser.
Offline
The other thing I am puzzled about is how slow the loops are. An empty repeat 30 block takes about a full second to execute. Yet at the same time, CPU usage by scratch is near zero (as seen in the Windows task manager). Not sure if it is my machine, OS, or scratch VM internals. Feels as if internally on every pass of the repeat loop VM puts the thread to sleep.
Are the other project spinoffs like BYOB use the same virtual machine code and equally slow loop implementation ?
Offline
vladn wrote:
The other thing I am puzzled about is how slow the loops are. An empty repeat 30 block takes about a full second to execute. Yet at the same time, CPU usage by scratch is near zero (as seen in the Windows task manager). Not sure if it is my machine, OS, or scratch VM internals. Feels as if internally on every pass of the repeat loop VM puts the thread to sleep.
Are the other project spinoffs like BYOB use the same virtual machine code and equally slow loop implementation ?
The VM isn't the cause of the speed issue. It's mainly the execution engine implemented in Scratch. I'm still trying to figure out how it works so I can possibly make a faster one without having to rewrite everything, but that won't be done for a while. In the meantime, just go to edit > set single stepping > turbo speed and it will be much faster.
Offline
Tried the turbo mode, it does indeed speedup loops, but it makes graphics updates very choppy even if there is only few sprites on the screen.
BTW, found the "sprite name" reporter block in Panther. But the execution engine has the same speed problem in Panther.
Offline