View Single Post
Old 07 January 2019, 19:22   #41
Registered User
Join Date: Dec 2017
Location: Austin, TX
Age: 36
Posts: 187
Lou's Pseudo 3d Page has got you covered for the maths.

I've attached an image showing the bitmap used by the game. It's drawn with the blitter and has some perspective-correct stripes in different colors. If the closest visible object is at z=1 then the most distant is chosen to be at z=7. This ratio 7:1 approximates the camera field-of-view. It's an arbitrary choice and I chose it for aesthetics.

The edge of each stripe is placed at some horizontal position near_x (center of the screen at x=0, negative to left, positive to right). At the farthest (highest) point on the screen: far_x = near_x / 7 . These form straight lines to draw with the blitter and fill between with colors. After this point the bitmap is not changed during gameplay.

The copper does all the magic. On every row of the screen (about 200 in total in the playing area) a new color value is set for color indices 1-6. These values are decided by the CPU and written into the copperlist during each frame. There are about 50 different color values used in total, but the bitmap records only 8 unique areas of color per row.

The camera position is tracked horizontally (camera_x) and into the screen (camera_z). Shifting the camera horizontally uses a classic pseudo 3D trick: shift each row of the display by a different amount, more closer to the camera than further away. This gives the illusion of parallax. For a chosen near_shift_x we can calculate: far_shift_x = near_shift_x / 7. Big values close to the camera, small values far away.

camera_z starts at 0. As the music plays camera_z increases at a rate consistent with the speed of the MOD (which can vary throughout the song), once per frame.

For each row of the display the corresponding Z position is calculated. screen_z = camera_z at the bottom. Progressing up the screen a different value is added at each row. These values are smaller at the bottom and larger towards the top, since things further away appear smaller. This part's described well by Lou's page linked above, summarized in: y_screen = (y_world*dist)/z_world. The Z steps are inversely proportional in size to Y.

Given a Z value for each row then the rest is quite easy. Track stripes are as simple as testing (z & (1 << some_bit)). e.g. for bit 8, Z values 0-255 give false, 256-511 give true, 512-767 give false, etc. Based on true/false just set the stripe color value to foreground or background. Since our Z values already scale correctly with perspective the stripes will seem to "move" faster as they get nearer to the camera.

Blocks on the tracks are drawn in a similar way. Colors 2,3,4 (left/middle/right) are set to foreground (actually a different color representing pitch) or background depending on whether they intersect the Z position for that screen row. A separate data structure records where the blocks are located and is walked through in sync with the MOD replayer.
Attached Thumbnails
Click image for larger version

Name:	modsurfer-tricks.png
Views:	106
Size:	24.6 KB
ID:	61495  
arcanist is offline  
Page generated in 0.24934 seconds with 12 queries