http://youtu.be/5kYjLdKqWHo
From the description:
Added a few more new features.
1. Radar indicator thingie. I've always wanted to give the player an idea of where objects and enemies are outside of the screen, within a certain range. This makes it easier to find and fight them.
2. Rotating objects. The enemy planes now orient themselves towards the player. This will be useful for other things like cannon turrets.
3. Changing levels. Hitting the start button switches to a different level, using different assets and code. You can tell by the changing tile layout and enemy placement. One map I attempted to do a "winter" style theme but totally failed and it looks pretty bad.
Before I was hardcoding sprites locations into the VDP but now it's much more flexible. There's a common set of tiles to load (player, weapons, effects, hud, etc.) and each level can choose to load their own stuff, like the background and foreground layers.
4. Player lives. Only shown briefly at the end. When the player dies, they restart the level one with less life. And the enemies that have been destroyed stay dead.
5. Enemy planes have their own sprite. Now I won't get questions anymore about why there are many copies of the player on screen
Enemy objects now have their own dedicated 16 colour palette. The current palette setup is PAL0 for the player and effects, PAL1 for enemy objects, PAL2 for the background layer and PAL3 for the foreground layer.
This part wouldn't fit in the Youtube description:
It took me a while to come up with a solution to do the radar and enemy plane rotations. I went with a look up table of precomputed values of angles in degrees. The table is four times the size of the screen area, but divided by 8 so that it maps to tile space. Only having angle values for 8x8 sections of the map is good enough for me as I don't need pixel perfect values. This gives me a map of 80 x 56 of 16 bit values for a total of 8k. It's a little big but it'll be used for a lot of things so I don't mind too much.
The angle look up table. Every value in the table contains the angle made from the origin to its position. Angles go from 0 to 90, but we're mapping it to 0 to 63 to only take up six bits in the 16 bit value, explained later.
Code: Select all
(0, 0)
--------------------------
| |
| |
| |
| |
------------------------- (79, 55)
This is a typical scene. When the enemy is off screen but within a certain range, we want to show a radar indicator thing.
(P) is the player, in the middle of the screen
(E) is the enemy object, outside of the screen but in range.
Code: Select all
range
--------------------------------------------------
| |
| |
| _______________________ |
| |screen | |
| | (P) | |
| | | |
| ----------------------- |
| (E) |
| |
--------------------------------------------------
When computing the angle between two objects, we first translate their positions so that the first object is at the origin. Then we divide their positions by 8, the tile size, so that their new tile-space positions map to the angle look up table.
Code: Select all
(0, 0)
(P)---------------------
| |
| |
| (E) | (50, 30)
| |
------------------------ (79, 55)
So the value at angle_table[50, 30] will be the actual angle between those two objects. Later I'll explain what I do with it.
The area around the player is logically divided into four quadrants, with the player position as the origin. Each quadrant is 80 x 56 in tile space (640x448 in pixel space) which maps to our angle look up table.
The angle look up table really only has values for one quadrant, quadrant 4. But we can derive correct values from it for the other quadrants. This saves us space as a trade off for a bit of computation.
Code: Select all
range
1 2
----------------------------------------------------
| | |
| | |
| ____________________ |
| | screen | | |
-----------------|--------(P)-------|---------------
| | | | |
| -------------------- |
| | (E) |
| | |
----------------------------------------------------
3 4
Once I've gotten the angle from the table, I use it to make other lookup into other tables. For example, for the radar pointer thing, I use the angle to get the x/y positions from a pre-computed position table. And for the enemy planes, I map the angle to a table of animation frames. Angles are mapped to 0-63 because then I can use bit shifts to map into other tables that are almost always power of two. So while I lose a bit of precision (256 degrees for a circle instead of 360), it makes things a bit easier to work with.
A related problem I was trying to figure out was how to quickly compute distance between two objets. Since we're only using 6 bits out the 16 for every value, there's quite a bit of room left so I thought I'd use the extra 10 bits to store distance as well. Bonus!