stardust wrote:For software sprites, I want to know more, espencially in smooth movement and transparance. I don't know how to put an object (e.g. a normal character) on a text mode screen (40*25) with 300*200 location.
Hmm, i've two cups of tea in me today and this might end up as the first draft for an article on OSG
so i'll have a go. =-)
Right, for a starter it's far more often 160x200 positioning rather than 320x200 because the graphics and the software sprite will usually be running in multicolour. There's also a number of ways to do this, but i'll explain one of the most involved since the majority of the rest can be worked out from there.
Each soft sprite object needs a work space; for the sake of example we'll assume an 8 by 16 pixel ball which is two by two characters and that'll need a three by three character work space because the ball is going to have to smoothly travel between character cells. That space can be organised like this...
...and i'll explain why it's in columns rather than rows a bit later on. The object itself is stored in four possible states somewhere in memory (not in the character set) with each being offset by a pixel so they look like the column on the left in this diagram...
...whilst the column on the right is a series of masks for each pre-shift. The process of writing in a software sprite using the work area and mask might go like this:
1. Work out where the work area characters need to be plotted to the screen, these values will be the software sprite's X and Y position divided by 4 and 8 respectively (since it's multicolour, the pixels have a 2:1 aspect ratio). The nine characters already on the screen at that point are pushed off into a storage space because they'll be needed for a couple of things.
2. Draw in the nine character work space and then copy the definitions from the characters that were there previously (see, i said they'd be needed! =-) This makes the work area "invisible" because it now looks exactly
like the characters it overwrote.
3. Select which of the four blocks of pre-shifted sprite data (from the example above) is going to be used - again, the sprite's X position provides the value, it's the lowest two bits that were previously ignored when positioning the work area.
4. Work out the drawing height within the work area (the bottom 3 bits of the sprite Y since it was divided by 8 rather than 4).
5. Cut a "hole" in the work area character definitions at the selected height (done using the mask for the selected frame, the data is ANDed against what is already in the work area so the "hole" is the shape of the ball and the background surrounding that hole is left intact).
6. Draw in the object at the selected height (this time ORing the data in so that the background that survived the masking process is still unharmed).
When it comes to moving
the object there's a couple of extra steps:
7. Overwrite the work area with the characters that were in it's place previously.
8. Update the sprite's position, then jump back to step 1 to redraw it.
And that happens once a refresh (with all the work needing to be done out of the visible screen or to a second buffer to avoid it looking a mess) and for many games that'll mean 25 or 50 times a second. The reason for the work area being arranged into columns is simple, it means that the mask and definition can be written in with a simple loop rather than needing fiddly exceptions to skip between rows; if character A is at $2000 and character B at $2008 you can just keep drawing over the boundary if one is above the other, if A is at $2000 but the character below it is D at $2018, there'll need to be a "skip" checked for.
stardust wrote:I remmembering when I am young and program a game by BASIC for Plus/4, I want the main character to perform smooth move, but all the reference program I can find is move by characters.
Trying to handle software sprites from BASIC is highly problematic, moving in character steps is normally used because it's the fastest and least resource hungry solution. Even from machine code what i've described above is quite a hefty chunk of processing power to handle and many games pare down the process, either managing sprite positions to avoid the need for overwriting the background, keeping the overall sprite count down, going for character steps or variations on those themes.
There are techniques to speed things up such as unrolling all the loops (instead of having one LDA and STA in a loop, having loads of LDA and STA commands) but these solutions are memory hungry and therefore not always viable on the C16.
stardust wrote:For hardware smooth scrooling, what is the register address for Plus/4?
For horizontal scrolling it's $ff07 and vertical is handled by $ff06 but it's important to note that these are multi-purpose registers and only the lowest three bits (and the fourth governs if the borders are in smooth scroll mode or not) are used for smooth scrolling; writing the wrong value into these locations can "mangle" the output since $ff06 can do things like enable bitmap mode or disable the screen.
Slight disclaimer: i'm still not fully
awake and aren't going to proofread this properly before posting it, so if something doesn't make sense just say and i'll have another go. =-)