Making the wheels spin is actually a bit more complicated than one might think. The 3D model of the car is divided in five different geometric objects. Four of these objects represent the wheels and the fifth object is the rest of the car.
Each object is defined by a number of vertices (points) in 3D space. If you want to spin a wheel, you have to rotate its vertices around its center axis. The problem is that when you rotate vertices using OpenGL, they are rotated around the origin of the coordinate system. Consequently, if you apply a rotation transform to a wheel, it will not spin around its center axis. So what you have to do is move the wheel to the origin, rotate it, and then move it back to its original position.

I extended my OBJ converter script to calculate the center point for each object in the 3D model and then save it along with the geometric data. Then in the car rendering code, I added a translation transform to move the wheel to the origin by subtracting the center point, followed by a rotation, and another translation to move it back by adding the center point again.
The order of the OpenGL transformation calls may look like they're in the wrong order, but this is due to the order in which the transformation matrices are multiplied.
Currently, it takes one separate call to the drawing function for each object in the 3D model, because different transforms have to be applied to the objects. This can be optimized by using the matrix palette OpenGL extension.
Instead of pushing matrices on the OpenGL matrix stack, you precalculate the entire transformation matrix for each object and place them in a matrix palette, which is really an array of matrices. Then each vertex struct is extended with a field that contains an index into the matrix palette, indicating which matrix should be used to transform that particular vertex.
This way you only need one call to the OpenGL draw function to draw the entire model, because no state changes need to occur in between the rendering of the different objects in the model.
I have added lateral movement of the car. Whenever your finger touches the screen, the "requested" lateral position of the car is updated. The car then moves towards the requested position at a preset rate. If the car moved to the new position immediately, it would look like it was teleporting.
I think I'll probably add spinning wheels next.
I created a fairly ugly Formula 1-type car in 3D and exported it as an OBJ file. The OBJ format is a very simple and fairly common plain text format for 3D objects. However, it is not a very compact format, so it takes up a lot of space.
The usual approach is to create an importer in the game engine that can parse and load the OBJ file, but I created a converter in REBOL instead. The converter reads the OBJ file, optimizes the geometric data for use with vertex buffer objects in OpenGL, and finally saves the data in a binary file.
I then wrote a corresponding file loader in C++ in the game framework. It basically loads the binary file straight into the vertex buffer object, since the converter has already organized the data in the same way it is stored in memory.
A lot of things can be improved, but at least now I have a 3D car to play with in my game code. I guess the road may be next!
The time has come to start thinking about the technical details of the iPhone racing game. I like to attack my projects on multiple fronts from the get-go, as it gives me a sense of the overall architecture and requirements quickly.
This is probably not the right place to start, but I've created placeholders for the app icon and the loading screen. I would rather look at placeholders than the default white icon and black loading screen, given how many times you see the icon and loading screen during the development of an iPhone app. More importantly, I had fun doing it.
My iPhone game framework interface is heavily inspired by XNA and the game state XNA sample. Obviously, the implementation of the interface is completely different, but anyone who has ever used XNA would feel at home using my framework. However, I have not implemented anything similar to the content pipeline... yet.
The framework was/is implemented in a hybrid of Objective-C and C++, where Objective-C is really only used for Cocoa specific functionality and the fundamental app skeleton. The main reason for this decision is that I am hoping to be able to reuse some C++ code that I have written in the past for other platforms.
I've decided to use 3D graphics and OpenGL is the obvious, not to mention only, choice for that purpose. Fortunately, I have previous experience with OpenGL, both from work and my own projects. The first time I used OpenGL was in 1998, on a 3Dfx Voodoo 2 GPU. Since then, OpenGL has come a long way. Still, I prefer Direct3D over OpenGL, but OpenGL will have to do.
When I did my master's thesis on terrain rendering, I started out in OpenGL, but I switched over to Direct3D very early on. Fortunately, my abstraction layer allowed me to completely replace the renderer in one single day. It would probably be a good idea to create a similar abstraction for this project, even if OpenGL is the only option on the iPhone.
When it comes to audio, I will go with OpenAL. I have already written a very, very basic implementation of an OpenAL audio engine. I will build on that to create something that is actually usable in a game.
So far, the entries on this blog have been fairly long. It is difficult to be brief when talking about software development and still say something worthwhile. There will probably be shorter entries that are easier to digest down the line as well (this one for example), but I am mostly interested in writing more in-depth entries than I have previouslywritten on the various incarnations of my blog.
One of my favorite programming languages goes by the name of REBOL. It was designed by Carl Sassenrath, who wrote the original Amiga OS kernel. I first encountered the language before it was released on the REBOL1 website (rebol.com), which contained a description of the main concepts and some example code. That was all it took for me to get hooked. I knew immediately that it was going to be a great language.

I downloaded the first public release of the interpreter in 1997 and since then, I have written REBOL code almost every day. I have tried Perl, Lua, Ruby, Python and a bunch of other scripting type languages and there is nothing out there that rivals REBOL in terms of productivity. For me, at least.
Most people have never heard of REBOL. I have won no less than three official REBOL contests (here's one), which either goes to show that I am a REBOL genius or that the REBOL user base is limited. Unfortunately, I am leaning towards the latter.
I have informed a number of software engineers of the existence of REBOL and they always ask me what's so great about it. And here's the kicker: I can't for the life of me explain it in a way that does REBOL justice!
There are so many great little features that you can't really boil it down to a brief summary. And it's not just the features, it's how everything is tied together in a cohesive mass of pure awesomeness.
REBOL is all about the data. There are about 40 different data types. Even the code itself is data. This property of a programming language is referred to as homoiconicity. As a consequence of possessing this property, REBOL is its own meta-language! Usually, C programmers are hopelessly lost at this point, but anyone that has an understanding of Scheme or LISP probably gets it.
Rebol has no keywords. Instead it has symbols. The symbols are data constructs that have no inherent meaning; they are only words. It is not until a symbol is bound to a specific meaning in a specific context that the symbol resembles something a C programmer would think of as code.
You can think of REBOL code as a system of axioms and functions that are derived from these axioms. In REBOL, the common "for" loop is actually a function, which in turn is derived from the "while" loop function. The "while" function is a native function, which means it's implemented in C in the interpreter, i.e. it is an axiom. REBOL provides a number of native functions, and then every other function is built on top of the native functions.
I could literally go on forever, but I will leave REBOL's other fantastic features, such as the series abstraction and the domain specific dialecting, for a future blog entry.
REBOL and the REBOL logo are registered trademarks of REBOL Technologies. ↩
Let's flesh out the game design for the iPhone racing game a little bit more. In the previous post I mentioned the fundamentals. This time I will go into more detail.
The player has to avoid obstacles on the road. There are obstacles that move, in the form of other cars. Bumping into a moving car will slow the player's car down. There are also static obstacles, such as:
Bumping into large static obstacles will stop the car completely for a brief period of time. Oil patches will temporarily make the player unable to control the car. Water puddles will slow the car down.
Some obstacles are not really obstacles however. If the player runs into e.g. a fallen tree trunk, the car will jump. This can be used to jump over certain obstacles.
Obstacles are spawned randomly, but under controlled circumstances, to ensure that the track is not the same every time.
Each level consists of a stretch of road of a certain distance. At the end of every level, there is a checkpoint marker. The player has to reach the checkpoint within a certain time limit, or the game is over. Once the checkpoint marker has been passed, the timer is reset.
The levels get progressively more difficult. There are mainly three parameters for controlling the difficulty:

Different environments will provide visual variety. Colors of the scenery and objects at the side of the road will change depending on what type of environment a particular level represents. It could be a desert, a winter landscape, a forest, a tropical island, or just about any other kind of setting.
The objective of the game is to maximize the player's score. The player gets points for picking up flags along the way. The player also gets points for the amount of time left on the clock when a checkpoint is reached.
An optional feature would be to implement an online global high score table. This would hopefully add competitive value to the game.
The control scheme is easy: the player can only move the car sideways. The speed of the car is determined by the game. The player will move the car laterally by moving a finger, left and right, across the screen.
The game ends when the player does not make it to a checkpoint on time. There is no set number of levels, but at some point, the game will get so ridiculously hard that the player will run out of time, no matter how skilled he (or she) is.
When it comes to web development, there's the server side and there's the client side. Server side development is like any other kind of software development, with all that it entails in terms of consistency, robustness, and sound structures. Client side development, however, is a different beast altogether.
On the client side you have a bunch of different technologies seemingly haphazardly bolted on top of each other. To make things worse, the browser vendors can't even agree on a standard. Every browser has its own quirks and its own set of features. Microsoft's Internet Explorer, version 6 in particular, is infamous for its inability to comply with standards set forth by the W3C.

Traditionally, web developers have relied on a plethora of browser specific hacks and kludges to get by. Every site also used to have more than its fair share of reinvented wheels. The complexity of a more advanced website was truly overwhelming.
Fortunately, as the web has matured, the insanity has given birth to a number of client side frameworks, such as jQuery, mootools, and Prototype. These frameworks sweep the inconsistencies, hacks, and kludges under the carpet. They're still there, mind you, but as a developer you don't have to deal with them directly anymore. Instead, you use the clean and browser independent APIs of the frameworks. This site uses jQuery extensively and I look forward to further experimentation.
Software development is really about managing complexity and while encapsulating a bunch of hacks is not always a good thing, the frameworks reduce the complexity a web developer has to deal with considerably.
OK, so I may as well kick off this blog with an entry about a new project. I've wanted to create a game for the iPhone for quite some time now and I have actually written parts of a game engine for the iPhone already. For some reason I just haven't been able to find the time to create an actual game. A lot of that probably has to do with the scope. I need to start with a very small project.
So, I have come up with an idea for a simple game that could still be entertaining. It's basically like the game Buggy Boy, but with a straight road. If I get that far, I can consider throwing some turns and curves in there as well, but let's not get ahead of ourselves here!
Here's a mockup picture I created in about 3 minutes:

The objective is simple. Avoid obstacles like other cars and the big grey thing (which is supposed to be a rock) and pickup flags for points. As you advance through the game, there will be more obstacles and the car will go faster. The objective is to get the highest score possible. An online high score list could possibly add motivation, but that is not crucial for the initial implementation.
Now that I'm blogging about it, it will haunt me for years if I don't finish it, because Google will cache this post for me for a long time. That should motivate me to keep going even when my dayjob makes me tired of coding, if ever so briefly.
Let's get this thing on the road! Pun intended.
Hello, my name is Martin Johannesson and this is my home on the web. I live in Stockholm, Sweden, where I work as a software engineer at a software company.
Ever since I was a kid and discovered the art of programming on my
C64,
I've been tinkering with my own little software projects and experiments.
This site is one such experiment.
more...