Mayfly Studio

Nov 03

While I think of what to do with A. CYBORG, time to switch gears. I had a brill idea for a graphics trick to do with my old landscape engine thingie and have been working on it fairly obsessively this weekend. This is only a proof of concept, but I can’t get over how well it came out.
The executive summary: notice the nice, soft lighting on this chunk of land? How it’s darker in valleys, a little dark around the edges of the mountains, and so forth? And that, in turn, makes it look like much more of a real object than a computer-generated one? That’s called ambient occlusion, my friends. A point at the bottom of a valley is only going to see a small chunk of the sky, and will therefore be darker than a point at the top of a hill which has a full view of the sky. And that’s what’s going on here.
To implement this, I added a step to landscape generation. For each point of landscape geometry, we plant a camera at that location looking directly up and with a wide field of view, and render the environment colored solid black against a solid white background. That gives us an occlusion map at each point, where the white pixels indicate how much of the sky is visible and in what directions. In order to test out how this looks, I am sampling the occlusion map down to a single pixel, whose level of brightness indicates how much sky is visible overall; that gives us the ambient occlusion level at each point, and thus the nice results above. (The old version of Air manually calculated occlusion by raytracing across the terrain in a couple of cardinal directions. It sort of worked, but wouldn’t catch obstructions that weren’t located along a main axis and so you’d get noticeable artifacts. By contrast this technique could handle anything — spires, walls, even bridges or other obstructing objects floating in the air.)
However, remember that we actually have a relatively detailed occlusion map available, not just one pixel. If, when we render, we also draw a picture of the sky (including the sun, clouds, sky color blend, and anything else going on up there) from a camera sitting on the ground and with the same wide field of view, multiply the occlusion map at each point by that sky map, and filter that down to a single pixel per point… suddenly we know the full illumination of each point on the map. Realtime landscape shadows fall out of that literally for free, as would cloud shadows, changing environmental lighting, and a whole lot of other things.
Now, in order to really see all this working, I’d need to make it so the vertex shader can examine the whole occlusion map for each point — not just one pixel — and occlude the sky map with it. The latest bleeding-edge shader models have a facility for launching subsidiary renders while executing a shader, but I doubt my computer has that support or that it would be efficient enough to use so intensively anyway. I think the vertex shader is just going to have to do a long list of unrolled multiplications of the two maps. With the 8x8 resolution that I’m currently using, that’s 64 multiplies and adds. Feels kind of excessive to me, but by today’s standards that’s not really a big deal. And since it’s in the vertex shader, it just runs once per visible point in the scene instead of once per pixel as a pixel shader-based system would do.
The other other tweak that occurred to me is that I could render the original occlusion map with the actual color values of the landscape. Filtering that down to a single point would tell me the color of light reflected from the surrounding obstructions, and could thus be used for more accurate ambient lighting. I’m not sure how noticeable that would actually be, but it wouldn’t be hard to experiment with and find out.

While I think of what to do with A. CYBORG, time to switch gears. I had a brill idea for a graphics trick to do with my old landscape engine thingie and have been working on it fairly obsessively this weekend. This is only a proof of concept, but I can’t get over how well it came out.

The executive summary: notice the nice, soft lighting on this chunk of land? How it’s darker in valleys, a little dark around the edges of the mountains, and so forth? And that, in turn, makes it look like much more of a real object than a computer-generated one? That’s called ambient occlusion, my friends. A point at the bottom of a valley is only going to see a small chunk of the sky, and will therefore be darker than a point at the top of a hill which has a full view of the sky. And that’s what’s going on here.

To implement this, I added a step to landscape generation. For each point of landscape geometry, we plant a camera at that location looking directly up and with a wide field of view, and render the environment colored solid black against a solid white background. That gives us an occlusion map at each point, where the white pixels indicate how much of the sky is visible and in what directions. In order to test out how this looks, I am sampling the occlusion map down to a single pixel, whose level of brightness indicates how much sky is visible overall; that gives us the ambient occlusion level at each point, and thus the nice results above. (The old version of Air manually calculated occlusion by raytracing across the terrain in a couple of cardinal directions. It sort of worked, but wouldn’t catch obstructions that weren’t located along a main axis and so you’d get noticeable artifacts. By contrast this technique could handle anything — spires, walls, even bridges or other obstructing objects floating in the air.)

However, remember that we actually have a relatively detailed occlusion map available, not just one pixel. If, when we render, we also draw a picture of the sky (including the sun, clouds, sky color blend, and anything else going on up there) from a camera sitting on the ground and with the same wide field of view, multiply the occlusion map at each point by that sky map, and filter that down to a single pixel per point… suddenly we know the full illumination of each point on the map. Realtime landscape shadows fall out of that literally for free, as would cloud shadows, changing environmental lighting, and a whole lot of other things.

Now, in order to really see all this working, I’d need to make it so the vertex shader can examine the whole occlusion map for each point — not just one pixel — and occlude the sky map with it. The latest bleeding-edge shader models have a facility for launching subsidiary renders while executing a shader, but I doubt my computer has that support or that it would be efficient enough to use so intensively anyway. I think the vertex shader is just going to have to do a long list of unrolled multiplications of the two maps. With the 8x8 resolution that I’m currently using, that’s 64 multiplies and adds. Feels kind of excessive to me, but by today’s standards that’s not really a big deal. And since it’s in the vertex shader, it just runs once per visible point in the scene instead of once per pixel as a pixel shader-based system would do.

The other other tweak that occurred to me is that I could render the original occlusion map with the actual color values of the landscape. Filtering that down to a single point would tell me the color of light reflected from the surrounding obstructions, and could thus be used for more accurate ambient lighting. I’m not sure how noticeable that would actually be, but it wouldn’t be hard to experiment with and find out.

Nov 02

Lodestar: Don't Write a Game Engine -

lodestargame:

When I first started writing Lodestar, I had no idea what I was doing. I read everything related to first-time game creation that I could get my hands on. One of the recurring themes that was thrown at me was: if you want to make a game, don’t write a game engine.

When I read, “Don’t make a game…

It really depends on your goal. For the stuff I’m working on here at Mayfly Studio, equal with my goal of “make some original games” (something which often seems as far away as the day I started) is the goal of staying current with tech I’m not using at my day job. While my success rate at getting titles out the door is dubious, I am at least keeping my skills broader than they would be otherwise and having a good time doing it. So I’ll count that as a win.

That being said, if I was making these games to pay the rent as opposed to just as a hobby… yeah, it would be wise to ditch the custom engine code and go with a mature third-party engine. Reinventing the wheel is fun, but it’s not a productive use of one’s time.

Oct 21

At this point, I feel as if I have the technical and artistic questions behind A. CYBORG sorted.
I can create a sprite-based ground environment with arbitrary layout, and generate it on its own thread so there’s no hitching waiting for tiles to be created.
Environments, including ground and skyboxes, can be set up easily and I can transition between them during the game.
Obstacles can be generated which the player must avoid.
Enemies can spawn on schedule, fire homing missiles at the player, and get shot down. They can be set up with an arbitrary flight plan that is also relatively easy to make.
The player’s avatar can steer around the screen, use homing missiles and hitscan bullets, change speed, and detect collisions with enemy missiles or obstacles.
Artistically, I’ve established that I can draw the needed poses for the main character.
And, I’ve established that a “real-world” military aircraft looks just fine as an enemy, as seen above.
There are various other technical things I’d like to do, but these were the big open questions. At this point, I really need to nail down the design of the game. It’s wobbled around a bit — originally it was a much more wordy tale of our doughty heroine confronting both her loopy, troublesome creator Dr. Grand-Mal and a suspiciously nonspecific alien invasion, then I sort of pared it down to a virtually story-free After Burner clone since it felt like creating all those story sequences would get in the way of playing a game that’s maybe ten or twenty minutes long at the absolute most, then I got all like “meh, I dunno” which is where I stand now.
I would like to do something with a bit of character and dialog, especially since that’s the kind of game I like the most and Neon Galaxy had none of that. Deep down though this is just a very simple arcade game and I don’t know if that’s plausible without totally overwhelming the game itself.
There are some interesting things I could do with the engine. The obstacle system could be used to make a hand-designed stage for the player to dodge through or pretty much any kind of crazy obstacle course a la Sega’s Galaxy Force. And there’s nothing keeping enemies in the air, either — a trivial “flight plan” could place installations on the ground, and setting up multi-part boss enemies wouldn’t be all that tough either. I can picture a 3-D Super Scaler take on 1943, say, attacking aircraft and then descending to the surface to take on warships with lots of gun turrets and whatnot.
And then of course there’s crossing these with the concept of a world map and multiple environments, which the whole engine is based around. There could be a branching tree of stages like Outrun, or it could be linear and more story-focused, or even have a map of stages that you could freely move around.
Too many choices! Like I said, I dunno. Before I do any more work with this concept I’m going to have to really sit back and nail one down.

At this point, I feel as if I have the technical and artistic questions behind A. CYBORG sorted.

There are various other technical things I’d like to do, but these were the big open questions. At this point, I really need to nail down the design of the game. It’s wobbled around a bit — originally it was a much more wordy tale of our doughty heroine confronting both her loopy, troublesome creator Dr. Grand-Mal and a suspiciously nonspecific alien invasion, then I sort of pared it down to a virtually story-free After Burner clone since it felt like creating all those story sequences would get in the way of playing a game that’s maybe ten or twenty minutes long at the absolute most, then I got all like “meh, I dunno” which is where I stand now.

I would like to do something with a bit of character and dialog, especially since that’s the kind of game I like the most and Neon Galaxy had none of that. Deep down though this is just a very simple arcade game and I don’t know if that’s plausible without totally overwhelming the game itself.

There are some interesting things I could do with the engine. The obstacle system could be used to make a hand-designed stage for the player to dodge through or pretty much any kind of crazy obstacle course a la Sega’s Galaxy Force. And there’s nothing keeping enemies in the air, either — a trivial “flight plan” could place installations on the ground, and setting up multi-part boss enemies wouldn’t be all that tough either. I can picture a 3-D Super Scaler take on 1943, say, attacking aircraft and then descending to the surface to take on warships with lots of gun turrets and whatnot.

And then of course there’s crossing these with the concept of a world map and multiple environments, which the whole engine is based around. There could be a branching tree of stages like Outrun, or it could be linear and more story-focused, or even have a map of stages that you could freely move around.

Too many choices! Like I said, I dunno. Before I do any more work with this concept I’m going to have to really sit back and nail one down.

Oct 14

New smoke trail particle behavior in A. CYBORG. I think I’ll keep it.

New smoke trail particle behavior in A. CYBORG. I think I’ll keep it.

Oct 13

I’ve checked in the new enemy management code and am pretty happy with it. I can come up with arbitrary enemy movements, spawn them whenever I want, and even have them fire missiles when ordered to by the flight plan. The old code managing enemies in waves and trying to spawn different types is gone and good riddance to it.
It might actually be worth breaking Pixen out again now to draw some better enemies and fix up the kinda hideous cloud sprite I use everywhere.

I’ve checked in the new enemy management code and am pretty happy with it. I can come up with arbitrary enemy movements, spawn them whenever I want, and even have them fire missiles when ordered to by the flight plan. The old code managing enemies in waves and trying to spawn different types is gone and good riddance to it.

It might actually be worth breaking Pixen out again now to draw some better enemies and fix up the kinda hideous cloud sprite I use everywhere.

Oct 12

No Image Saturday

Tch, not gonna have anything flashy worth posting for Screenshot Saturday this week. I’m finally buckling down and sorting out enemy behavior in A. CYBORG, and pretty much throwing out all the stuff I’d implemented up until now with “wave” objects that controlled spawning, a variety of C++ classes defining different behaviors, and so forth. Instead I’m following something like this plan:

  1. Enemy behavior is governed by a few set details, most importantly a constant cFlightPlan object referenced from the level data. Give it how long it’s been since the enemy was spawned, the flight plan tells you where it should be. Yes, this means no legit physical motion at all for these guys, and frankly I’m okay with it. This is a simple arcade shootemup, not a sophisticated physics simulation. I’m not going to try and overimplement these things on the off chance that they’ll be reused for something crazy sophisticated someday, because if they are I’m doing it wrong.
  2. The level you happen to be on has a list of all the enemies in the level and the distance at which they spawn.
  3. A specialized cEnemySpawner generates these guys as the player reaches the appropriate distance. I’ve ended up using this pattern (of having a spawner class for various game objects) several times; obstacles are generated in a similar fashion, and the landscape system is metaphorically the same kind of thing as well.

I have to decide what’ll govern enemies’ decision to fire at the player, but it’s quite possible that can just go in the cFlightPlan as well. Again, there’s nothing sophisticated about these guys; they just need a simple scripted motion and that’s it. There are going to be a few genuinely sophisticated enemies — bosses, if nothing else — but those guys are going to have unique, hand-crafted behavior so I’m okay with giving them unique, hand-crafted code as well.

Oct 06

I kind of wish that Screenshot Saturday was Screenshot Sunday, since I usually don’t have anything that isn’t totally programmer art hackage by the end of Saturday. But anyway, I’ve implemented a fairly robust obstacle system in A. CYBORG. These will be used for bonus stages, not dissimilar to how it works in After Burner, although as per the world map I posted a while back you’ll only traverse one obstacle stage (out of four possible) in any single playthrough.
Oh, and, uh… I finally got around to updating the game window’s title bar. Yeah.

I kind of wish that Screenshot Saturday was Screenshot Sunday, since I usually don’t have anything that isn’t totally programmer art hackage by the end of Saturday. But anyway, I’ve implemented a fairly robust obstacle system in A. CYBORG. These will be used for bonus stages, not dissimilar to how it works in After Burner, although as per the world map I posted a while back you’ll only traverse one obstacle stage (out of four possible) in any single playthrough.

Oh, and, uh… I finally got around to updating the game window’s title bar. Yeah.

Sep 30

[video]

Sep 23

That should do for now.

That should do for now.

Sep 16

LET’S FLYING

LET’S FLYING