Skip to content
Celtic Minstrel edited this page Nov 22, 2013 · 12 revisions

This is a rough work in progress at the moment that is neither complete nor final, but as it is being updated I will keep it visible for anyone to comment on if they feel I can be going in a better direction or just have tips/opinions. (One key missing thing is that pictures will eventually be added of some steps to make them clearer and the block adding process easier to understand)

Table of Contents

  1. Getting Started / Making the paddle
  2. Explaining Sprites
  3. The main loop and drawing objects
  4. Getting user input and using messages
  5. Adding the ball
  6. Using bounce
  7. Using direction and speed
  8. Making the ball bounce off the paddle
  9. Collision detection
  10. Adding the blocks
  11. Using arrays
  12. Adding points and lives
  13. Custom variables
  14. Adding sounds
  15. Sound blocks

Getting Started

In any programming language it’s key to break down problems into their basic components. In Waterbear this is even more true, as those basic components will translate into the blocks that you will join together to form your program. In this case we will be building up the classic game “Breakout!”, and the finished program is available within the examples on the Waterbear website.

Explaining Sprites

Breakout has a lot of bells and whistles, but if we strip out the lives, points, music, and even the blocks we’re left with a simple paddle and bouncing ball. We can even start with just a paddle. The paddle will need to be a rectangle drawn on the screen and controlled by the left and right arrows, and not allowed to leave the edges of the screen. In Waterbear we have several sections related to drawing shapes on the screen: Sprites, Images, Rects, and Shapes. Images, Rects, and Shapes all deal with static images which are drawn at a certain point and are intended to largely stay there. Sprites however possess extra traits of direction, movement, and even collision. For a game like Breakout, this is the section we will use for the majority of our objects.

To create our paddle we will drag in our sprite creation block, “rectangle sprite ___ big at ___ with color _____”. Sprite Constructor Block

When it’s dragged in Waterbear will automatically assign it a name, and add it to the collection of global objects at the top of the playground, in the area called the Workspace. The automatic name is just the type of object and unique number, but we can rename it to something more meaningful by double clicking on the workspace block and changing the name, which will automatically update the references.

The rectangle sprite has three variables which need to have initial values, namely the size, location, and colour. These go in the holes in the block, which are called sockets. When you dragged in the block they were automatically filled with default values. The size is another object which contains the width and height, and we will simply change these values to what our paddle needs. Points are also objects, and here we do want to make a bigger change, because the paddle should not be at a random point. We will grab this point block and pull it out of our sprite block, and delete it by dropping it off the left of the screen. Now that we have an empty socket, we go into the Points menu and grab the block that will let us specify a point in x and y values. Point Constructor Block Our x will be what the player controls, but to start with we want it to be in the centre of the screen. Luckily, instead of having the measure the width of our screen, Waterbear makes this easy by providing a block. Inside the Sensing menu is the “centre x” block, and we will drag that in. Center X Block

Notice now that blocks tend to have a few different basic types demonstrated by appearance. Some blocks have the bump on top and whole on the bottom which lets them link with other similar blocks. These are called step blocks, and take actions. They link together because our program will be a series of actions that the program moves through. Some blocks however, like centre x, do not have these bumps. This is to show that they cannot stand alone as steps, but are rather variables. They return and signify some value, and are placed in the sockets of other blocks to add information to steps which need it. There is one third kind of block which we have not yet encountered but will eventually for the backbone of our program, which is the control block, found within the Control menu. These blocks are smooth and curved on the top, but have a space for a step block to connect underneath them. When you drag them into the playground they encompass the step blocks added within them, and this lets these steps be dependent on the control block. This will be the case when we want blocks to only happen if some other condition is true, or if we want to repeat the steps some number of times without having to drag them out over and over again.

Now let’s go back to our program. We’ve gotten our x, but what is the y? We want the paddle to be near the bottom of the screen. We could use a constant value, but then we’d have to make some assumption regarding the vertical size of the screen and it’s better to let Waterbear figure that out for us in case it changes. If we look through the Sensing menu we can see that the stage height is close to what we want, but since the location to draw a sprite is from the top left corner using that as our y value would draw our paddle off the bottom. We need to subtract our paddle height plus a little wiggle room. To do this we need to look into the Math menu. Math contains blocks for most mathematical operations we could need to compute, and contain sockets which let us drop in variables to apply the math to. So we drag in a subtraction block, the stage height in the first socket, and a little more than the height in the second socket. Centered Paddle

Our final initial variable is the colour, which we could leave as random but it’d be nice to have some consistency so let’s drag that out and discard it. This leaves a little square of colour, which when we click on lets us select a colour. (Does this depend on OS? Work on Mobile?) Now we are finished defining our block, and need to draw it. For a sprite this is simple, there is a draw block which takes as a socket a sprite to draw. This is where our workspace comes in, because we will grab our paddle variable block and drag it down, which creates a copy or reference which we can place in as many blocks as we want. Once this is placed in the draw sprite block we have enough basic steps that we can run the program. Paddle with Draw

The main loop and drawing objects

Now that we’ve got the paddle drawing we need to move it. To do this we will need to be updating the x and y values of the paddle and redrawing it when it changes. Later on there will be other objects which need to move and draw, as well as game logic that has to be figured out, so we’re going to take this chance to create the main loop of our game that will be responsible for updating all of these things. We’re also going to save ourselves some trouble later by keeping in mind that we won’t want our game to last forever, it should end when we’re out of lives. So looking under the Control menu, the block we need is “repeat __ times a second until ___”. The first socket is used to control how fast the loop runs. The second is the condition while causes the game to exit, and for now we’ll leave make it “false” to make our loop run forever.

Now we can drag our draw sprite block into this main loop. If we run it again things don’t look any different, but we can add a new block which will be useful and also make the change more apparent. Right now we’re just drawing our pixels on the default white background, but let’s say we want to make it black instead. Inside the Sprite group there is a “clear stage to color ___” block. Let’s drag that into our main loop, before our “draw sprite paddle” block. The one socket for this block is a color, and it defaults to using the color creation block which takes in red/blue/green/alpha values. This will do for now, since red 0, blue 0, green 0 is black. Run the program to see how it looks. You’ll notice that there’s a nice fade in effect, which is due to the alpha being 0.1 at default, which means slightly transparent. It takes a few cycles for the transparent black to layer up to a solid color, resulting in the fade. If you change the alpha to 1.0, you’ll see that it just goes straight to solid black. Note that we placed the stage clearing before our paddle drawing. The stage clearing will always have to be first because the drawing happens in the order of our blocks, and having the stage clear at the end would have it draw over top of all of our other sprites, making everything black.

Getting user input and using messages

Now that we’re drawing every frame we can update the position of the paddle to see it move. We will need to detect two different inputs, left and right arrow, and react accordingly. This is a chance to introduce another idea in programming, that of functions. Sometimes we have a complicated set of steps which we’ll use over and over. Instead of having to keep dragging in those blocks, we’re going to give that grouping a name and just refer to that name instead, which will cause that group of blocks to run. In Waterbear this is handled with messages, under the Control menu. There are two necessary blocks, “broadcast ___ message” and “when I receive ___ message”. The broadcast is what will be in our main program and the socket will be filled with the name of whatever function we want to call. The receive is a container block, and will have all of the steps we want to be taken when a message with that particular function name is sent out. We are going to put user input in a function, so that we can keep our main loop cleaner. So first we will define what our function does by dragging in a “when I receive ___ message” block underneath our main loop, and we’ll change the name from “ack” to “userInput”.

User input is covered in the Sensing menu, and keyboard input is done via the “key ___ pressed?” block. This block will return true what the selected key is pressed, and to make it so that we can dictate what to do when this is true we’ll use an if statement, which is done via the “If ___” block in Control. An if statement simply says “if ___ is true, take the following steps”, and we drag in any block which will return true/false to get our condition. So we drag an “if ___” block into our userInput function container, and then drag the “key ____ pressed?” block into the socket of the if block. We’ll use the drag down of the key pressed block to select “right” for the right arrow key, and now we’re ready to move the paddle. We know we want to move by some fixed amount in the x direction, so looking through the Sprite menu we can see that there is a “move ___ by x __ y __” block which will let us do what we need. Drag that into the if container, fill the first socket with the reference to the paddle like we did with the drawing block, and then in the second socket put in how many pixels you want the paddle to move by. This will dictate the ‘speed’ of the paddle. We’ll start with just 1.

Now we need to do the same thing, but for the left arrow. Make an if block like with the right key, but when you are putting in the x movement for the paddle you have to make it negative. The top left corner of the screen is 0, 0 so in the x direction positive is right and negative is left, and for the y direction up is negative and down is positive. Once that’s done we just need to broadcast a userInput message in our main loop with the “broadcast ____ message” block (before the draw block, since we want our paddle drawn in the updated position), then we can test it out!

Adding the ball

Using bounce

Now we would like to add our second major sprite, the ball. The basic functionality of our ball is very simple, we want it to be constantly moving around the screen and bouncing off of any other physical object it hits, including the walls. Since this is a fairly common idea, Waterbear has made the “bounce ___” block to simplify it for us. What the bounce block does it check if a moving sprite has reached any edge of the screen, and if so reverses its direction so that it bounces appropriately.

Using direction and speed

So, in the same manner as the paddle we create a new ball sprite. We have the creation block underneath the paddle’s, the bounce block underneath the broadcast userInput block, and finally the draw block under the paddle’s draw. But we also need to add some new blocks, since the ball is moving outside of user control. This is achieved by a few properties: Speed Direction Move block The speed and direction dictate where the block will go, and the move block must be called to make the sprite actually move along this path. What the move block does is basically like what we did with the user input, it uses the speed and direction to calculate the changes to the x and y of the sprite and adds or subtracts them. We can set the speed right after we create the ball using the “set sprite ___ speed ___” block. The direction is a little more complicated in that direction is split into two type: turn and steer. This can be considered to be like steer is the direction the sprite is moving, but turn is the direction the sprite is facing. We only have to worry about steer because we don’t really care about the rotation of where the sprites are facing since it’s all just rectangles, but you can play with it if you’d like. If you prefer to have the square ball change facing when it changes direction you can do it easily by using the “autosteer sprite ___ ___” block and setting it to true. Autosteer makes it so that changing the facing of the sprite with “turn” automatically changes the steer direction to match. So we would first set autosteer to true, and then instead of setting the steer would set the turn, because it would then automatically set the steer.

But with that aside, we add the “turn sprite to ___ degrees” block underneath the speed block, and to get a random direction we’ll go into Math to find the “pick random __ to __” block and use 0 and 360 as our upper and lower bounds respectively. Now our ball has a direction and speed for movement and we just need to add the “move ___” block to our main loop. With that done we can run it and observe how bounce works, as well as play with the speed.

Making the ball bounce off the paddle

Now that our ball is bouncing around the screen, we need to add interaction with the paddle. This involves a few steps: Detecting when the ball is intersecting with the paddle (collision detection) Figuring out how the direction of the ball should be changed to bounce properly

Collision detection

Collision detection at its heart involves comparing the x and y values of the two sprites to figure out in what way they are colliding. Luckily Waterbear simplifies this as well with the “sprite --- collides with sprite ---” block within Sprite. Notice that it is red instead of green, which indicates that even though we group it with the Sprite blocks it is really a Boolean block as it returns a boolean values (true or false). Since handling collisions is going to take several blocks and be done every cycle of our loop, we’re going to put it in a function like we did with userInput. So we make a function which we label handleInput, and within it add an “if” block with the boolean in the socket, and the paddle and ball sprites in the two sockets of that boolean. Now we have to figure out how to make the ball bounce. While the ball direction is something we just set as a value in degrees, internally it’s split into an x and y direction, like a vector, where the magnitude is speed. A solution to our bouncing problem that is very easy to understand conceptually is that when we bounce off the top of the paddle we want to reverse the y direction while staying in the same x direction. There are other ways we could do the bounce, but this is a simple idea. Within Waterbear there’s a little trick required however, because if you look through the Sprite menu you’ll see that while there is a variable block “vertical speed” which would give us the current y direction and speed, but there is no step block for setting this variable. There is a way to get around this, and that is with the Object menu. The object menu lets us work with objects like sprites on a lower level than the blocks by direction manipulating values at specific keys. The key is the name of whichever property we want to change in the actual code. Unfortunately to know this exact name you often have to look through the source code yourself. However, these is also a little trick that we can use. We haven’t looked at it before, but you may have noticed at “Script Text” tab at the top of the playground. Clicking on it, we can see the actual javascript code our blocks are generating. A good idea for understanding the blocks and programming better is to experiment with adding blocks and checking the code to try and understand what the blocks are actually doing. But for now, we can realize that when we use the block which accesses the vertical direction/speed it will generate code that accesses the actual variable, which we can then see the name of. We need somewhere to drop this block, but we don’t want it to actually be executed in our program, so we’ll bring in another new kind of block. Under the String menu there is a “comment ___” block. Comment is a special term in programming that indicates that the following code or text should not be considered an actual part of the program, but a message from the programmer to themselves or others which is usually there to explain in English what the code is doing. It is also a way to put in blocks which won’t effect our actual program. So we’ll drag in a comment block, and fill it with that “sprite ____ vertical speed” block. A good place to put it in this case is the very bottom of our blocks, so that we can find it more easily in the code. Switching into the code we scroll to the bottom and find this text “/* null.dy; */”. Those slashes and asterisks are how Javascript denotes comments, so the text inside is the result of the vertical speed block. The null means we haven’t dropped in an actual object, null is a programming name for when you’re trying to reference something that doesn’t actually exist yet. But the part we care about is the dy, which is the property the block is trying to access. So this is the key we need for our object! We drag in the “object ___ key ___ = value _____” block, fill the object socket with the ball, type “dy” for the key, and now for the value we want to multiple the ball’s vertical speed by -1 to reverse the direction without changing the magnitude. Now we’ve got a bouncing ball, and can play with this some more.

Adding the blocks

Now that we can bounce our block and move our paddle, we need something to actually direct our blocks at. In Breakout this is several layers of blocks along the top of the screen that are destroyed when the ball bounces off of them. To take advantage of the easy collision detection we are going to want these blocks to be Sprites, but we have a problem now. Each sprite we created so far has needed a construction block with several parameters, and to handle 10, 20, or 40 blocks would be time consuming and take up a lot of space. To avoid that, we’re going to use something called an array.

Using arrays

An array is like a kind of special list, and is handled under the Array menu. An array can hold any type of object, but all objects within a single array must be of the same type. So we could have an array of sprites and an array of numbers, but we couldn’t mix numbers and sprites in one array. To start with we just need to make the basic array, which will be empty, using the “new array” block, which will go with the rest of our construction blocks. We will also rename the array to “blocks” to make the code clearer. Now we need to add the sprites to our array, but we do still need to actually create each sprite using a construction block. The information for each block doesn’t change very much, so we can actually use a repeat control block like we did with our main loop to create these blocks in a loop instead of having 40 construction blocks in a row. So we will drag in the “repeat ___” block and change the number to 40. Notice that like our repeat per second block it has given us a count variable, which tells us how many times we’ve repeated. This time we’ll be using this, since we need the location of each destroyable block to change. So first we pull the usual Sprite construction block into the repeat.

Adding points and lives

Custom variables

Adding sounds

Sound blocks