#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;
}