REALbasic University Resources:

RBU: Glossary Defines common REALbasic programming terms
  Archives Previously published columns
Translations: Dutch Courtesy of Floris van Sandwijk
  Japanese Courtesy of Kazuo Ishizuka
  Chinese Courtesy of Dong Li
  RBU Translation Guide Information on Translating RBU into other languages
Books: Matt's Book (2nd Edition!) Ideal for experienced programmers
  Erick's Book Best for beginning programmers
Websites: Mother Ship The publisher of REALbasic
  RB Webring Links to hundreds of REALbasic websites
  RESExcellence Another REALbasic programming column
  REALbasic Developer Magazine The premiere source for REALbasic instruction.

REALbasic University is Sponsored by

Make your Mac do what YOU want it to. Create games, utilities, cool Mac OS X tricks. Download REALbasic now and create your own software.


Print This Article

REALbasic University: Column 048

RBU Pyramid XXI: Wrapping Up

RBU Pyramid is finished! Yeah! I'm sure we're all sick to death of card games, and it will be fun to go explore other topics, but before we do, I'd like to take this column to examine what we accomplished with RBU Pyramid, and analyze the success/failure of RBU during this project.

Did you enjoy the creation of RBU Pyramid? Were the lessons too drawn out? Was the pace too slow, too fast, or just right? I'm interested in your opinion, of course, but I'll offer my own analysis as well.

My Original Goals

Wow, we've spent a whopping twenty weeks working on RBU Pyramid. That's more columns than I originally anticipated (I was thinking of about a dozen), but then it's difficult to judge a project like this until you actually do it.

(Guilt trip: Now that you see how complicated even a simple card game is to create, I hope you'll all remember to pay your shareware fees next time you're asked!)

I know there are a few people who didn't like me spending so much time on a mere game, but I felt this was a valuable project for a number of reasons.

First, I wanted to show the development of a complete, full-featured program, with support for multiple undos, a help system, saved preferences, graphics, a high score chart, etc. All the tutorials I've ever completed create something basic and ordinary. Many times it's an example program, not even finished! When I first started programming, I found I could easily finish a tutorial, but the real challenge was going beyond that: I'd decide I wanted to add a tiny extra feature or enhancement (like a fancier About Box), and then bang my head against the wall in frustration. If only there was source code showing me how someone else solved those same problems!

I knew from the beginning RBU Pyramid was going to be an extensive lesson, but since it's the kind of thing I always wanted when I was learning to program, I wanted to write it.

My second goal with this series was to demonstrate the actual process of writing a complete program. Beginning programmers often stumble through a project, learning as they go, wondering the entire time if they're even vaguely on the right track. I wanted to show that even seasoned programmers have to make complex decisions, compromises, and even mistakes. That's encouraging for beginners, and the process of second-guessing, revising, and correcting mistakes is valuable for everyone.

The third goal I had in mind was to continue the RBU tradition of actually explaining why things are done the way they are. I hate tutorials that just say, Step 1, do this, Step 2, do that, etc. If that approach worked, everyone who's done a painting-by-numbers kit would be a famous artist!

If there are multiple ways to do something, I like to justify the approach I'm taking. If we're learning about solving a particular problem, I like to explain the concepts behind that situation, and detail alternative solutions.

So, how did I do? Did I meet my goals? Was the pace of learning too slow or too fast?

Only you, my readers, can answer that question, and the answer might be slightly different for each of you. Overall, I'm pleased with the results of the project.

The aspect of following a complete project from concept to completion worked very well: there were many small lessons that grew naturally out of the project context. Those small lessons -- explanations about data structures, bug fixes, exchanging data with a dialog, etc. -- are too small to have an article written about them, yet they crop up all the time in real-life projects and are often the thing that frustrates a beginning programmer.

While the project dragged on a little longer than I'd anticipated, for the most part it was because certain aspects of the project just needed more explanation, and I don't regret taking the time to explain things. I do, however, wish I'd planned ahead just a tad bit more: I had my version of Pyramid almost but not 100% finished before I started this series, and that caused some problems in creating the tutorial. More significantly, I should have planned in advance exactly which parts of the program I was going to explain in which columns -- written a complete breakdown of the program in outline form. Since I didn't, the columns wandered a bit, and I ended up needing a series of "miscellaneous" columns to wrap things up.

There was one thing I had expected to do in this series that I didn't. When I conceived of this type of tutorial, my original thinking was that it would follow, step-by-step, the moves I'd originally taken as I created the program. It would be like looking over my shoulder as I programmed. You'd see me make mistakes, revise my strategies, amd insert debugging code in an effort to track down odd glitches.

I would still like to do that kind of tutorial someday, but it couldn't be on a project as complex as RBU Pyramid. There were several reasons I didn't do RBU Pyramid that way.

First, for that kind of tutorial to follow my every move, I must document everything I do down to the smallest detail. In the case of RBU Pyramid, I'd already started writing the game before I'd decided to use it as part of a REALbasic University project. By that time I'd forgotten most of my early steps and it would have been artificial and inaccurate to go back and retrace my steps.

Second, that level of detail would take too much time. It would be interesting to read and there'd be value in it, but for a weekly column it would take over a year to finish the game!

For example, look at the undo system I created for RBU Pyramid. For the column, I presented that across a couple lessons and that was that. In real life, of course, I added the undo system after the game was almost done (not a good strategy) and it took me some degree of hassle to figure out how to wedge that into my existing design. There were some major bugs and I spent several long Saturdays playing RBU Pyramid and attempting to undo in an effort to figure out which actions didn't undo properly. If I'd documented my entire process, it would have taken four or five columns. And that's just for one feature!

Finally, I questioned how much value there'd be for you to wallow in my mistakes. Yes, it might ease your ego a little to know that even a (hem) pro like me makes mistakes, and yes, you might find my debugging techniques helpful in your own bug hunting expeditions, but in many ways reading about that might be like reading two or three rough drafts of Moby Dick!

So in the end, I decided to present a fairly straightforward, finished solution (minus a few bugs), and in retrospect, I still feel that was the correct decision.

In Detail

By the way, if you're wondering why I'm performing this self-critical analysis, it's because I desire to learn from what I've done. This is a valuable habit I learned from my high school journalism teacher.

After every issue had been printed and delivered, the journalism class would gather to critique the newspaper. We'd each grab a copy, a big red marker, and spend an hour pouring over it for the slightest error. We'd mark obvious mistakes like spelling errors and crooked headlines, but we'd also circle less noticeable problems like poor layouts, awkward writing, or mediocre photography.

Good points were also marked, and we'd note if an area that was weak improved. For instance, we had a period where our headlines were always done at the last minute and they were plain and boring (like "Speech Team Wins Tournament"), so we made a concious effort to improve our headline writing and the whole class was pleased when headlines became more interesting and inviting (like "There's No Debate About It: Our Speech Team Rules").

Because the whole class was involved, the critique became a sort of competition: who could find the most errors? When everyone was finished, we'd all compare our findings, and similar to the scoring of a Boggle game, only errors that no one else found were considered valuable.

We didn't actually keep score, of course, and there was never any blame addressed for any of the mistakes. It was all in the interest of education and improving ourselves, and I found it wonderfully therapeutic and valuable. I do it today in many parts of my life: you can apply the same type of analysis to anything.

In every project, there is always pressure and compromise, and often you'll feel like you did well in the cirmcumstances, but in real life, when paper meets ink, circumstances don't mean squat: it's all in the results. Taking time to look back and study what you did can be humbling, but it's also rewarding, for you see your successes as well as your mistakes.

In the case of RBU Pyramid, studying what was good and what was weak will help me write better tutorials in the future, and we'll all be the beneficiaries. And it's good for me to write about in public like this, because you'll read it and tell me if I'm right or wrong! (Please do, by the way: feedback is what makes this process work.)

What We Learned

So what did we learn in developing RBU Pyramid? It's surprising, when you go back and through the twenty lessons, how much we covered. Here are a few of the key techniques and skills we studied:

  • Planning an interface
  • Developing a data structure
  • Drawing playing cards programmatically
  • Creating a card object (a custom canvas) that knows how to draw itself, be selected, etc.
  • Using a control array
  • How to shuffle cards
  • Adding sound effects
  • Handling Preferences
  • Creating an About Box and Splash screen
  • Creating a "hot canvas" object (links to an Internet URL)
  • Using Contextual menus
  • Drawing a background pattern
  • Figuring out to detect valid moves
  • Adding a high score dialog
  • Remembering a window's size and position
  • Adding a help system
  • Adding an undo system
  • Adding a confirmation dialog box
  • Passing information between a dialog and your application
  • Working with menus
  • Safe shuffling
  • Adding a Mac OS X icon
  • Tracking and fixing bugs

While the tutorial was specific to RBU Pyramid, the basic techniques we covered are not. You can reuse many portions in other programs: the Preference system, the About Box/Splash screen system, the code that saves a palette's size and location, the help system, the background pattern drawing, the undo system, the hotCanvas custom canvas, etc.

Remember, REALbasic makes it easy to reuse code: you can drag a custom class, module, or window from your project to your hard drive to create a copy of that on disk. Then you can easily drag that into another project to reuse it.

REALbasic University Quick Tip

Starting with REALbasic 4, you can allow multiple programs to link to the same module or class! This is a terrific feature: if all your programs rely on the same class, for instance, you can make a single change to that class that will update all your programs (obviously, you do have to recompile them).

To do this, drag a module or class into your project while holding down the Command and Option keys. It's just like making an alias in the Finder: in fact, like the Finder, RB will change the arrow cursor to show a tiny alias return arrow to remind you that you're creating an alias.

Just remember never to delete that module or class from your hard drive: that's your master copy and there's no longer a copy inside your project!

That's a Wrap

Well, that's enough of a wrap-up for RBU Pyramid. I hope you enjoyed the project and learned something, and I hope you find time in your busy schedule to actually play the game occasionally.

Next week we'll have a little change of pace, and then we'll get back into a series of smaller, simpler, "one-shot" lessons for a while.

Next Week

A special surprise...

Letters

Proving that you can learn something new every day, I received a couple letters from people explaining what's going on with the Symbol font weirdness I mentioned in last week's column.

First, from Avi Drissman:

I'm not a usual reader, as I don't use REALbasic, but I followed a link from MacFixIt, and I have an answer for you about the Symbol font problems you were having.

You were speculating that the differences between the behavior of BBEdit and TextEdit were due to Carbon/Cocoa. In fact, it's due to the fact that TextEdit is doing Unicode correctly.

In BBEdit, you typed ߁ (I hope these symbols come through the mail), changed the font to Symbol, and you got the card suit symbols. That happened because BBEdit does not (apparently) use the new Unicode-savvy font routines. The old font routines see an 8-bit character, and show symbols the way they always did.

But TextEdit uses much smarter font routines. When you type ߁ into TextEdit, it sees them as Unicode--U+00A9 (), U+00DF (), U+2122 () and U+00AE (). The card symbols you're looking for are actually somewhere else in Unicode: U+2660 (spade), U+2663 (club), U+2665 (heart), and U+2666 (diamond). So even though you changed the font to Symbol, the font routines make sure that the actual symbols it's displaying don't change. It figures that if you wanted the card symbols, you would have given it the correct Unicode characters for them.

So how do you actually type those things? You need to turn on some keyboard layouts. Go to the International preference pane, and click the Keyboard Menu tab. There are two different keyboard layouts that would work. If you enable the Symbol layout, and use it to type in TextEdit, you'll get all the symbols you expect, because the Symbol layout is built so that all the keystrokes generate the Unicode needed to produce the same symbol that you would have gotten with that keystroke in the Symbol font back in Mac OS 9 days.

A different keyboard layout that would also work is the "Unicode Hex Input" keyboard layout. That lets you type the actual Unicode code points. For example, to get the spade (U+2660), you pick that keyboard layout, hold the option key, and type "2660".

I imagine that REALbasic uses the new font routines, and that's why it stopped working. Maybe one of the font routines that it used got smarter about Unicode from 10.0 to 10.1. I can't really say.

Avi

I also received this nice explanation from the manager of Apple Computer's Font & Language department (sorry about the special characters not being correct, but this is the way they came through in the email and I'm not sure what they're supposed to be -- you still get the message, however):

Dear Mr. Zeedar,

I read your recent RealBasic University column on problems displaying the Symbol font on OS X, after seeing it mentioned on MacFixIt. I thought I would write to you to try to clear up a little of the mystery.

This problem is caused by the interaction between an old technology and a new technology. The old technology is WorldScript, which was Apple's approach to supporting different languages, and the new technology is Unicode.

In WorldScript, each writing system has its own character set, and a given character code (say, 0xBD) means different things in different "script systems" (e.g., Roman, Japanese, etc.) and sometimes even in different fonts in the same script system.

In Unicode, an international standard (www.unicode.org), every character has a uniquely assigned value; Unicode is a single character set that covers most of the world's writing systems. The character code for a character does not change in Unicode, no matter what language or font is being used.

So how does Symbol fit into this? Symbol is a font that uses its own, unique character set, but declares itself to be a font that uses the MacRoman character set. You can see this in your article when you change the font in BBEdit; the same character codes given different glyphs.

The issue with Symbol and Unicode is that in Unicode, the characters in Symbol (like the card suits, ݒ ) have their own, unique character codes which are distinct from the character codes used for characters like . You cannot change to by changing the font in Unicode. is Unicode value 0x00A9; is Unicode value 0x2665.

So the issue is not Carbon vs. Cocoa; the issue is WorldScript vs. Unicode. All Cocoa applications are based on Unicode; Carbon applications are a mix, though most still use WorldScript at the moment. SimpleText and BBEdit are WorldScript-based applications.

Normally this is all handled transparently; when text on the clipboard is converted to Unicode, Cocoa notices that the font is Symbol and assigns the right Unicode character values. However, BBEdit does not put font information on the clipboard, and so Cocoa had no way of knowing that the font in question was Symbol. If you try the same copy and paste experiment from SimpleText to TextEdit rather than from BBEdit to TextEdit, you'll see that the data comes across fine.

Once the characters were in TextEdit with the wrong character values, there was no way to change them by changing the font. Cocoa does font substitution, so when you had a in your document and tried changing the font to Symbol, Cocoa said "Dear me! This font doesn't have in it. I'd better find another one to use." That's why you continued to get even though you had Symbol selected. In Unicode, to paraphrase Gertrude Stein, a is a is a .

As to why your RealBasic application stopped working, that's hard to say; I think the developers of RealBasic would have to look into it. It's possible either that the font information was lost, or that RealBasic is using Unicode to draw and is converting the information from the Symbol character set incorrectly. I can assure you that nothing changed in Mac OS X 10.1 that would prevent Symbol from being drawn correctly; I've verified that the characters display correctly in both Unicode and non-Unicode applications.

Thanks for both of these explanations -- Mac OS X is quite a different beast than regular old Mac OS.

Finally, we've got an interesting question from a reader in France:

Dear Marc,

I have a question about initializing scores to zero in newGame methode. I tried to fix this little bug myself before your last column. I added at the end of the newGame code the two lines:

  
gPyramide=0
gScore=0

It did not work. So I added a third line:

  
scoreCanvas.refresh

and it worked fine.

But I see that you put at the top of the methode only the two first lines, and it works. Can you explain why the "scoreCanvas.refresh" was needed in the first case and not in the second?

Thanks for an answer, and thanks a lot for the columns. (and sorry for my English!)

Jacqueline Gouguenheim-Desloy

Your English is no doubt better than my long-neglected French, Jacqueline! (Mon français est terrible! ;-)

Your question is a good one: I've often seen situations where an item needed a "refresh" to work properly, and it can be a mystery as to when it's needed and when it's not. All the refresh command does is force the item in question to redraw. In your case, your code did work -- the actual score was reset to zero -- it just didn't update the visible score the viewer saw. Forcing the redraw made the new score display.

Normally REALbasic "knows" when an item needs refreshing and handles it automatically. I don't know the specific order that RB follows when it decides to refresh something, and I haven't analysed exactly what's happening in this case, but my suspicion (and this is my unqualified and non-scientific answer) is that the change is happening too fast.

In your case, you put the initialization stuff at the end of the method, while I put it at the top. In my case, several other things happen before the end of the method (a fresh deck of cards is dealt, for instance). That gives the initialization change time to "sink in."

My theory is that in your case, the value of the score is changed at the very end, but the program has already moved past the "drawing the score" portion of the program and so it draws the old value.

Scientifically, this is bunk: it doesn't make any sense at all. I mean, when you change the value of a variable, it should be changed immediately. And a drawing routine that updates the score ought to reflect that immediately. But I've seen too many times where that wasn't the case and that's how I developed my "sink in" theory.

I certainly don't take my theory seriously, but it does make a good rule of thumb. Even you must have instinctively sensed it because you added a refresh command when you saw your scores weren't updating: why else would you think of adding that as a way around the problem?

So the short answer is I don't know why this happens sometimes. But forcing a field to refresh, unless you're in the middle of a long loop, is generally harmless. (In the middle of a loop it will make your loop 100 times slower.) So refresh away and don't worry about it: it's generally a minor problem (though it can be disconcerting to debug).

And maybe some RB expert out there has a better answer: I'd be happy to publish it in a future column.


About the Column
REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers.

Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.)

About the Author
is an author, philosopher, graphic designer, photographer, film director, soccer fanatic, and programmer (among other things). He writes for MacOpinion, runs his own software company, Stone Table Software, which sells the revolutionary Z-Write word processor, and is Publisher and Editor of REALbasic Developer. He lives in Northern California with his cats, Mischief and Mayhem, and is rapidly running out of free time.

See the REALbasic University Archives


REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.

Email This Article - Comment On This Article

.

Reader Specials

Server Racks Online:
Apple Xserve CompatibleServer Racks and Universal Network Racks
42U KVM Switch Solutions:
High-End Mac and Multi-Platform KVM Matrix switching solutions!
Digital Camera Online:
Great prices on Digital Cameras and accessories!
KVM Switches Online:
Great prices on Mac KVM Switches from the leading manufacturers!
LCD Monitors Online:
Great prices on LCD Monitors from the leading manufacturers!
LCD Projectors Online:
Shop online for LCD Projectors from the leading manufacturers!
USB 2.0 Online:
Great prices on USB 2.0 products from the leading manufacturers

Serious Business Software:
Accounting, Sales, Inventory, CRM, Shipping, Payroll & more!

KVM Switch solutions for MACs:
DAXTEN is a KVM switch, KVM extender and monitor splitter specialist for PC, SUN and MAC applications from name brand manufacturers - offices worldwide.

The "Think Different Store: The iPod Accessories Store - iPod cases, iPod mini, iPod photo, speakers, itrip, inMotion, Soundstage and all other iPod accessories

Earn Cash with the ThinkDifferent Store Affiliates Program

Need A Web Site?
Applelinks Web Hosting Starting at 19.95 a Month

iTunes_RGB_9mm

.

iTunes_RGB_9mm

Cool Mac Gear


iPod 1G-2G
iPod 3G
iPod 4G
iPod Mini
PowerBook-iBook
Keyboard Skins
Garageband