I had the opportunity to speak today at Code Camp Pittsburgh 2009. It was a great event. There were lot of very good talks and good audience participation.

I presented on Microsoft Small Basic. It is not often we get a chance to program just for fun. However, this tool is fun to use. It is currently in version 0.3 (emphasis on the zero). It is a great application for teaching someone to program. Newcomers to development will find the tool to be very accessible. For older developers it brings back the power you might have felt working when coding on a TRS-80 or Commodore 64 years ago. It is basic programming.

The talk was all code demos. The best way to pick up this tool is to just write some code. The following shows a few basic examples along with a longer, game demo based on the Atari classic, Kaboom!

 

Hello World

A simple way to get started is to create a “hello world” application. You can see by the image below that typing in a code window brings up all your options for the language. This is a rich version of intellisense. Notice that right-hand side of the screen. It contains context-sensitive help based on the object and operation you are calling. This includes parameter definitions. This is a really good way existing developers can come up to speed quickly on this tool.

Small Basic IDE

The Hello World code is very simple. It writes out text to a TextWindow (or console).

TextWindow.ForegroundColor = "Red"
TextWindow.WriteLine("Hello Code Camp!")

The TextWindow is also great for debugging. There is no real debugger in the tool. Therefore, you have to write messages out to help keep track of what the application is doing. The good news is that you can combine both Text and Graphic applications in a single program.

 

Drawing Circles

Of course the real fun comes with the graphics window. It has much easier to teach programming with real graphics than it is with text windows. The main object for graphics is the GraphicsWindow. You can use it to draw shapes, change colors, draw text, show pictures, and more.

Of course Small Basic also supports loops. You can create For/Next, While, and Goto type loops. The following code shows a simple loop that draws bigger and bigger circles on a graphic window. Notice the use of Program.Delay. This pauses the application during operation to allow users to see what is happening as it happens.
GraphicsWindow.Width = 600
GraphicsWindow.Height = 600

For i = 1 To 600 Step 10
  GraphicsWindow.PenColor = GraphicsWindow.GetRandomColor()
  GraphicsWindow.DrawEllipse(300 - i, 300 - i, i * 2, i * 2)
  Program.Delay(100)
EndFor

 

Note on variables: notice that in the previous code there was no declaration of the variable, “i”. Small Basic allows variables to be created anywhere and at anytime. It also has no notion of variable scope in the current release. Therefore, all variables are available anywhere in your application including other sub routines. While easier, this can make things a little messy.

Programming a Turtle

If you have ever used Logo or Turtle Basic you will recall a simple turtle that can be given instructions to execute. This helps make programming more accessible as you are controlling an object in your code. Small Basic includes the Turtle object for just this reason. This is great to show kids just how logic can be used to control something.

The following program is an example. It contains two loops. The inner loop draws a shape. The number of sides of the shape are defined by the “sides” variable. Inside the loop the Turtle is told to Move and then Turn based on an angle. The outer loop defines a circle. The number of iterations is dependent on your turn angle: multiplying the two should equate to 360 degrees.  

'set shape sides
sides = 5
length = 500 / sides

'define a circle
angle = 360 / sides

Turtle.Speed = 10

'rotate around the circle based on the turning angle
For j = 1 To 10
  For i = 1 To sides
    Turtle.Move(length)
    Turtle.Turn(angle)
  EndFor
  Turtle.Turn(36)
EndFor

Running the application results in an interesting shape as shown below. You can play around with the sides of the shape (50 or more creates circle like shapes), their length, the turn angles, etc. to create some interesting shapes.

 

Building Something Bigger: KABOOM!

To really test the product, I wanted to build something bigger. The following walks through how I started building a game loosely based on the addictive, Atari 2600 game: Kaboom! If you can’t wait, you can download the source now. There is a version with images and one without images. If you use the images, you will have to check the install path in the code based on where you put the images on your machine.

The following steps through my process I followed when building the game. This includes discovering a nice “gotcha” that almost sunk my game... 

Step 1: Define the game objects

If you never played Kaboom, let me explain. You basically have a bandit that slides across the top of the screen dropping bombs. You control a bucket of water. You use it to catch the bombs and extinguish them before they explode. That’s it; a simple concept that was addicting in its final form.

The first step I took was to define the objects of the game. This took advantage of the Shapes object. You can use this object to add shapes to the screen and maintain a reference to them in your code for later use.

For the game, I created three objects: a bucket, a dropper, and a scoreboard. I will add the ball, or bomb, objects later. The following shows this code:

'define a bucket to catch balls
GraphicsWindow.PenColor = "Red"
GraphicsWindow.BrushColor = "Brown"
bucket = Shapes.AddRectangle(50, 20)

'define the ball dropper
GraphicsWindow.PenColor = "Black"
GraphicsWindow.BrushColor = "Black"
dropper = Shapes.AddRectangle(80, 40)

'define the scoreboard
GraphicsWindow.BrushColor = "Blue"
GraphicsWindow.FillRectangle(1, 1, GraphicsWindow.Width, 40)
GraphicsWindow.FontSize = 24
GraphicsWindow.BrushColor = "White"
GraphicsWindow.DrawText(5, 5, "0")

'set initial position of shapes
Shapes.Move(dropper, 1, 50)
Shapes.Move(bucket, 1, GraphicsWindow.Height - 20)
Notice that I moved the objects into their initial position at the end of the code. If you call Shapes.Add, the shapes are added by default to the upper left corner of the screen. Therefore, I moved them into a better default position. If you run the code you will see the initial setup of the application as shown below.

Step 2: Add Mouse Support to Move the Bucket

Small Basic supports a few events for things like keyboard and mouse. To define an event, you first write a subroutine and then connect that subroutine to event.

In the game, I need to use the mouse to move the bucket. Therefore, I first define a subroutine that will be called when the mouse is moved. I add that routine to the bottom of the code window. The routine contains a little math to move the bucket based on the mouse position.

Sub MoveBucket
  Mouse.HideCursor()
  bucketX = GraphicsWindow.MouseX - 25
  Shapes.Move(bucket, bucketX, GraphicsWindow.Height - 20)
EndSub

Next, I connect the event. Back in the main line of the application flow I add the following line of code:

'add mouse support
GraphicsWindow.MouseMove = Movebucket

Running the application now shows the mouse movement.

Step 3: Define the Main Program’s Execution (Get the Dropper Moving)

The next step is to define the main code (or loop) that is going to keep the application running. In this case, I want to drop a set number of balls. Until then, I want to keep the programming running. Therefore, I setup a main loop based on the number of dropped balls.

Inside the loop, I need to move the dropper back and forth across the screen. This is done with a Shapes.Move call and a call to Program.Delay. The latter is used to slow the application so the user can see the shape move. The following shows this code (that also includes playing a sound at game start and showing the score at game end):

droppedBalls = 0
ballsMax = 25
dropperX = 1

'game starting sound
Sound.PlayChimesAndWait()

'--------------------------------------main program loop
While (droppedBalls < ballsMax)
  Shapes.Move(dropper, dropperX, 50)
  Program.Delay(10)
  SetIncrement()
  dropperX = dropperX + incrementX
EndWhile

GraphicsWindow.ShowMessage("Game Over. Your score: " + gameScore + " / " + ballsMax , "kaboom score")
Program.End()
'-----------------------------------------------

Notice that above I put a subroutine call in the code for SetIcrement. After the object is moved, I need to check to see if it has reached the edge of the screen. If it has, I move it in the opposite direction. This is all done inside of SetIncrement as follows:

Sub SetIncrement
  If ((dropperX + 80) > GraphicsWindow.Width) Then
    incrementX = -5
  EndIf
  If (dropperX <= 1) Then
    incrementX = 5
  EndIf
EndSub

Running the application now will show the dropper smoothly sliding left to right and back. The next step is to get the dropper dropping balls (or bombs). 

Step 4: Dropping Bombs

To get started dropping balls, I need to add some code to my main While loop. This code checks a random number and uses it to determine if a bomb should drop. This is not exactly how the original game worked but it does make for a similarly compelling game.

If I decide to drop a ball, I call a DropBall subroutine. Subroutines in Small Basic do not take parameters. There are no variable scoping levels. The variables in the subroutines are all the same as those outside of it. However, I still want to use something like a parameter. Therefore I leverage the Stack object. With it, I can push a “parameter” onto the stack and pop it off inside the DropBall subroutine.

The following code (in bold) is added to the main While loop. Notice I am now also tracking the number of dropped balls.

While (droppedBalls < ballsMax)
  Shapes.Move(dropper, dropperX, 50)
  Program.Delay(10)
  'randomly drop balls at different times
  If (Math.GetRandomNumber(100) > 95) Then
    Stack.PushValue("p", dropperX + 30)
    DropBall()
    droppedBalls = droppedBalls + 1
  EndIf
  SetIncrement()
  dropperX = dropperX + incrementX
EndWhile

Of course I also need to define DropBall. This method creates a randomly colored ball and then defines a loop. The loop is used to show the ball dropping down the screen. A little coordinate math is used to make sure the ball drops from the right place (x) and only goes down the screen (y). The following shows the code:

Sub DropBall
  'set ball's x and y coordinates
  ballX = Stack.PopValue("p")
  ballY = 90
  'add ball and move it into position
  GraphicsWindow.BrushColor = GraphicsWindow.GetRandomColor()
  ball = Shapes.AddEllipse(20, 20)
  Shapes.Move(ball, ballX, ballY)

  While (ballY - 20 < GraphicsWindow.Height)
    Shapes.Animate(ball, ballX, ballY, 1000)
    ballY = ballY + 5
  EndWhile
EndSub

Notice also the use of Shapes.Animate. This allows the ball to be dropped slowly down the screen independently from other balls. It ensures I can drop multiple balls at a single time. However, as you will see in a minute, it is a major gotcha.

The following shows the application running and dropping balls.

Step 5: Test to see if the Ball is in the Bucket (Hit Test)

The last challenge (or so I thought) was to write a test to determine if the ball has hit the bucket. For this I create another subroutine called TestForBallInBucket.  This method will get called every time the ball (or bomb) moves.  There are two basic tests: first, I determine if the ball is in the same area of the paddle. Next, I determine if the x coordinate of the ball is within the x coordinates defined by the paddle (and its width). If the tests pass, I call a method to increment the score. I then move the shape off the screen to ensure it doesn’t score again on the next pass down the graphics window. The following shows the code:

Sub TestForBallInBucket
  'is the ball in the paddle area?
  If ((ballY + 20) >= GraphicsWindow.Height - 20) Then
    'has the paddle caught the ball?
    If (ballX < (bucketX + 50)) And (ballX >= bucketX) Then

      'score the point
      Score()

      'move the ball off the screen
      ballY = ballY + 60
      Shapes.Move(ball, ballX, ballY)
    EndIf
  EndIf
EndSub

The Score subroutine is very simple. It rewrites the score area on the screen with the updated score. It also plays a short sound. The following shows an example:

Sub Score
  gameScore = gameScore + 1
  'clear current score
  GraphicsWindow.BrushColor = "Blue"
  GraphicsWindow.FillRectangle(1, 1, GraphicsWindow.Width, 40)

  'show new score
  GraphicsWindow.BrushColor = "White"
  GraphicsWindow.DrawText(5, 5, gameScore)

  Sound.PlayClick()
EndSub

The last step is to call the hit test from within DropBall. To do so, you add the call (shown in bold) to the While loop as follows:

While (ballY - 20 < GraphicsWindow.Height)
  Shapes.Animate(ball, ballX, ballY, 1000)
  TestForBallInBucket()
  ballY = ballY + 5
EndWhile

You can now run the game and notice the results. It seems to almost work okay. However, you will notice that the hit test and scoring is not working correctly.  This is the gotcha. Recall that the ball moves using Shape.Animate. Also recall that there are multiple balls being dropped. This means each ball is falling based on its own schedule.  The While loop that drops balls and the Animate method does not block the program. This is a good thing from the perspective of usability. However, the hit test will never work correctly. The loop completes before the ball actually comes near to the bottom of the screen. KABOOM indeed!

Step 6: Changing the Game

There is not much I can do to code around the issue with hit testing an Animate inside of Small Basic. Therefore, my only real option is to change the game. The big change is that I can only really drop one ball at a time if I intend to be able to test for its intersection with the bucket. This would make the game too easy. Therefore, I need to change the challenge a bit. I decided to do two things: make the dropper more random and erratic (harder to follow) and randomize the speed of the ball drops. The following walks through the changes.

First, I modified SetIncrement to increment the dropper on a more random (or jumpy basis). The following shows the code (in bold).

Sub SetIncrement
  'set the increment to be random = jumpy dropper
  incr = Math.GetRandomNumber(30)


  If ((dropperX + 80) > GraphicsWindow.Width) Then
    incrementX = -incr
  EndIf
  If (dropperX <= 1) Then
    incrementX = incr
  EndIf
EndSub

Next, I modified the DropBall routine to get rid of Animate. I replaced it with Move followed by a Program.Delay. This will pause the entire program as the ball drops. This lets the hit test work correctly. The following shows the code changes (in bold) made to DropBall:

Sub DropBall
  'set ball's x and y coordinates
  ballX = Stack.PopValue("p")
  ballY = 90

  'add ball and move it into position
  GraphicsWindow.BrushColor = GraphicsWindow.GetRandomColor()
  ball = Shapes.AddEllipse(20, 20)
  Shapes.Move(ball, ballX, ballY)

  dropSpeed = 2 + Math.GetRandomNumber(15)

  While (ballY - 20 < GraphicsWindow.Height)
    Shapes.Move(ball, ballX, ballY)
    Program.Delay(dropSpeed)

    TestForBallInBucket()
    ballY = ballY + 5
  EndWhile

EndSub

I now have a working game! It is somewhat challenging and can be made more so by changing a few variable values. You could also add an outer loop to add levels that get progressively faster. However, it still looks a little too simple: it lacks icons and images. The next step allows you to quickly change things to use images instead of shapes.  

Step 7: Add Graphics

Small basic made adding graphics to the application very easy. The hard part was drawing the graphics. I used Paint and my very poor skills to create a dropper bandit, a bucket for catching bombs, and a bomb image. I constrained these images to the same size as my shapes. This meant swapping out the shapes with images was really easy. I simply modified the shape creation calls to load the image from my hard drive. The following shows the three lines of code that required modification:

bucket = Shapes.AddImage("c:\kbgame\bucket.bmp")
dropper = Shapes.AddImage("c:\kbgame\bandit.bmp")
ball = Shapes.AddImage("c:\kbgame\bomb.bmp")

You can get these images from the final version posted here (2.36 kb). When you run the game, it has a slightly better look as shown below:

Conclusion

I hope you have as much fun with Small Basic as I did! Consider using it to teach someone a little about bit about programming.