#include <vectrex.h> // 240 rather than 256 to leave a little slack for a margin // BLOCK LENGTH is actually half a block. Hence 120 not 240 below. #define BLOCKS_PER_SCREEN 15 #define BLOCK_LENGTH ((int)(120U / (unsigned int)BLOCKS_PER_SCREEN)) #define ROOF_SCALE 0xFF //#define FLOOR_SCALE ((unsigned int)(((long)ROOF_SCALE * BLOCKS_PER_SCREEN) / (BLOCKS_PER_SCREEN+1L))) #define set_scale(s) do { VIA_t1_cnt_lo = (unsigned int)s*2; } while (0) static int oldy, oldx; void LineAbs(int x, int y) { Draw_Line_d(y-oldy, x-oldx); oldx = x; oldy = y; } void MoveAbs(int x, int y) { Moveto_d(y-oldy, x-oldx); oldx = x; oldy = y; } int mapx(int x, int pass) { if (pass == 0) return x; return (int)(((long)x*7L)>>3L); } int mapy(int y, int pass) { if (pass == 0) return y; return (int)(((long)y*7L)>>3L); } void Line(int x1, int y1, int x2, int y2) { Reset0Ref(); oldx = oldy = 0; MoveAbs(x1, y1); LineAbs(x2, y2); } int main(void) { int basex = -59, basey = 59; int pass, few = 0; int dx=-1, dy=1; set_scale(ROOF_SCALE); for (;;) { Wait_Recal(); Reset0Ref(); oldx = oldy = 0; Intensity_a(0x60); for (pass = 0; pass <= 1; pass++) { // On the second pass, one or two of the base edges will not be visible // depending on the quadrant, and one or two of the other edges will be clipped. // Unfortunately using the center point as a test doesn't quite work, when the floor // square is entirely within the roof square, but still a little off-center. The actual // test needs to be against the two corners corresponding to the quadrant. // problem could be avoided if floor and roof are drawn at the same scale. Whether that // would have the right visual appeal remains to be seen... computation and verticals would // certainly be much cheaper! I.e. isometric rather than perspective. // left edge if (pass == 1 && basex < 0) { } else Line(mapx(-BLOCK_LENGTH+basex, pass), mapy(-BLOCK_LENGTH+basey, pass), mapx(-BLOCK_LENGTH+basex, pass), mapy(BLOCK_LENGTH+basey, pass)); // depending on the quadrant of the center of the block, some of the // z-edges will not be visible. // bottom left corner if (pass==0 && (!(basex < 0 && basey < 0))) Line(mapx(-BLOCK_LENGTH+basex, 0), mapy(-BLOCK_LENGTH+basey, 0), mapx(-BLOCK_LENGTH+basex, 1), mapy(-BLOCK_LENGTH+basey, 1)); // top edge if (pass == 1 && basey > 0 ) { } else Line(mapx(-BLOCK_LENGTH+basex, pass), mapy(BLOCK_LENGTH+basey, pass), mapx(BLOCK_LENGTH+basex, pass), mapy(BLOCK_LENGTH+basey, pass)); // top left corner if (pass==0 && (!(basex < 0 && basey > 0))) Line(mapx(-BLOCK_LENGTH+basex, 0), mapy(BLOCK_LENGTH+basey, 0), mapx(-BLOCK_LENGTH+basex, 1), mapy(BLOCK_LENGTH+basey, 1)); // right edge if (pass == 1 && basex > 0) { } else Line(mapx(BLOCK_LENGTH+basex, pass), mapy(BLOCK_LENGTH+basey, pass), mapx(BLOCK_LENGTH+basex, pass), mapy(-BLOCK_LENGTH+basey, pass)); // top right corner if (pass==0 && (!(basex > 0 && basey > 0))) Line(mapx(BLOCK_LENGTH+basex, 0), mapy(BLOCK_LENGTH+basey, 0), mapx(BLOCK_LENGTH+basex, 1), mapy(BLOCK_LENGTH+basey, 1)); // bottom edge if (pass == 1 && basey < 0) { } else Line(mapx(BLOCK_LENGTH+basex, pass), mapy(-BLOCK_LENGTH+basey, pass), mapx(-BLOCK_LENGTH+basex, pass), mapy(-BLOCK_LENGTH+basey, pass)); // bottom right corner if (pass==0 && (!(basex > 0 && basey < 0))) Line(mapx(BLOCK_LENGTH+basex, 0), mapy(-BLOCK_LENGTH+basey, 0), mapx(BLOCK_LENGTH+basex, 1), mapy(-BLOCK_LENGTH+basey, 1)); } if ((few&3)==3) { basex += dx; basey += dy; if (basex >= 60) dx = -dx; if (basey >= 60) dy = -dy; if (basex <= -60) dx = -dx; if (basey <= -60) dy = -dy; } few += 1; } return 0; }