Back in January, while I was doing the internationalization code, I felt that all this endless detail work was killing my enthusiasm for the project. I needed a break.
I started writing a little mini-game just for fun. That lead to my problems with artwork in Part 48 and the sound support in Part 49. Reading about character animation made my head hurt, and I got discouraged again. I decided that this "mini-game" idea wasn't helping. In fact, it was just Advanced Procrastination. So I dropped it.
A few weeks ago, I decided to pull out the old code, do "just one more day" on it to finish off some kind of trivial game, and show it to you. I actually ended up working on it for a week or more, and then got distracted by this GUI work I'm doing with Shamus Young.
The GUI work still isn't finished, and neither is this game. However, I don't have anything else to show you this week, so I thought I'd write up what I've done so far. There will be a second part on it when I get it finished.
I was looking for the simplest game idea I could implement that would be any fun, and I remembered an indie game called Proun by Joost Van Dongen. His website has a video, but Figure 1 shows the heart of the game. There's a ball on a track. You follow a fixed path and try to avoid all the obstacles. Hitting things slows you down, and the goal is the quickest lap you can manage.
You have only the four cursor keys as controls. Up and down arrow control your speed. You normally play with the up arrow pressed the entire time! Left and right rotate the ball around the track. Rotation also slows you down, so after you've managed to not hit anything, you can further improve your time by rotating as little as possible. Add some nicely rendered graphics (with depth of field blur), some catchy music, and you have a game.
I emailed Joost and asked if I could imitate the game and he replied,
Just as long as you don't intend to extend it and release it commercially,
Hopefully this version isn't a problem. I've left out nearly all the nice features that Proun implements, so it's hardly an extension. Since it's all about avoiding obstacles, I decided to call my game "Don't Hit Me!"
Instead of a ball on a solid track, I went with my silly little flying saucer, and put it on a transparent noisy track. Instead of geometric shapes, I decided to use my nebula sky and some of the SeaOfMemes landscapes. I added the speed and rotation controls. This first bit was done back in January. I had a saucer flying along a track (Figure 2).
The only tricky part of this is figuring out the correct transform matrices. The eye hovers above and behind the saucer, and both are rotated around the track at the attachment point. The saucer (and hence the eye) have to follow the line of the track.
One thing I discovered right away is that spinning stars on a full screen game can actually make me dizzy. I'll be interested to see if any of you have the same reaction.
Next, we need some scenery to avoid hitting.
I was going to use my same old asteroid, created by generating a height map in six chunks (the faces of a cube distorted into a spherical shape), but decided that was boring. I wanted caves to fly though. With lava!
To build this, I have three levels at each point on the sphere. See Figure 3. The bottom level (red) is lava, at a constant radius. The outside of the asteroid is generated as usual, by adding Simplex noise to a radius (green).
The inside is generated by subtracting noise from a larger radius (blue). This means the inside surface actually cuts through both the outside and the lava levels. For the inside, I'm summing the absolute values of the Simplex noise at each octave. This produces a much spikier terrain. Descending from above, we get a "stalactite" look.
The only tricky bit here is when the inside and outside edges cross. I want there to be fissures in the asteroid shell. When I generate the triangle meshes, I omit the triangles which have inside heights greater than outside heights at all their vertexes. This leaves a hole in the terrain. I also set the inside and outside heights the same at these crossing points to create a clean edge. The result is Figures 4 and 5.
Unfortunately, the low resolution of my heightmap is really obvious here, and the edges of the fissures are crude. The simplest way to handle that would be a quad-tree on the sphere surface, which would use higher resolution for the areas with more detail. Since I'm just fooling around with this, I didn't bother.
I could just route the track in and out of caves, giving you stalactites to avoid, but that would be boring. I needed more variation, and after some thought decided a wrecked starship would be just the thing. It would be geometric in contrast to the rocky asteroid. My inspiration was the Discovery, from the movie 2001: A Space Odyssey (Figure 6.) It seemed easy to model.
As I mentioned back in Part 48, the only 3D modeling editor I've managed to do anything with is Google SketchUp, and I only did simple things with it. I much prefer to build my models in code with parameters I can tweak again and again until I think the proportions are OK. I just have no feel for that kind of work. Even when I'm sick of it and decide I can't do any better, I have no idea if it's any good.
For my ship, I started with three spline curves as shown in Figure 7. The top circle is the cross section of the shape. The other splines scale the top and bottom edges of the shape. I decided to do a 120 degree part and use it three times, to add some interest to it. The result is Figure 8:
Because of the way I build the shape, the mesh follows the curve of the splines (Figure 9). The easiest way to cut out windows would be to drop some of these mesh squares and put a lighted room behind them. But that would only get me weird curving windows.
Also, remember that the goal here is to create obstacles for the player to avoid. Adding windows along this straight hull wasn't going to do that. I needed to add more structural elements to this ship.
I decided to add a rotating habitat section. I could have done a large ring, but that would have required some kind of complicated struts attaching it to the center. It would also have been a very simple obstacle.
Instead, I added some towers attached to the core. Ever since I saw Shamus Young's Procedural City, I have wanted to put some lighted office buildings into a project. So why not stick them on a spaceship? How about a bunch of them, at various angles, giving me lots of obstacles and interesting views for the player? Figure 10 shows the result:
But this is supposed to be a wrecked ship. So I smash the windows, break the towers off, and cover everything with mold (space mold is the worst!) I can make the windows transparent here without any sorting. You only need sorting when you can see through two layers of transparency. In this case, you can't get inside the towers, so you can never view any other transparent stuff through the windows. Here's a closeup:
With the ship crashed into the asteroid, the scene now looks like Figure 12. Proper lighting would really improve this, but I'm not up to that yet in any of my graphics programming. Some day!
To finish this off, I will route the blue path through the wreckage and the caves, giving the player lots of obstacles to avoid. The biggest missing piece of code is collision detection. Since the whole game concept is avoiding obstacles, I need to do a detailed comparison of the saucer shape with the objects in the environment. It won't do to just bounce off a sphere around the saucer!
I also want a bit more scenery, but haven't decided on what. I'd like some animated objects to liven things up, and some more organic shapes. There needs to be a sound track as well, including a noise when you hit things. To finish it off, it needs a start sequence, a lap time display, a score board, and some UI for setting options.
I think I can finish this in another week, but I can't start that work until I finish more GUI for Shamus. I still have a lot to do on that. But there will be a playable version of this sometime soon.
By the way, Proun is a lot of fun, and is a "pay what you want" game. Give it a try!
blog comments powered by Disqus