#include <vectrex.h> #include "controller.h" #ifndef TRUE #define TRUE (0==0) #define FALSE (!TRUE) #endif static unsigned char current_intensity = 127; #define HEIGHT 30 #define HALF_HEIGHT 15 #define WIDTH 30 #define HALF_WIDTH 15 #define tx(x) (x) #define ty(y) (y) void line(int xl, int yb, int xr, int yt) { int a,b; int dx, dy; Intensity_a(current_intensity); Reset0Ref(); a=ty(yb); b=tx(xl); Moveto_d((int)(a<<2), (int)(b<<2)); dy = ty(yt)-a; dx = tx(xr)-b; Draw_Line_d((int)(dy<<2), (int)(dx<<2)); } // original author 'CatOnTreeStudio' at scratch.mit.edu // hacked by gtoal@gtoal.com for Vectrex // To do: use perspective spacing for walls as in // https://scratch.mit.edu/projects/157841571/ // (Currently spacing is linear and doesn't look quite right) #define KEY_RIGHT 0 #define KEY_LEFT 1 #define KEY_UP 2 #define KEY_DOWN 3 #define KEY_ANY 4 int key(int code) { unsigned int bit[5] = { 0x88, 0x44, 0x22, 0x11, 0xFF }; return (int)buttons_pressed() & (int)bit[code]; } #define FADE 8 void intensity(int i) { Intensity_a(current_intensity = (unsigned char)i); } static int rotation=1, KeyPressOn=0; static int dist, stepX=0, stepY=0, Size_X, Size_Y, HeroPosY, HeroPosX, ScreenSizeX, ScreenSizeY, ScreenPosX, ScreenPosY; // The original scratch code supported coloured blocks and the different // codes (1:7) below represent different coloured blocks (walls). // (9 is a corridor space and I think 8 was for an object in a space) // If the maze is pre-built like this, using a large array is OK as it // is const and therefore in ROM space. However if you need dynamic // dungeon generation then the array could be shrunk considerably by // replacing each byte with a single bit (since the vectrex only // supports one colour), and packing 8 bits per byte. // (the fenceposts are because Scratch's arrays are based at 1 rather than 0. // - easier to add an exra element than to adjust all the indexes) const char *Level[] = { "1111111111111111111111" "1111111111111111111111", "1199919119991199991111", // <-- starts in northwest corner (2,2) "1191119999199994491111", "1191111119194444491111", "1191111119199999499911", "1199999989111944444911", "1191111939111999494911", "1191199939991119994911", "1111193333391119199911", "1199199933399919111111", "1191111933333919999111", "1199999939933919119911", "1191111933933919111911", "1191111933933911111911", "1191191993999999199911", "1199991193933919991911", "1191191993933911111911", "1191191933933911999911", "1191191993999911111211", "1111111113333111111111", "1111111111111111111111", }; // left and right wall code could be merged into one procedure at the expense of clarity. // I'm OK with the redundancy for now. void DrawLeftWall (int WallPosXLeft, int WallPosYUp, int WallPosYDown, int stepX, int stepY) { if (Level[(HeroPosY + dist * stepY - stepX)][(HeroPosX + dist * stepX + stepY)] > '7') { if (Level[(HeroPosY + (dist + 1) * stepY - stepX)][(HeroPosX + (dist + 1) * stepX + stepY)] > '7') { if (WallPosYUp - (HALF_WIDTH + (dist + 1) * Size_X) * 3/8 != 0) { line(WallPosXLeft + dist * Size_X, WallPosYUp - (HALF_WIDTH + dist * Size_X) * 3/8, WallPosXLeft + (dist + 1) * Size_X, WallPosYUp - (HALF_WIDTH + (dist + 1) * Size_X) * 3/8); } if (WallPosYDown + (dist + 1) * Size_Y != 0) { line(WallPosXLeft + (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y, WallPosXLeft + (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y); line(WallPosXLeft + (dist + 1) * Size_X, WallPosYDown + (HALF_WIDTH + (dist + 1) * Size_X) * 3/8, WallPosXLeft + dist * Size_X, WallPosYDown + (HALF_WIDTH + dist * Size_X) * 3/8); } } else { if (WallPosYUp - (dist + 1) * Size_Y != 0) { line(WallPosXLeft + dist * Size_X, WallPosYUp - (dist + 1) * Size_Y, WallPosXLeft + (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y); line(WallPosXLeft + (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y, WallPosXLeft + (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y); line(WallPosXLeft + (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y, WallPosXLeft + dist * Size_X, WallPosYDown + (dist + 1) * Size_Y); } } } else { if (WallPosYDown + (dist + 1) * Size_Y != 0) { line(WallPosXLeft + dist * Size_X, WallPosYUp - dist * Size_Y, WallPosXLeft + (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y); line(WallPosXLeft + (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y, WallPosXLeft + (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y); line(WallPosXLeft + (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y, WallPosXLeft + dist * Size_X, WallPosYDown + dist * Size_Y); } } } void DrawRightWall (int WallPosXRight, int WallPosYUp, int WallPosYDown, int stepX, int stepY) { if (Level[(HeroPosY + dist * stepY + stepX)][(HeroPosX + dist * stepX - stepY)] > '7') { if (Level[(HeroPosY + (dist + 1) * stepY + stepX)][(HeroPosX + (dist + 1) * stepX - stepY)] > '7') { if (WallPosYUp - (dist + 1) * Size_Y != 0) { line(WallPosXRight - dist * Size_X, WallPosYUp - (HALF_WIDTH + dist * Size_X) * 3/8, WallPosXRight - (dist + 1) * Size_X, WallPosYUp - (HALF_WIDTH + (dist + 1) * Size_X) * 3/8); line(WallPosXRight - (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y, WallPosXRight - (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y); line(WallPosXRight - (dist + 1) * Size_X, WallPosYDown + (HALF_WIDTH + (dist + 1) * Size_X) * 3/8, WallPosXRight - dist * Size_X, WallPosYDown + (HALF_WIDTH + dist * Size_X) * 3/8); } } else { if (WallPosYUp - (dist + 1) * Size_Y != 0) { line(WallPosXRight - dist * Size_X, WallPosYUp - (dist + 1) * Size_Y, WallPosXRight - (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y); line(WallPosXRight - (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y, WallPosXRight - (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y); line(WallPosXRight - (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y, WallPosXRight - dist * Size_X, WallPosYDown + (dist + 1) * Size_Y); } } } else { if (WallPosYDown + (dist + 1) * Size_Y != 0) { line(WallPosXRight - dist * Size_X, WallPosYDown + dist * Size_Y, WallPosXRight - dist * Size_X, WallPosYUp - dist * Size_Y); line(WallPosXRight - dist * Size_X, WallPosYUp - dist * Size_Y, WallPosXRight - (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y); line(WallPosXRight - (dist + 1) * Size_X, WallPosYUp - (dist + 1) * Size_Y, WallPosXRight - (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y); line(WallPosXRight - (dist + 1) * Size_X, WallPosYDown + (dist + 1) * Size_Y, WallPosXRight - dist * Size_X, WallPosYDown + dist * Size_Y); } } } void BuildBackgroundWall (int WallPosXLeft, int WallPosXRight, int WallPosYDown, int WallPosYUp, int stepX, int stepY) { dist = 0; intensity ((int)(64 - dist * FADE)); while (!( (Level[(HeroPosY + dist * stepY)][(HeroPosX + dist * stepX)] < '8') || (dist > 4) )) { DrawLeftWall (WallPosXLeft, WallPosYUp, WallPosYDown, stepX, stepY); DrawRightWall (WallPosXRight, WallPosYUp, WallPosYDown, stepX, stepY); dist += 1; intensity ((int)(64 - dist * FADE)); } intensity ((int)(64 - (dist - 1) * FADE)); if (WallPosYDown + dist * Size_Y != 0) { line(WallPosXLeft + dist * Size_X, WallPosYDown + dist * Size_Y, WallPosXRight - dist * Size_X, WallPosYDown + dist * Size_Y); line(WallPosXRight - dist * Size_X, WallPosYUp - dist * Size_Y, WallPosXLeft + dist * Size_X, WallPosYUp - dist * Size_Y); } } #define set_scale(i) VIA_t1_cnt_lo = i void DrawFrame(void) { Wait_Recal(); set_scale(0x7F); Read_Btns(); enable_controller_1_x(); enable_controller_1_y(); Joy_Analog(); Intensity_a(60); Print_Str_d(-100,-120, "BACK FORWARD LEFT RIGHT\x80"); if (rotation == 0) { stepX = 1; stepY = 0; } else if (rotation == 1) { stepX = 0; stepY = 1; } else if (rotation == 2) { stepX = -1; stepY = 0; } else /* rotation == 3 */ { stepX = 0; stepY = -1; } if (KeyPressOn && !key(KEY_ANY)) { KeyPressOn = 0; } else if (key(KEY_LEFT)) { if (KeyPressOn == 0) { rotation += 3; KeyPressOn = 1; } } else if (key(KEY_RIGHT)) { if (KeyPressOn == 0) { rotation += 1; KeyPressOn = 1; } } else if (key(KEY_UP)) { if (KeyPressOn == 0) { if (Level[(HeroPosY + stepY)][(HeroPosX + stepX)] > '7') { HeroPosX += stepX; HeroPosY += stepY; } KeyPressOn = 1; } } else if (key(KEY_DOWN)) { if (KeyPressOn == 0) { if (Level[(HeroPosY - stepY)][(HeroPosX - stepX)] > '7') { HeroPosX -= stepX; HeroPosY -= stepY; } KeyPressOn = 1; } } rotation &= 3; { int a,b,c,d; // avoid gcc bug a = (rotation^1)&1; b = -((rotation&2)-1); c = (rotation&1); d = -((rotation&2)-1); BuildBackgroundWall (ScreenPosX, ScreenPosX + ScreenSizeX, ScreenPosY, ScreenPosY + ScreenSizeY, a * b, c * d); } } int main(void) { HeroPosY = 2; HeroPosX = 2; // initial square ScreenSizeX = WIDTH; ScreenSizeY = HEIGHT; // size of scratch display ScreenPosX = -HALF_WIDTH; ScreenPosY = -HALF_HEIGHT; // center Size_X = ScreenSizeX / 10L; Size_Y = ScreenSizeY / 10L; for (;;) DrawFrame(); return 0; }