- fixed the synchronized rotation issue with large asteroids
When I first started coding Space Rocks, I set it up to support an arbitrary number of styles for each size of asteroid as I didn't know how many would end up in the game. So I wrote the original InitWave routine like this to select a random asteroid style, rotation and speed:
gSpriteAnimSeqID[i] = LARGE_ASTEROID_SEQ_ID + ((LARGE_VARIATIONS * (Random32() & 0xff)) >> ; gSpriteAnimControl[i] = RandomRotation();
LARGE_VARIATIONS is defined as the number of styles, say 2, 3 or 4. The multiplication with Random32(), combined with the masking (&) and shifting (>>) results in 0-1 for 2 styles, 0-2 for 3 and 0-3 for 4.
I thought we'd end up with 3, maybe 4, but the graphics took more space than I was expecting so we ended up with just 21 styles (and we even had to reduce the number of rotation positions from 32 to 24.) As ROM grew ever tighter, I started optimizing the code and rewrote that section like this:
gSpriteAnimSeqID[i] = LARGE_ASTEROID_SEQ_ID + (Random32() & 1); gSpriteAnimControl[i] = RandomRotation();
Because the style of asteroid and the rotation were in sync with each other (so that style A rotates one direction and B the other), something had to be going on in RandomRotation(). At first glance it's not obvious what it could be:
unsigned char RandomRotation() { // bit 7 controls rotation direction, 0-6 speed // rotation speeds 8-23 return ((Random32() >> 24) & 0x8F) + 8; }
In computers, there's no such thing as random. We simulate random using various techniques, and the one I'm using in Space Rocks is known as a Linear Feedback Shift Register (LFSR). The specific implementation I'm using is the Galios LFSR.
unsigned int Random32() { static unsigned int random = 0x02468ace; return random = (random >> 1) ^ (unsigned int)(-(random & 1u) & 0xd0000001u); }
In looking at the init wave routines, bit 0 of the random number is being used to determine which asteroid style is drawn.
In looking at the rotation/speed routines, bit 31 of the random number is being used to determine the direction of rotation.
In looking at the random number routine, the prior random number is manipulated in such a way that the inversion of whatever was in bit 0 is now in bit 31 (if bit 0 had 0, then bit 31 will get 1. If bit 0 had 1, 31 will get 0). This link between bit 0 of the prior and bit 31 of the current random number is what caused the rotation and style to be in sync.
To fix the problem of synchronized rotations, I modified RandomRotation to use a different 8 bit segment of the LFSR as such:
unsigned char RandomRotation() { // bit 7 controls rotation direction, 0-6 speed // rotation speeds 8-23 return ((Random32() >> 16) & 0x8F) + 8; }
1there's really 4 styles as each style is available in solid or vector format.
ROMs
Note: if you have a Harmony, please run the Stress Test ROM on your real Atari so we can make sure the screen jitter and rolling problem has been resolved.
spacerocks20121004_STRESS_TEST.bin
Source
29 Comments
Recommended Comments