Have you ever wanted to create an ARCADE-LIKE SUPER-GAME in Scratch? You can have found a full list of problems to be solved: an awful amount of sprites, super-long scripts and everything should run smoothly in (at least) the Flash Player but also in Scratch when downloaded. How do you get an efficient design? Which are the basic ideas?
ifugu shared with us all the problems and solutions he found by himself when trying to program the Scratch version of Space Invaders. You can find its wonderful project here.
Here you are what ifugu has to tell to all of us. Enjoy!
=================================================================
SPRITES: First off, there's a sprite for each alien. It would have been nice to use a single sprite for each type of alien and then stamp the screen to make it appear that there were many, but I found that stamping is a pretty expensive operation that bogged things down quickly. Another benefit of having individual sprites is a conceptually simpler programming model ... having the aliens listen for events.
COLLISION DETECTION: The next challenge is implementing collision detection for the missiles that the player fires. It would have been nice for each alien to check to see if they were hit, but my loops serviced the aliens far fewer times than it did the missile. So for every movement of an alien, the missile may have moved 5 steps and zipped right through the alien. Finding a way to make sure the missile didn't just pass through the sprites while maintaining performance was tricky. Checking to see if the missile is touching a color other than black seemed logical and simple, but it was unreliable. Also, once you're touching another color, you'd have to figure out what you're touching. You could just broadcast an event telling all the aliens to check themselves, but this introduces a small pause in the action. The solution was an ungodly long nested If statement on the missile sprite to check to see if it was touching anything. This gives you the info you need right away (i.e., which alien it's touching). The Scratch IDE completely bogs down when you chain blocks to the extent I did. I had to break the chain apart into a few pieces to work with it.
MOVING THE ALIENS: To have the aliens change direction, I decided to create long black bars on each side of the screen that would check to see if any aliens were touching. If they were, time to change direction. I think this was better performing than broadcasting to all of the aliens to check their position or to loop over all of the alive aliens to see where they were.
STAMPING OR NOT STAMPING: I used stamping sparingly. Mostly to show where missiles had hit. Stamping definitely hurt performance. Another thing is that I developed the game on a laptop that was a few years old. By having a slower computer, I was always aware of performance and tried to wring out every little bit. Once things worked in presentation mode on the slower laptop, I knew it would perform well on faster computers. This leads me to another concept, managing the animation rate.
ANIMATION RATE: I felt compelled to make the game work in Turbo mode too. Perfectionist in me. The coding gets a little tricky and cumbersome to do it. The Scratch movement blocks that let you specify how much time it should take to move from point to point are mostly immune to the problem. Controlling the rate of movement yourself is another story. Since we have to check for collisions, we do our own loop that provides an opportunity of detecting collision between movements. I used a timer to keep track of how much time had passed since the last movement of a sprite. Based on the elapsed time and the desired rate of movement, I could calculate how much to move the sprite. For example, if you want a sprite to move 10 steps every second and you find that it's been two tenths of a second, then you need to move the sprite 2 steps. The tricky thing is when the calculation results in numbers lower than 1 or have fractional parts. If we simply tell Scratch to move the sprite regardless of the amount, we'll end up with an unpredictable rate of movement. I skipped moving the sprite if it was too little of an amount. I accumulated how much the sprite was supposed to move for each iteration and when it finally passed a threshold, like 1 step, I'd move the sprite and reset the accumulator. As a simplified example, if every loop resulted in a movement amount of 0.25 steps, the sprite would only be told to move every 4th loop when the movement amount of 1 step had accumulated.
LISTS OR NOT LISTS?: I would have liked to see how well lists performed and how I could have reduced the code. There should have been a lot less copying and pasting with the use of lists. Unbelievably, I discovered lists in Scratch after I was done creating the game. I think the coding would have been much more compact and easy to read with lists. I don't know how it would have affected performance though. As it is there was a lot of copy and paste.
Well, that's all. Sorry for such a long story. If you forget everything else, remember to limit the use of stamping and collision detection (it's expensive too). Have fun!
Last edited by s_federici (2012-02-03 03:08:35)
Offline
Thanks for posting this for me. It's very flattering.
I made a mistake in the Animation Rate section. I said 0 instead of 1. It should read:
"The tricky thing is when the calculation results in numbers lower than 1 or have fractional parts."
Thanks again.
Offline
ifugu wrote:
I said 0 instead of 1
Right. I edited it.
Offline