.NET Zone      
 
Smack the Santa: Creating a Game in VB.NET (cont.)

Smack That Bad Boy!
To register a smack, you must have a routine associated with the Click event of the dynamic Santa buttons. All the routine needs to do is increment a counter. The following Smack method runs when the user smacks a Santa. Here, I've added an image switch for a little flare.

   Sub Smack(ByVal oSanta As Object, _
      ByVal eOuch As EventArgs)
   
      iSmacked += 1
      oSanta.Image = Me.btnSanta_Smacked.Image
      sbStatus.Text = iSmacked.ToString & _
         " Santas Smacked!"
   End Sub
One note about the images: Because defining the source of an image is not a matter of merely specifying the source file, I found that the easiest way to use images with dynamic forms is to add those images to button controls on the Control Form, setting their Visible properties to False. Then, when I instantiate the new controls on the dynamic form, I simply set the new control equal to the existing control. Or, as in this procedure, I assign just the Image property.

Finally, the Smack method updates the text of the status bar that appears on the new form. Also, with all the new CLR methods and properties available, I've stopped using the CStr function and instead use the ToString method (inherited by every class from Object) to convert my counter to a String.

Get This Party Started: Create an On-The-Fly Form
The event handler for the Smack Him! button pulls everything together and creates the dynamic game form. The first step, of course, is the procedure declaration. Again, as an event handler, certain arguments are required. Here, the IDE created the declaration for me automatically when I double-clicked btnSmackHim, so I've stayed with the default argument names.

   Private Sub btnSmackHim_Click (ByVal sender As _ 
      System.Object, ByVal e As System.EventArgs) _
      Handles btnSmackHim.Click
When a user clicks the Smack Him! button, you need to define the dimensions of the form and the array of Santas based on the selections the user made in the Control Form. Because the trackbar values are available without specifying the parent object, I just assign them to the global variables iRows and iCols, which are easier to type. Brilliance is lazy, after all.

      'Define the dimensions of the form
      iRows = tbRows.Value
      iCols = tbColumns.Value
      iSantaCount = iRows * iCols
After finding out the exact number of Santas that will be needed, based on the row and column counts, I can re-dimension the array I declared globally. I'll repeat that last part...the array I declared globally. That's the trick to using a variable number of controls. Several different procedures need to access these controls, so I declared an array at the Class level with "Dim arrSantas() As Button". At any point, in any private procedure, after discovering the actual dimensions of the array (as chosen by the user), you can redefine that array using the ReDim statement.

      ReDim arrSantas(iSantaCount)
Next, the method declares a couple of private variables, iThisRow and iThisCol.

      Dim iThisRow, iThisCol As Integer
Now comes the start of something great, the instantiation of the Form object. After creating the form, you can start adding all the new controls and events to it. First, declare the form and set its size, starting location, and title bar text.

      Dim frmChimney As New Form()
      frmChimney.Size = New Size((TWIDTH + 10) * _
         iCols + 10, (THEIGHT + 10) * iRows + 50)
      frmChimney.StartPosition = _
         FormStartPosition.CenterScreen
      frmChimney.Text = "Smack The Santa!"
      sbStatus = New StatusBar()
Note that the value of the Size property is actually an object of the Size class, not a primitive value like Integer or Long. One of the ways you can assign a value to the Size property of the form is to simply declare a new, unnamed, Size object. Constructors let you set an object's initial properties in its declaration. A class may have many constructors, each of which accepts a different set of arguments, creating unique "signatures." One Size class constructors accepts Width and Height arguments, both of type Integer. The global constants TWIDTH and THEIGHT define the width and height of each Santa button; the code adds some padding all around to give the buttons a little room to breathe, plus extra padding on the bottom for the status bar control.

With the form declared, you can start adding controls. First, add the status bar.

      frmChimney.Controls.Add(sbStatus)
Next, add the Santa buttons. This is a little trickier, obviously. I've placed them in a matrix based on the dimensions requested by the user in the Control Form.

      'Create and add controls to the form
      For iThisRow = 0 To iRows - 1
         For iThisCol = 0 To iCols - 1
            iThisSanta = (iThisRow * iCols + iThisCol)
            arrSantas(iThisSanta) = New Button()
            With arrSantas(iThisSanta)
               .Name = "btnSanta_" & CStr(iThisSanta)
               .Visible = False
               .Bounds = New Rectangle((TWIDTH + 5) * _
                  iThisCol + 5, (THEIGHT + 5) * _
                  iThisRow + 5, TWIDTH, THEIGHT)
               .Image = btnSanta.Image
            End With
            AddHandler arrSantas(iThisSanta).Click, _
               AddressOf Smack
         Next
      Next
Most of this is self-explanatory if you're familiar with VB's For...Next loops. The With...End With block is more interesting because the base object is a member of the arrSantas array. It's worth mentioning that the lower bound of arrays in VB.NET is always 0.

The Bounds property is new to VB.NET controls. It combines the functionality of both the Size and Position properties. Similar to the Size class, the Bounds property takes an instance of the Rectangle class as a value rather than one of the primitive data types. The Rectangle constructor used here accepts, in order: the x and y coordinates of the upper-left corner for the control, the control width, and the control height. The Image property, as mentioned before, holds the value of the Image property copied from one of the dummy buttons on the Control Form.

The last line in the loop adds the button Click event handler. As previously covered in the StartClock procedure, you can use a single, simple AddHandler statement to assign any procedure you want to this event. Now, clicking on any of the new Santa buttons will execute the Smack method.

Of course, creating all these buttons would be pointless without adding them to the form. Fortunately, VB.NET offers a way to add the entire array at one time rather than having to iterate through each object:

      frmChimney.Controls.AddRange(arrSantas)
Before launching the form, you must do one last thing—start the clock ticking. The easiest way to do this is to assign the StartClock procedure you saw earlier to handle the Load event of the form. Doing that triggers the procedure when you show the form, without any extra effort on your part. Brilliance is lazy!

      AddHandler frmChimney.Load, AddressOf StartClock
Finally, let the games begin:

         frmChimney.Show()
      End Sub
Where to Go From Here
This walkthrough demonstrates how easy it is to generate dynamic forms. Using the techniques you've seen in this article, you can create controls on the fly, create and associate event handlers with those controls, and then add them to a dynamically generated form. But that's just the basics. As you compile and play the game, you'll begin to notice features that are not there that you may want to add. For example, try implementing a time limit, so that you have to smack as many Santas as possible within a given interval. Or add a stopwatch, to see how quickly you can smack a set number of Santas. Consider adding something fairly intricate, a High Score mechanism, that would involve reads and writes to a data source of some sort. Or try something simple, like adding a Close button to the dynamic game form.

The code here should be enough to get you started. As always, the DevX discussion boards are open for bragging and trash talking. So, have fun smacking your Santa this happy holiday season!


Justin Whitney is a Lead Engineer with DevX and the creator of several games that double as learning activities, or vice versa. His latest, DevX New Worlds, mixes .NET Web Services with 3D graphics in another showcase of his not-so-secret desire to be a game developer. You can contact him at jwhitney@devx.com.


The Popup Mechanism

Introduction

Introduction The Smack The Santa Control Form Global Variable Declarations
The Popup Mechanism Smack That Bad Boy!  


 





 TALK BACK
Have the problems associated with browser incompatibilities, technology advances, and .NET killed off DHTML and browsers for distributed application development? Let us know in the talk.editors.devx discussion group.
Click here to Join
Get the code for this article

The .NET Framework SDK

.NET Events

Grouping Data in Collections





 
Sponsored Links

Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map
Jupiterweb networks

internet.comearthweb.comDevx.comClickZ

Search Jupiterweb:

Jupitermedia Corporation has four divisions:
JupiterWeb, JupiterResearch, JupiterEvents, and JupiterImages

Copyright 2004 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Jupitermedia Corporate Info | Newsletters | Tech Jobs | E-mail Offers

Copyright Information/Privacy Statement