Welcome to my Programming Blog...

I am currently working on a couple of projects: An original game called "Implosion" which I am porting from Flash to the iPad, and a remake of Q*bert in Python (pygame), as part of the class I am teaching. Please feel free to use the "Labels" (at right) to follow a specific project or theme. If you are one of my Python students, I recommend that you check out the Python thread.

Monday, May 31, 2010

Progress

Oh, we're cookin' now! (Summer vacation rocks!)

I now have seven different "selectors" - each a different shape. (Think of Tetris and count...) They all show up great, are movable by the player, rotate, and take chips out. Every time you take out a chip, the old selector goes away and a new one is selected. It's working well. I think I may have even ironed out a bug that sometimes required you to wiggle the rotation of a selector to get it to register. I think it was parked at 360°, instead of 0°.

So what's next? In no particular order....

  • Sounds
  • Scoring
  • A timer - what's a little pressure?
  • Messages - e.g., hints at first.
  • Surprises as the game progresses (sleepers and selectors)
  • Doors, so that the game does progress.
  • Particle effects, for a little pizzaz.
  • A display that rotates based on the orientation of the iPad.
  • Icons, name and snazziness
  • Pause/Start menu
  • High Scores? Maybe with Facebook?
One more strange thing - each of the selectors has a different color, and they are all partially transparent. For reasons that I don't understand, when different selectors appear on the screen, it changes the brightness of what is being displayed. Very odd.

Thursday, May 27, 2010

Progress through Thursday...

It took a bit of a refresher to remember how to initialize multidimensional arrays in C++, but eventually I was able to make it work. I am building an array with the relative coordinates of each of the 4 blocks in the various shapes. So that's 2 coordinates x 4 blocks x ? types of selector shapes.

Once I had that down, I wrote a bit of code to handle the rotation of those coordinates, based on the angle of the selector, as the user has determined (with the two finger rotation method). From that, I was able to respond when the user taps the screen to see whether all four Chips under the selector are the same or all different. If so, the chips will drop away and the screen will fill in. So the game is basically playable! (Though not without its issues.)

Wednesday, May 26, 2010

Belated posting on Implosion

Whoops! It's been a few days since my last post. I have made some progress.

A quick trip to Starbucks (and a few minutes before school on Monday) and I was able to make my 10x10 grid of Chips appear. 

Its looks are deceptive. They actually are chains of Chips, as before, so that if you remove one on the inside, the Chips slide inwards to fill the hole.
I've also been able to write a bit of code to detect a single-click on the screen. Two things are relevant here: the time between the press and release, and the difference between a single click and a double click. Surprisingly, the single/double part is the easy bit - the variable sio2->_SIOwindow->n_tap tells you which it is (1 or 2, or 3, I suppose...). To tell how much time it took between press and release, I created a "clickCounter" variable in my GameManager class. Every render step, it adds the delta time to this variable, and when I press the first finger, I reset the variable. Then when I detect the last finger leaving the screen, I can detect whether a sufficiently short period of time has elapsed to call this a "click."

So, once I have detected a click, I can then remove the Chip at the origin of the Selector and the rest of the Chips fill in. Things are starting to look right... 

Saturday, May 22, 2010

Translation and Rotation - third try's the trick

Graduation was yesterday, and I was on campus for most of the afternoon - so I had a chance to work on Implosion for a while, after the students left, but before the ceremony. It was nice having a block of time... when I wasn't exhausted!

I think I have the one-finger drag and two-finger rotate functions working properly to get the selector working properly. This is the third iteration - the first was based on some incorrect assumptions about how the events for the touch screen worked; the second was based on a very limited data structure - I was using variables like "startTouch1" and "startTouch2" - very specific for only one implementation. The third version is using arrays and is a bit more generic, so I can handle more than two fingers on the screen at once (if I ever want to), I've made the variables named consistently, and I've separated the event detection methods from the ones that actually do the work once I have detected the event.

So how does it work, you ask? (A glutton for punishment, Hmm?)

Here's the outline: First of all, I am maintaining an int variable numFingersOnScreen, to track how many fingers the user has on the screen. When the touch event comes into template.mm's templateScreenTap() function, there are three relevant variables:
sio2->_SIO2window->n_touchIndicates how many fingers have had their touch status changed
_state (a parameter)Indicates whether the fingers were added or removed.
sio2->_SIO2window->locsAn array of where the fingers were that had changed.
So, based on _state, you either add or subtract "n_touch" to/from the numFingersOnScreen.

So far so good, right? I'm also keeping track of two arrays of vec2* variables. These will indicate where the the fingers were most recently (lastFingerLocs[]), and where they are this iteration (currentFingerLocs[]). (For touch/untouch events, these will be the same - when the user drags a finger they will have a useful difference.) Adding a finger is easy - just put the locations from the locs array at the next spot in the two "finger" arrays.

However, when you remove a finger, how do we know which finger was lifted? If I put my index finger and thumb on the screen, how can I tell if I then lift one finger which it is? My solution has been to search the "finger" lists and identify which finger was closest to the one that just lifted. I then remove that one from the list and slide the other fingers' locations towards the front of the list. (I'm only keeping track of five fingers, at most, so this isn't too time-intensive.) If I have two fingers lifted, I do this algorithm once for each finger lifted.
I'm trying to come up with situations when this won't work as well - if the fingers are right next to each other, perhaps? But I'm not sure it matters.
Then, if I just tapped or released, I delegate what should happen to another function, which can determine what to do with the information in currentFingerLocs. (Actually, I send it to one of several functions, based on numFingersOnScreen.)

Drag events are the next question. They come into template.mm in another function, but the information is stored in the same n_touch and locs variables - how many fingers moved, and where are they now? I use the same algorithm to identify which fingers on my currentFingerLocs list were moved, and I update their locations in that list (but not in lastFingerLocs, yet). Then I delegate the code to other functions (e.g., handleSingleMove() or handleDualMove()) to deal with what happens now. Finally, I update lastFingerLocs to match currentFingerLocs.

It works, and works well, I think. The next thing I need to do is to check that I am not having memory leaks. I am creating a lot of vec2* and vec3* variables - I need to make sure that I am releasing them again. (I think so, by looking at the code, but I need to check.) The Apple Developer Tools have a program called "Instruments" that should help with this - but I need to learn the program!


Thursday, May 20, 2010

Graphical improvements

I'm working on a few little things in Q*Bert this morning. Several of
my graphics were antialiased - that is, the used a light gradations
around their edges to make the curves look smoother. This is usually a
very good thing, but if you change background colors, or use
transparency, you get a light grey outline around the object, which
looks terrible. So I cleaned up some of my graphics.
I've also just updated the coily falling routine so that if you can
trick him off the edge of the pyramid, it clears all onscreen enemies,
and you get 700 points. You are also immune to attack when you are on
a platform now.
Next up: dealing with the death of a Q*Bert.

Sunday, May 16, 2010

Qbert levels

Ok. As of Friday, I have the levels system working, though I have only
created two levels to date. I had a little bout of "forgot to call the
loading function-iris," but I am doing much better now. It's time for
slick and sam, and maybe some scoring.

Rotations - success and frustration

re: implosion multitouch...

I had some success last night writing code to rotate the Selector with two-finger rotations. By playing around with the sio2->_SIO2window->n_touch variable in "templateScreenTap()", I could sense multitouch events. I used an algorithm to compare the angle between the two touches and compare it to the angle between the previous two touches to find a delta rotation and rotate the object by that much. If there were two fingers on the screen, things would rotate. If only one was on the screen, it would twist. After a bit of futzing around, it worked great.

At least in the simulator. (Using the option key to simulate multi-touch)

I figured it was about time to try this in the actual iPad, and I realize now that it is more complicated. Even as I tried to rotate the Selector, it would also move about - sometimes skipping between one location and the other. I think that this is a response to the iPads' sensors being a bit more "messy" than the simulator would have us believe! Specifically, I wonder if I am getting some flicker - when I have two fingers on the screen, perhaps the iPad is occasionally only detecting one.

I've also done a bit of exploring and found that the "templateScreenTap()" and "templateScreenMove()" methods in the template.mm file are just relaying the message from the EAGLView.mm file, and that gives me more information about how that works. The "_state" variable in templateScreenTap, for instance, indicates whether the "tap" was a touch or release event, and it seems to me that n_touch is indicating how many fingers changed touch/release state, not how many are remaining on the screen. Likewise, in the templateScreenMove(), the touches it receives are indicating only the ones that have moved, not a comprehensive list of touch points - and the n_touch variable corresponds to how many have moved, not how many there are. 

This changes my understanding considerably. Even as I wrote this last paragraph, I realize that my assumption that "flicker" was happening (in the previous paragraph) is likely wrong - I was just moving one finger and that caused the problem.

This will require a rethink about how I implement rotation.... For one thing, at the moment, I have been splitting responsibility for managing these touches between template.mm and GameManager - I need to reconsider that split.

Thursday, May 13, 2010

Q*bert progress

By the way, I haven't made too much progress recently on Q*bert. I'm happy to say that I have been answering a lot of good questions and having productive conversations about algorithms for everything from rendering laser beams to differentiating between collisions with horizontal vs. vertical obstacles constructing AI for moving about a maze.
Good stuff, student-initiated, and what they pay me for! (I suspect that somebody has written Q*bert before....)
Yes, I am just writing Q*bert for two reasons:

  1. To keep me occupied a little so that I don't meddle with students during class - otherwise, I start to give unwanted advice and solving problems before the students even understand what the problems are, let alone try to figure them out! (And that's not good teaching.)
  2. To model the process of writing the program like the ones they are writing, for which this blog is a help.
I have made a little bit of progress, however. I am midway through writing a function in my main class that will read a file of level data. One line per level. This will determine what colors appear on the screen, the frequency of enemy appearances, the number of colors the cube tops cycle through, and the type of cycle they have. So that's a work in progress.

Moving ahead, or at least "around"

Some good progress tonight on Implosion.

I have made a "Selector" class which will host the Tetris-like shape.  It is based on the VisualObject class, and consequently has very little code of its own. I was able to link it to the shape in sio2, so I can clone the shape and it renders.

Next I played around a little with the event handlers in the template.mm file that comes with sio2. After not too much trouble, I was able to get the chip to move around, following the "finger." It doesn't matter whether the finger touches the chip - it still tracks it. (Moving right with the finger by 1 cm moves the selector to the right by 1 cm.) So that's pretty cool.

I've also pulled the camera back about 40%, so everything is a little smaller. This will let me fit a 10x10 grid of chips on the screen.

Coming up next:

  • Two-finger twisting of the selector. I suspect that this will be more of a challenge. I'm trying to decide between an algorithm comparing the angle of the line between the fingers at the start and at the drag, or one that uses the cross product of the line between the fingers and the relative motion of the second finger. (Although the second option sounds cool and math-y, I think the first will work better.)
  • Create the grid of 10 x10 squares. Likely to be tougher than it sounds - I don't just want to make a grid of chips like I did earlier - I need to make outward-pointing chains of chips that nest together effectively.
  • Make the selector "snap" to the grid orientation and position. Preferably, this should be animated...
  • Start recognizing where the four squares of the selector are, and which Chips they represent. This means that I will have to search a list of 100 Chips. I wonder if it will be worth keeping the list sorted somehow?
  • Deciding (and implementing) what the user interface should be when I wish to "select" a group of Chips. Should it be a quick shake (+/- z-axis) of the iPad? A quick tap on the screen? Both?
Fun, fun, fun!

Wednesday, May 12, 2010

Refactoring

The problem with quick prototyping is that while it is great for making sure that the core functionality works, it leads to sloppy coding. So, while was able to get my Implosion chips to show up on the
screen and link together as a sequence, I was breaking a few design rules as I did so.

So last night, I did some refactoring - I realized that much of what I had written for the Chip class was stuff that I would like to generalize. I need to be able to keep track of a 3d object's location and orientation, as well as it's reference in the sio2 resource list.

The second benefit to pulling the graphics object out of the Chip class is that it makes Chip less dependent on SIO2. If I should someday decide to go to a different rendering engine, it will be
easier to make the change.

The new class is called VisualObject, and Chip now inherits from it. I plan to extend VO for several other classes, too.

Oh, and I'm working on documenting my code a bit, too.

Tuesday, May 11, 2010

python info

I just found a cool thing for Q*bert - an instructional manual for somebody who owns a coin-op version of the game. Page 7 of the pdf shows statistics about the game and graphics for the characters.

I think I will move on to the file loading portion of the game to make levels.

Platforms

A late update on the Q*bert front - yesterday, I got the platforms working - Q*bert can land on one of them and they will carry him to the top of the screen. It's working surprising smoothly. Next up - I need to create a green guy who jumps down the pyramid like the balls do and resets the cubes' colors. I also need to start thinking about how I will manage levels....

Saturday, May 8, 2010

It's always the little things....

As you may know, I am trying to teach myself two things at once for this iPhone App I am working on - blender, and the SIO2 code library that lets me put blender objects on the iPhone screen. (Actually, I'm aiming for the iPad.)

I've been wanting to make my 4-square selector shapes be translucent - that is, I'd like for them to have an Alpha level of about 50% or so. They will mostly appear behind the Chips, but when a chip drops, I'd like it to be seen, and there may be some artwork behind the chips that is important, also.

I watched the SIO2 tutorial #4 several times, and I even found a correction to the tutorial online since the tutorial hasn't kept up with a few updates. But even though I was doing what the tutorial said, I couldn't get objects to show up with any kind of transparency. I'd create an object that was opaque, and it would show up fine. I'd switch the color blending mode in blender to "Value" or (the new version) "Color," and it would disappear when I tried to view it in the iPhone simulator. What gives?

I was just about to start complaining that the Tutorial didn't work, the support forums weren't very helpful and the only book on SIO2 wasn't much help, when I realized that I hadn't actually looked in the book for this... sure enough, a quick peek in the index led me to a page that indicated the problem wasn't in Blender - it was a one line change I needed to make in my code in XCode. I was only rendering solid objects - I needed to tell it to render the solid objects and the objects with alpha transparency. I needed to change:

sio2ResourceRender( sio2->_SIO2resource, sio2->_SIO2window, 
                        sio2->_SIO2camera,
                        SIO2_RENDER_SOLID_OBJECT |
                        SIO2_RENDER_LAMP);

to

sio2ResourceRender( sio2->_SIO2resource, sio2->_SIO2window, 
                        sio2->_SIO2camera,
                        SIO2_RENDER_SOLID_OBJECT |
                        SIO2_RENDER_ALPHA_TESTED_OBJECT |
  SIO2_RENDER_TRANSPARENT_OBJECT|
    SIO2_RENDER_LAMP);

and everything instantly started working. Sigh.

Thursday, May 6, 2010

Platforms

I'm working on creating the two hovering platforms that sit on either side of the pyramid and carry Q*bert to the top of the pyramid if he jumps on them. Not too much to show for it right now, though. I am borrowing a lot from the Cubes - so that I can position the platforms the way I would a cube and so I can detect when Q*bert has landed on one.

The other thing I am doing is going back and reviewing whether I am documenting my functions. I realize that I have been a little sloppy, making up functions without putting leading comments before them to remind me what they do. And that's not setting a very good example!

starting with the four-squares

I need to find a way to make a shape that selects four of these chips. The shape is like a Tetris piece. Since this only glides around, it can be a 2-D piece. I could simply make a solid shape, but I have two problems with that - first, that it affects the visibility of at least one of the five chips I have already made, and second, that I am having trouble adjusting the opacity, so I can't see the chips fall behind it. (Or the status of the squares it covers, which will also be important.)
The other option is an outline of the shape - I am playing with either a very sharp-cornered shape, like the one at right, or a more rounded one, like the one at left.
In either case, I think they hug the green box a bit much, but I rather thought that shape was a little large, anyway. I'm not really thrilled with either option, so far.
In any case, I am learning more about blender as I experiment with the program. Now if I could just remember how I was able to create a mesh by clicking where I wanted points, rather than adjusting an existing shape....

Monday, May 3, 2010

... Foiled again!

If you are not familiar with the game of Q*bert, you may not know that he has a bit of a potty mouth. In the game, when he gets hit by a ball or enemy, a speech balloon appears above his head with some curse characters, and a sound file plays that is sort of a grumble. I have the visual part of it working now, when he gets hit by a ball.
I don't have the snakes getting him yet, just the balls - but it shouldn't be too hard. I wonder, though, whether the snakes will be too hard to dodge. I'll have to calibrate it a bit later.

... but will anyone listen?

You know, when you are a teacher, you have to expect (and accept) that some of the things you tell your students are going to in one ear and out the other. Teachers know that we are going to have to repeat ourselves or find new ways to get the ideas we are trying to express to stick. Every year, I talk to my AP students about the difference between primitives and objects and the ideas of pointers.

You would think I'd be paying attention, myself.

I got bogged down in a puzzle this weekend - I had Chip objects that had a set of coordinates for their current position, and another set of coordinates for their destination. I'd start them off the same, but if they were ever different from each other, they would move a tiny little bit towards the destination, until they arrived there. Except when I changed the destination coordinates, they would just jump to the new location - they wouldn't glide; they'd teleport!

If you understand pointers, you can probably tell what my problem was - but it took me a couple of hours to puzzle it out (and find some other bugs along the way, but that's another story). Because I had set the myLoc and myDest variables to point to the same object, when I changed the coordinates of myDest, it changed the coordinates of myLoc, too. When I went back and changed my setter methods to make clean copies of the (x, y, z) coordinates that weren't the same object, suddenly things startes working right.

I wonder what else I was saying that I didn't listen to? I'll bet I need to do a better job documenting my code....

Sunday, May 2, 2010

Chain, chain, chain....

Some good success this weekend - I have gotten the chain of chips to work properly. Each chip is part of a sequence now. If one of the chips is removed, the ones past it glide in and replace it, and a new chip is dropped into the mix. (Your view is from above.) Here's a quick video - every time I click, a random chip is dropped:

The way this works is that each Chip has a "follower" and a "leader" - it is essentially a node in a doubly-linked list. Each chip also has two sets of coordinates - where it is now and where it is moving to, as well as a boolean that indicates whether it is in the process of moving. When a chip is removed, it sends its location to its follower, which uses it as its destination, and starts the chip animating. It also removes itself from the doubly linked list, as you would expect - tying its follower and leader together.

This is a major hurdle in the game, and one of the first things that looks great in OpenGL that I couldn't do with the Quartz commands - check out how the chips flip around as they fall away!