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
[Vertical Space Shooter] Parallax stars?Posted: Mon Sep 12, 2005 12:59 pm
My game has a simple scrolling background:
I've been trying to work out a way to make the game look less flat, and the best way in a game like this is a parallax starfield. In the past, I've been doing all rendering in software so it's nice and easy to do, but have no idea how to do it on a Game Gear.
I use very few colours (it's a conversion of a BBC Micro game), so maybe set a vertical "stripe" of 8 colours on the tile I want the stars to be on in ascending order, and by modifying the palette? Or by scrolling the tile itself round and round? The stars would look a bit naff (it'd be very obvious where the 8x8 tile looped)... Is there a commercial game that does this that I could take a look at?
||Posted: Mon Sep 12, 2005 2:09 pm|
GG Aleste II / Power Strike II on GameGear does parallax scrolling in the first stage (or was it the first one?).
It shouldn't be hard/cpu intesive to do if you don't need to scroll sideways, you should probably use more then 1 tile for it though.
||Posted: Mon Sep 12, 2005 6:46 pm|
There are a number of ways to do it:
- Filling all the 'blank spaces' with a single tile and updating that tile to make it appear that it's scrolling at another speed is one option. The obvious problem there is that the "edge" tiles where there is graphics data that represents the 'foreground' will have to be entirely opaque because you can't update enough tiles to do the starfield effect on all the non-blank tiles that should have some 'background' peeking through. So you'll have to either have black areas where there should be stars, or make all your foreground take up the entire 8x8 tile. Or perhaps just update a few "corner" tiles to give it a rounded effect, but be aware you can't use tile flipping then because the stars will go in the wrong direction.
Of course you're correct that it won't look like a natural starfield with an 8x8 looping pattern.
- You can do the same as above with a repeating 16x16 starfield pattern (2x2 tiles or 4 titles total), but you still have the same problem as above.
- You can use sprites, even multiplex a single sprite across the screen with h-interrupts (see my other post about that) but that may not be a good choice because you need to have sprite-over-playfield priority for those bases pictured in the screen, and the stars would also appear in front of the the bases. This would be better if you wanted to do a two layer starfield with a distant background that moves slowly and faster moving stars in front.
You could be very clever and simply turn off the sprite on a scanline where it would be covered up by a background tile. That would be difficult to do, you'll have to keep track of the opaque pixels in each title, and do a lookup of which tile is used on a given pixel for each star, but it's probably the only way I can think of to get a good parallex starfield going behind a foreground. Note that lower numbered sprites appear above higher numbered sprites, so you can multiplex sprite 63 (or others in that high range) to make sure stars don't appear in front of ships. Higher numbered sprites are also the ones that disappear when there are too many sprites on a scanline so there may be some star dropout.
- You can do the palette thing you mentioned - If you're only using the first 8 colors you can use the other 8 to fill every 'blank' pixel where the startfield would show. Then you could turn stars on and off for each scanline by setting some colors to white (or your star color, grey or blue I guess) and others to black. You don't need to update all 8 colors per scanline, usually you'll just be turning on color 'on', one color 'off' or both.
This is still a bit ugly looking as 8 pixels across does not define a good starfield as it would look too regular, but at least you can have a non repeating pattern veritically along the screen.
- You can scroll in 8 pixel increments, that is, not use hardware scrolling at all but just push all the "foreground" tiles down one row of tiles at each scroll update and draw in 'background' tiles where the foreground tiles would appear. The advantage is that you could have a background pattern of any complexity. The disadvantage is the background layer can't be moved at all, the foreground moves 8 pixels at a time (either too fast or too chunky) and you still have the problem with transparency around the edges. This is a bad choice, but I've included it for completeness.
||Posted: Tue Sep 13, 2005 1:12 am|
|Heliophobe mentioned one of the ways that GG Aleste II does it: As "star" sprites are scrolled down the screen, it checks the background tile (in VRAM) overlapping that sprite and turns off the sprite if the background isn't an empty tile.|
||Posted: Mon Sep 19, 2005 1:50 pm|
Is it fast to read from the VDP? I'm already close to hitting the point where writing any more to it is going to start screwing stuff up (lots of big 16x16 sprites and my probably-not-very-efficient code). I've already had to rewrite the routines to work out what has been hit on the ground and update the tiles 3 times for speed reasons... ;-)
I'd be using single pixel stars (most likely, anyway), so a "get_pixel" routine would be required. I have my tilemap backed up in RAM (faster for bullet collisions, I had assumed), but I'm not sure how to check this quickly. I shall have to experiment!
Lastly, my sound effects system is very simple - each sound is stored as a list of period/volumes/times and period/volume increments (so that for each tick of the time the period and volume is altered) and has a priority attached to it. Up to 8 sounds can be played at once, and it detects the one that is the highest priority to play on the PSG. This sounds OK-ish, but I'm wondering if there is a better way to do it - possibly by selecting the loudest current sound effect?
My tile set looks like this, by the way:
...so there is quite a bit of blackness that extends past the edges of the border tiles, and a star that disappears when it hits those would look a bit odd.
||Posted: Mon Sep 19, 2005 5:50 pm|
Reading from the VDP isn't toooo slow, but if you already have a shadow of the tile map in ram then it's best to use that. If you didn't have a shadow to read from and the tile map wasn't just a direct dump from rom (for instance, if you are using some sort of compression, repeated patterns, or grouping of tiles into 2x2 or 4x4 blocks) it might be easier and faster just to pull it out of vram than to try to figure out what would be on the screen at that point.
Whether, as a practice, it is better to use a ram copy of the tile map or to read it from vram depends on how badly you need the memory and how often you are needing to do collision checks (or similar operatons). The more often you do it, the more cycles you save pulling it out of ram, and there would be a break even point where if there were few enough accesses it would be slower to maintain a ram copy. In most cases I'd say it's not worth it, but for the star trick, or if your game were bullet-crazy, it would be.
You may want to create a 'key map' for each tile for which pixels are transparent, rather than determining the color of each pixel and using that as an indication of transparency, as you'll have nasty bitplanes to deal with. A get_pixel (or get_pixel_transparency) type routine might go like this:
- Figure out which tile the pixel is in, taking scroll value into account
- Get the tile number (either from vram or from your copy)
- Find that tile's transparency "key" (either a bit array or byte array)
- Look up the entry in the key for the particular pixel you want to test.
- If that entry is 1 (indicating opaque), return 1. If it's 0 (indicating transparent), return 0.
You'll also have to take tile flipping into account if you use it.
When I refer to a 'key' I mean a 8x8 "table" where each entry in the table indicates whether that pixel should be opaque. The easy, fast, but wasteful way is to use one byte per pixel -- so if you want to test for pixel (3, 7) you multiply 7 times 8 (8 pixels per line), add three, add that offset to the beginning of the key address, and you have your indicator. The problem there, obviously, is that it's 64 bytes per tile - a waste of ROM, but it's fast.
The more compact way that is also slower and harder to write is to pack them in as bits, as if you were storing a monochrome tile. In the above case, you'd add "7" to the key address, and look at bit 3, and return 1 if it's set and 0 if it's not. That uses only 8 bytes a tile.
To justify the use of a whole byte per pixel, though, you could have more than one result. There could be a 100% transparent value (0), a 100% opaque value (1), and then one or more 'tint' values that indicate the star should be a different color for that pixel. You could, for example have blue "glass" areas that tint the starts behind it blue. In doing so you fake not only parallex scrolling, but translucency.
||Posted: Mon Sep 19, 2005 6:21 pm|
To give a better answer to that, assume you've already got the vram address to read in HL, I'm thinking it's about 41 cycles to read from the VDP:
ld a,l ;4
out ($bf),a ; +11 = 15
ld a,h ; +4 = 19
out ($bf),a ;+11 = 30
in a,($be) ; +11 = 41
For reading from RAM, it's more like 7 --- but to be fair you'd need to spare another 18 cycles to add the RAM offset which wouldn't necessary for the VDP read. You might be able to slip that in with another step, though, so it's hard to say. But there is an overhead for keeping the ram in sync with video ram so you'd need to do a lot of lookups for that to be a good idea.
RE: the sound effects, I've used a priority system in the past, one thing you could do is have the priority change over time so a high priority sound can interrupt another high priority sound if it's fading out. If you have sfx that waver in volume then just using the volume as a determinant might have strange results.
||Posted: Tue Sep 20, 2005 10:19 am|
I tried with a volume-based sound effect code and it sounds a lot cleaner than the priority-based code - I added the change with a couple of .ifdef blocks so it's easy to revert if need be.
A slightly more pressing issue at the moment is the lack of space - the game currently leaves about 3KB free on a 32KB ROM image, and that's still incomplete and has no music. I tried to work out how to set it up for a 64KB ROM image but didn't get to far - the best I got was a messed up title screen (but the code ran fun, so I'm assuming I did something silly with the .org - the title screen code only uses relative jumps). Everything else complains and refuses to compile.
With regards to the stars - thanks for all these ideas. :-)
||Posted: Tue Sep 20, 2005 7:58 pm|
|You can go up to 48kb without having to deal with bankswitching. But you will want to set the banking registers to the appropriate pages (0 in $fffd, 1 in $fffe, 2 in $ffff) in your startup code for the benefit of people using dev carts.|
||Posted: Wed Sep 21, 2005 9:49 am|
It was more a problem of getting WLA-DX to compile without errors - if I set it to use a single ROM bank, size $10000, and add a .org $8000 at the end of the source file before I .include the large external data (and add $8000 to all memory addresses which access that data) it works (and on hardware), but is very inelegant.
I've added some simple stars (just checking to see if the tile is 0, if so draw - so it's far from pixel-perfect!), but it looks like I need to reshuffle some code again to move it out of the vblank delay:
||Posted: Wed Sep 21, 2005 11:52 am|
|I've never had problems with banking in WLA DX. I can post some sample code it you like - I just realised I haven't released the source of any project that uses banking very much.|
||Posted: Wed Sep 21, 2005 12:13 pm|
|It's probably a case of me misunderstanding the documentation, so if you had some sample code for setting up banking I'd be extremely grateful!|
||Posted: Wed Sep 21, 2005 12:44 pm|
Here's some bits of Bock's Birthday 2004:
Defining the banking setup. This arrangement allows larger chunks in the first 32KB:
slot 0 $0000
slot 1 $7ff0
slot 2 $8000
Initialising banking registers:
Loading screen data from upper banks:
.section "More GFX" superfree
.incbin "BB2K4 (tiles).pscompr"
.incbin "BB2K4 (tile numbers).pscompr"
.include "BB2K4 (palette).inc"
WLA DX will decide which bank to put the data in; the :Label syntax gets the bank number which is used for paging, and the label addresses will then be valid since they will be computed for the data to be in the range $8000-$bfff.
This code will not compile as-is, the middle section needs to be in a valid section or at least after a .org.
||Posted: Thu Sep 22, 2005 9:00 am|
Thanks a lot for that Maxim, worked a treat.
I have finished the stars (only took a couple of evenings after work amongst other small fixes/tweaks) and using the method Heliophobe described in depth. I thought it would be too slow or the flickering of the 8-sprite-per-scanline limit would be too obvious, but it looks pretty good. :-)
||Posted: Wed Nov 09, 2005 6:47 pm|
|Benryves, that looks very promising. Can't wait for any news and a playable demo : )|
||Posted: Thu Nov 10, 2005 10:38 am|
I'm sorry to disappoint, in that case - I'm no longer working on this project.
Here's a video clip of the "latest" version. (I couldn't get Emukon to record video without it crashing, so had to resort to recording my Game Gear the old fashioned way).
I'm abandoning it for a number of reasons; the game is far too difficult, for one thing (I'm very bad at any computer game, in any case, but this is utterly unplayable). The game would be very unpolished (lack of background on score rendering it unreadable, no music) and all in all a bit rubbish. Beyond that, it's a massive amount of very dull work to get it near finished (all the more interesting code has been written).
If anything, I still have the source.
||Posted: Thu Nov 10, 2005 11:02 am|
|It looks pretty near completion to me... is the difficulty because you didn't closely port the original game logic, because of the smaller screen or just because you're no good at it?|
||Posted: Thu Nov 10, 2005 11:10 am|
Quite possibly a combination of all three. I tried as best I could with porting the game logic - as for the screen size, the background is the same resolution as the original (width-wise) but the sprites are double the size as the original (I couldn't get 8x8 sprites to look any good).
|Posted: Sun Nov 27, 2005 11:44 am|
I (still) got some weird problems logging in, so I'll do guest posts for now...
Benryves, the video looked fantastic! Please continue your work on this project! I'd love to see at least a demo + source release of what you already acchieved. Maybe others could support you on certain aspects that way ?
||Posted: Sun Nov 27, 2005 10:28 pm|
Yes I agree with Chris
I believe that input from other users who have played the game would be very beneficial and if everyone works as a TEAM, Together Everyone Achieves More!
||Posted: Wed Jan 11, 2006 6:56 pm|
I guess I should post this here: here's the ROM as it currently stands. http://benryves.com/bin/ftrack.zip
Source will follow as/when I have the time to tidy/zip it up!
||Posted: Wed Jan 11, 2006 11:17 pm|
|Wow! It's Star Force on the GG!|
||Posted: Wed Jan 18, 2006 10:30 am|
Wooooot! Thank you!