Sega Master System / Mark III / Game Gear|
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew
Flight of Pigarus - development Q & APosted: Tue Dec 04, 2018 6:24 pm
A couple of questions regarding the development of the game came up in the release thread, which, of course, I'm more than willing to answer. If you have any further questions, don't hesitate to ask them here, and I'll answer them as well as I can.
But now, let's delve in. Prepare for a lengthy post.
Yes, I did. Graphics were what drew me into SMS development in the first place. I just learned how to code when the guy I had originally planned to team up with suddenly backed out.
Other than (I believe) most developers I actually do the complete graphics for my games first, before I even write a line of code. This sets the mood of the game early. Also, I find it helpful for planning the way the VRAM is going to be used. Another benefit is that it keeps the motivation to finish the project high. You don't want to abandon it if you have already put so much effort into the visuals.
I like interconnected palettes where the colour ramps share single colours instead of just coexisting. It makes the game world feel much more coherent.
Note that in Pigarus the backgrounds have much less contrast than the sprites, as they use more subdued pastel colours, no black and only very little white. That's because human perception expects this from things that are farther away. The sprites on the other hand use bolder, more saturated colours as well as high contrasts along with pure black and white. This makes the sprites really stand out. They never merge into the background and always look like they are on a level closer to the player's viewpoint. The bosses, why technically made of background tiles, also use this kind of bright colours to make it believable that they are indeed on the same level as the sprites.
There's also a little bit of colour-coding going on. Roughly speaking, things that are blue-ish, green, or grey are deadly, while stuff that's pink-ish or yellow is harmless and potentially beneficial. In a busy game like this, you can't always concentrate on the whole screen at once, so things must still stay easily readable even if you see them only in peripheral vision.
One exception is obviously the first boss, but since the boss fight situation is much more focused than the bulk of the game, I don't think readability suffers in that particular case.
For the music I used Sneventracker instead of Mod2PSG2 for the first time. While Sneventracker's vgm export leaves much to be desired, and Mod2PSG2 has much nicer vibrato effects for flute- or strings-like instruments, Sneventracker's instrument editor is fun to play with. It enabled me to create some very satisfying drum sounds, and the rougher sounding lead voices actually went very well with the circus-y feel I was going for.
Too many games to list. Pigarus himself is loosely based on the character Michael from the Parodius games. The rest of the design was inspired by such different games as TwinBee and Story of Thor. I also played through the GBC Zeldas at the time when I was working on the graphics, and that's why there are bats and the green blob enemies.
Gameplay-wise, every Caravan shmup builds on the foundation laid by Hudson's Super Star Soldier, which established most of the staples of the sub-genre like bonus icons, the infamous ring enemy, and so on. My main sources of inspiration were two other homebrew Caravan STGs, though, namely Super Star Shooter and Blade Buster. In fact, both of my bosses started out as spoofs of the bosses from Super Star Shooter, but then spiraled into being very much their own thing. I think they are all the better for it.
I don't think I understand what you mean by that.
RAM was never a problem, and since I considered how I was going to use VRAM beforehand, there weren't any big issues there either.
The sprite limits were a different beast, though. It's absolutely essential that the important sprites (as in things that can kill you) are always drawn, so I carefully constructed my enemy waves so that nothing important ever disappears. The player bullets and the explosions are much less important, so I make sure that those are the last sprites that are drawn. The drawing order from top to bottom is as follows: Pigarus, enemy bullets, enemy missiles, enemies, player bullets, explosions. Additionally, within these chunks there's programmed flicker so every sprite shows at least every other frame.
Other than that I just carefully constructed my game around the limits, so they don't show too often.
Much more simple. In a shoot'em up you need very responsive and super-accurate controls, so inertia is a total no-go. It's really as simple as just moving the player at a constand speed in the direction pressed. The diagonals, however, are normalized, as that makes movement feel more natural.
A bit of both. The movement is mostly scripted. An enemy path basically consists of a list of movement vectors (speed/direction) followed by a timer value that tells the game how often to repeat the move. There are 3 points when something special is triggered: When the end of the path is reached, when the enemy is destroyed, and when an 'action'-bit is set in the timer value. These special things are coded for each enemy type individually.
I had to cut two enemy waves which had too many horizontally aligned sprites, so they flickered excessively.
Another thing I would have liked to have is some kind of speed indicator for the player, which I couldn't do because I ran out of VRAM for any more sprites. You can still read the speed by watching how fast Pigarus flaps his wings, but it's very subtle.
But apart from that, I was able to implement everything that I wanted, and the finished game very closely resembles my initial vision for it.
If I started it again, I would maybe implement differently coloured variants of the same enemies (like the green and white flowers) by actually changing the palette instead of storing both variants into VRAM, and use the freed space for another enemy type or the aforementioned speed indicator.
I just tried to match the 'classic' Sega material with the quirky clip art as closely as possible. I guess I could post some .IDML templates, but they would be quite useless, because I couldn't include the fonts used for legal reasons.
I refresh the tilemap every 16 frames by adding a new double row at the top of the screen. I wrote some custom tools that sort the map data in double row chunks going from bottom to top. These chunks's data is then split into three parts that are compressed and stored seperately: the tile numbers, the tile attributes, and the positions and types of the destructible parts. While the former two work with standard 8x8 pixel tiles, the latter one actually stores 2x2 meta tiles. This lets me have wonderfully detailed backgrounds and easy handling of the destructibles.
During runtime, this data is combined in a buffer and finally sent to the tilemap. By stretching the decoding over several frames I can keep the strain on the cpu for each individual frame low.
I split the collision detection. On even frames I handle the collision of player bullets and enemies, on odd frames, all the rest of the collisions is checked.
The player/enemies, player/enemy bullets, player/bonus jewels, and player/powerup collisions are quickly checked, because there's only one object they have to check with (the player).
The player bullets/background collisions check a single point in the middle of the player bullet against a collision map that gets refreshed every time a new row of destructibles is decoded. That way, I don't have to read from VRAM.
Now, the interesting part is the player bullet/enemies collisions, as there are quite a lot of those. I used a modified approach to what kusfo describes in this thread. The screen is divided into 12 horizontal slices of 16 pixels height. When updating the player bullets, each of them cannot be in more than two of these slices. For each slice it's noted which bullets are in it. An enemy then only checks collision against those bullets that are in the same slice he's in. This method creates a bit of overhead, but the actual collision detection is very fast.
That's the reason, by the way, why the player bullets are not normalized, as that would make it totally unpredictable how many bullets can be in a slice. By making the diagonal bullets move vertically with the same speed as the straight ones, I can make sure that there are never more than 8 bullets in a slice, usually it's less than 4.
That's super simple, actually. I just store the controller input in SRAM every frame. Since I know that a full game of 5 minutes has 15,000 frames, I know that fits nicely into the 16 K SRAM bank. At the end of the game, if there's a new highscore, the control data is compressed and stored in the other SRAM bank. For the replay, the saved data is decoded again, and the control data is read instead of written.
I originally coded this just to have a tool to record an attract mode. When I had it in place I realized that I could use the technique for a full replay.
||Posted: Tue Dec 04, 2018 7:56 pm|
I often draw some graphics up front, typically because I want to check something will work within the constraints of the system, and I will need to write code based on certain assumptions about the nature of the gameplay which are related to the size or layout of things.
I usually find that I need to decide on the structure of the code around things like interrupt handling and main loops. There's a few different approaches, and it's interesting to hear how people manage it - in your case you have two modes (gameplay and title screen), do they share code or do you dispatch between handlers based on the state? The stuff about collision detection shouting across frames is also part of the code structure for me.
Did you make use of the profiling tools in Emulicious? I've never managed it but it seems like it would be super useful to measure and graph your time in different phases of the frame time.
||Posted: Wed Dec 05, 2018 4:58 pm|
In that case, there are actually three parts to the game: title screen, game proper, and results screen. All of them are pretty much self-contained and independent from each other.
Within the game proper, the main loop largely consists of calls to the various handlers that update the player, the bullets, the enemies, etc. and checks for game-ending conditions (player hitpoints dropping to zero, time running out). The various handlers are also modular, so I could, if I wanted, switch around the two bosses by simply changing the order of the level parts.
I used the profiling functions of Emulicious a lot. They helped me deciding on how to split the collision checks to even/odd frames. I also used them to determine how many objects my game can handle without slowdown.
||Posted: Thu Dec 06, 2018 9:38 am|
wonderful tool in good hands - if I can say :)