When you create a project, with a lot of scripts, it will run very slow.
Online, and even offline. Are there any tips for gettin' big projects at normal speed?
Some examples:
RCRally 3D by JSO
Dogfight 3D by S65
City 4 by JoelP
_______________________________________________________________________________
[blocks]
<forever>
<say[ scrips ]for( REM
<wait( 0.05 )secs>
<end>
[/blocks]
Will it run more smoothly without the wait? Even with a lot of scripts?
_______________________________________________________________________________
Use this: ?
[blocks]
<repeat until>
<end>
[/blocks]
Or this:
[blocks]
<forever>
<if> condition
<stop script>
<end>
<end>
[/blocks]
_______________________________________________________________________________
Please tell what is the best solution!
Last edited by JSO (2008-05-23 10:48:17)
Offline
If they have many images or many music in it, then go to the menu and press Extras --> compress sounds or Extra--> compress images. With scripts, there is no way to compress them.
Offline
I started building things in Scratch thinking that "anything goes", and didn't worry about using Forever loops if that seemed easiest (or came to mind first). I assumed programming magic provided by the developers of Scratch would just make things work. To an amazing extent, this is true.
As far as "repeat until" vs "forever / stop script": Repeat until will keep testing for a condition, unless you trigger the "forever" loop again, it will do nothing, but will still have to test for its trigger condition. So there probably isn't much difference.
Obviously, avoiding a forever loop if you can makes sense. A tiny delay in a forever loop will help other things run more smoothly. I experimented with "Wait 0.01" (and lower) statements in my first (Stealth Fighter http://scratch.mit.edu/projects/EdnaC/33613) project, and found that it made turns and motion very choppy, so those forever loops run with NO "Waits". The game runs smoothly on any reasonably recent computer, but has (at least) four Forever loops running all the time. These loops take a toll, so I'm sure there is a limit to how many can be running.
From what I've seen, use a "Wait" in scripts where you can (where the program isn't responding to user input). I wonder (Jens could tell us) if "Wait "0 (Zero)" frees up any processor time???
-Mr Ed
Last edited by EdnaC (2007-09-10 07:39:53)
Offline
I'm not a tech guy, but from what I've looked at in the Squeak source code of Scratch I don't think that there's a major difference (if any) between a 'wait until' condition block and 'forever (if)' block, since they're both instances of the same class, using the same internal process thread. I don't know about the java version, but I suspect that it might be just voodoo there, too.
I also strongly believe that all those comments about seemingly 'good' programming style and 'cpu-usage' reduction 'secrets' are quite besides the point, and really counter-productive, because recommendations about 'forever'-loops being 'bad' for performance and adding pointless mini-waits distract you from actually producing readable, understandable, and thus shareable and maintainable projects.
At one time I had an issue with failed broadcast reception in a 'forever' loop in the online version (which was a known bug back then), and got all those clever recomendations telling me to add a '0.001' sec wait. But I really didn't want to change my code, since the underlying logic simply didn't need a mini-wait. So I just waited for the Scratch team to solve that problem, and they sure did in the very next version, now my project works just fine.
Another vastly overrated thing is the number of scripts per project, implying that 'less scripts run faster'. In my experience often the contrary is true: Instead of creating only a few ugly 'run-on-scripts' try breaking them up into smaller units that each only do one thing or solve one particular problem, and trigger them using broadcasts. Don't worry about using a lot of scripts and a lot of broadcasts, it's what Scratch is *really* good at!
After all, it's often not raw 'speed' that causes problems, but projects getting out of synch (e.g. a gun responding too slow to a 'fire' command). This often happens, if your scripts (which each run in separate threads) are so long, that they evolve with a 'life of their own', regardless of what's happening the context of your project.
(this may be one of the problems in JSO's 3D car racer project, if you have look at the 'cn_control' sprites, and at the 'when I receive gamescripts' script)
So, to sum it up, my seven advices for 'good' performing big projects are:
1. use whichever (control) blocks make sense to you, don't worry about forever loops being bad for performance or 'cpu' usage. That may have been an issue with assembler, with Scratch it is not.
2. make sure your scripts do (only) what you want them to do. Consider, e.g. that broadcasts are sent to *every* Scratch object (every sprite and the stage), so make sure only those objects needing to react actually do.
3. use *a lot* of broadcasts to keept your project in synch. Remember, Scratch computes massively parallel (!) doing more than one thing at a time greatly speeds up your project.
4. Go through your code again and again and think how you can further simplify and abstract your scripts. Remember: The simpler the better / the faster.
5. Don't be afraid of big projects, lots of sprites and lots of scripts. In fact, rather than stuffing everything into a single sprite consider creating a separate sprite for every separate task you got.
6. Avoid run-on scripts and don't overdo deep nesting of if-else blocks. They are hard to read and even harder to schedule. While deep nesting of if-else blocks may be the academically correct way to emulate case statements, a chain of simple if blocks is often easier to read, to correct and thus to keep in synch.
7. Don't worry about performance. Come up with a cool project idea and think of how to code it nicely. Scratch is about learning to programm, not about tweaking system performance. If it runs too slow now, just wait a year, it'll get faster all by itself ;-)
Last edited by Jens (2007-09-10 05:58:01)
Offline
That's good to know. I've been putting in "little waits" on the advice in other forum threads, because it seems to make sense, but in some places, this just made things choppy so I did away with them.
The idea of more short scripts as opposed to fewer long ones is great advice. Easier to understand and to debug . In building "StealthFighter", I got turning of the Planes working like I wanted (a no-waits forever loop) then left that script alone and built the script to "move" the planes separately. (Not for any scientific reason, it was just the easy way to go.)
A lot of new users are (I think) using the (Key Pressed) "Hat" to control things like turning or moving. A forever loop testing for input using "If <keypressed ()?> works a LOT better.
Offline
EdnaC wrote:
A lot of new users are (I think) using the (Key Pressed) "Hat" to control things like turning or moving. A forever loop testing for input using "If <keypressed ()?> works a LOT better.
And I believe they are right!
I don't think one method is principally better than the other. Moreover it depends on what you're aiming at. The key pressed hat starts a new THREAD, i.e. a script that runs completey on its own, whereas querying the condition of a pressed key inside a loop lets you define further conditions under which you want to 'look up' if a key is pressed. Depending on what other code is in the 'forever' loop your script may be very slow to recognize a pressed key, whereas using the key pressed hat will make it find out right away.
Whenever I want my projects to feature user interaction with moving sprites (which I don't have a lot in my posted projects) I usually create a set of variables describing the movement's properties like (movingOn, directionAngle, speed etc.) . Then I put together a 'movement' script (usually starting when the green flag is pressed or some 'start' event is received. That script usually is a foreverIf loop querying the status of the 'movingOn' variable and then moving the sprite according to the variables. I then use various event hats (key pressed, mouse clicks etc.) to change the value of the movement variables (sometimes defining further constraints in these separate scripts). And that's all there is to it. Because Scratch is *multithreaded* it lets you change the value of a variable in one script while it is queried in another.
In fact, multithreading is probably the one most underestimated and most often misunderstood feature of Scratch. Scratch isn't just an old BASIC remake with draggable and droppable keywords and such, but a parallel computing environment. you can do many things at once in Scratch using parallel threads (i.e. event hat scripts), and broadcasts to synchronise them. A broadcast isn't just a call for a subroutine, but a signal for a new thread (!).
IMO most of the 'performance issues' in big projects arise out of reluctance (or even ignorance) to use multiple threads productively.
Last edited by Jens (2007-09-10 10:17:05)
Offline
Thanks! I will try to split the scripts in my racing project (if it's possible), and see if it runs better.
But: i still have a question: My projects usually gets a lot (i really mean a lot) of variables. Will scracth (or the Java Applet) run more slowly with more variables in the memory? And: is it better to use local variables where possible?
PS: In (some) other programming languages it doesn't take sense, but i do not understand squeak (maybe it will change... I can't do everything... I'm just 12...) and i don't know how "variables" in scratch are programmed. (real squeak variables, one big array,...)
Offline
Variables are a great way to generalize what your project does. Also, you can store results of complex computations in variables, so your project doesn't have to go through these complex computational steps every time, which usually speeds up your project a lot.
Of course, variables need memory, however, in Scratch (currently) variables only hold numbers, and therefore use up less memory, than any 'say: 'blablablabla...' block. Again, I don't believe extensive use of variables pose any performance issue whatsoever, as long as you don't abuse them to imitate large collections (Arrays, Strings etc). But even then it's probably not the variables that will slow down your project, but the complex code needed to abuse them....
The difference between global and local variables also doesn't relate to speed or performance, but rather to namespace. If you just need a variable within the scope of one sprite to - say - remember the result of a complex computation, you don't need to cram up your list of globals with it. In other words, it helps you organize your project, but doesn't affect speed.
Finally, JSO, you don't have to know Squeak at all to create fantastic projects in Scratch, as you already are. It doesn't depend on how old you are to notice, that your projects are quite exceptional (especially your lego and racing projects). Given the fact, that you're not even a teenager yet let me tell you, that you are doing just perfect. If I recently referred to Squeak internals in this forum, I might have given the impression, that there are 'secret' Scratch tricks to be discovered by studying the Squeak source code. That impression, though, is thorougly wrong! let me assure you, that all you need to know to make great Scratch projects is Scratch itself!
Last edited by Jens (2007-09-11 03:38:09)
Offline
Organizing variables has been a frustration for me. I find myself not making variables when I normally would, just to avoid the clutter that accompanies a lot of variables. Avoiding calculating something that will be used multiple times is one example, and in that case, I will go ahead and make a variable. Another good use for variables is to store a simple number that a sprite will use in many places (perhaps to describe something like the min and max "X" dimension that it is allowed to travel to). Changing the variable is easier than hunting down the number in all of the scripts and changing it in the "code".
I posted some suggestions about reorganizing how the variables get displayed:
http://scratch.mit.edu/forums/viewtopic.php?id=1479
And another about renaming them:
http://scratch.mit.edu/forums/viewtopic.php?id=1501
You may want to weigh-in with ideas. How to reorganize the display of variables is a tough subject. It would be nice to be able to navigate them more easily (for big projects), but the development team needs to stay focused on keeping Scratch easy to use (lots of options can make things imposing for beginners). I wonder about an "expert" setting, like some CAD programs have.
-Mr Ed
Last edited by EdnaC (2007-09-11 08:13:57)
Offline
Thanks for all the replies! If i really want to program more difficult things (i mean the code), i always can use Flash...
Maybe you can come see one of them (on my one site):
Sorry: the site is fully writen in dutch, also the game.
Krak online puplished folder
The games that are published at the real site, are in the "Games" folder, And some (newer and better) beta versions in the "Extrafolder".
Scratch is just amazing, cause it's easy to program a project, with a brain full of ideas, and then: the most important: show it to everyone, get coments...
Offline
I agree with Jens about concentrating on making code simple and using broadcasts to start threads. I often move the user interaction into short "when key clicked" scripts that send broadcasts for the actions to perform.
I disagree about doing "forever loops" with no waits. They are, to my mind, a bad programming style. The best forever loops have explicit long waits or pairs of waits for mutually exclusive conditions, so that they don't run freely but pause somewhere on each iteration. Putting tiny waits (like 0.001 seconds) doesn't really do much other than provide the scheduler a break point---now that they've fixed the scratch engines to allow rescheduling on each iteration the tiny waits are no longer needed (I think).
I agree with EdnaC that the current variable pane *discourages* variable use for more than 2 or 3 variables, because of how much scrolling it takes to get to the variable you want. Having pull-down lists in the set, change, and variable blocks (like for messages) would be a simpler interface and much less cluttered.
Offline
Now, it would be interesting to get an answer from the Scratch developers on the issue of waits. In my opinion, there plain and simple is no such thing as 'waiting' computer, unless you pull the plug... ;-)
But seriously: a 'wait until (condition)' block is nothing else than a loop (!) that keeps evaluating itself constantly until the condition is true. The focus here is on it being a *loop*. In other words, the programm is far from idling, moreover the thread keeps running (actually looping) and checking its condition *all the time*.
Consider for example the following code snippet:
[blocks] <wait until><(1 <=> 0 )>
<play sound[ pop [/blocks]
double click it. You'll notice a white highlight indicating that the thread is running, that will *not* go away, and it will never get to play the sound (because it rightfully keeps forever checking the impossible condition).
On the other hand, try the following:
[blocks] <wait until> <( <pick random( 0 )to( 100 <=> 0 )>
<play sound[ pop [/blocks]
Whenever you double click this script, it will highlight for a while, and then stop. And that's because it keeps looping and polling random numbers all the time, until it finally finds the true one.
What it really does is the same as:
[blocks]<set{ variable }to( 1
<repeat until> <( <{ variable }> <=> 0 )>
<set{ variable }to( <pick random( 0 )to( 100
<end>
<play sound[ pop [/blocks]
Or, to use a 'bad' forever loop:
[blocks]
<forever>
<set{ variable }to( <pick random( 0 )to( 100
<if><( <{ variable }> <=> 0 )>
<broadcast[ event ]and wait c>
<stop script>
<end>
<end>
<when I receive[ event
<play sound[ pop [/blocks]
So, my point is, waits aren't any 'better' programming style than loops, because waits *are* loops.
I agree with Kevin, though, that waits (being shortcuts for loop statements) make for better code reading, and may thus be the preferable coding alternative, but not for performance or scheduling reasons.
Therefore:
[blocks]<forever if><( <pick random( 0 )to( 100 <=> 0 )>
<play sound[ pop
<end>[/blocks]
Is really equivalent to:
[blocks]<forever>
<if><( <pick random( 0 )to( 100 <=> 0 )>
<play sound[ pop
<end>
<end>[/blocks]
and to:
[blocks]<forever>
<wait until> <( <pick random( 0 )to( 100 <=> 0 )>
<play sound[ pop
<end>[/blocks]
as well as to:
[blocks]<forever>
<set{ variable }to( 1
<repeat until> <( <{ variable }> <=> 0 )>
<set{ variable }to( <pick random( 0 )to( 100
<end>
<play sound[ pop
<end>[/blocks]
and not any better or worse programming style.
However, in this case I would prefer the simplest and shortest variation, which would be the foreverIf loop.
Last edited by Jens (2007-09-12 12:40:18)
Offline
If they've implemented waits correctly (no guarantee of that), they used daemons instead of loops, so the condition of the wait is only evaluated when one of the variables in it changes (unless you included the "random" function, which needs to be re-evaluated every time).
If the wait is done as a busy-wait rather than a daemon, then it offers no efficiency advantage.
Scartch developers, did you use daemons for "wait" and "forever if"? If not, how were they implmented?
Offline
Wait. My game has glitches, but I don't know why. Could it be I use many forever blocks with if's inside them?
Offline