#include <pitrex/pitrexio-gpio.h> #include <vectrex/vectrexInterface.h> #ifndef TRUE #define TRUE (0==0) #define FALSE (!TRUE) #endif static unsigned char current_intensity = 127; int tx(int x) { // rescale return x*50; } int ty(int y) { return y*50; } void line(int xl, int yb, int xr, int yt) { v_directDraw32(tx(xl),ty(yb), tx(xr),ty(yt), current_intensity); } // 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) { int bit[5] = { 0x88, 0x44, 0x22, 0x11, 0xFF }; return currentButtonState & bit[code]; } #define FADE 8 void intensity(int i) { v_setBrightness(current_intensity = i); } static int dist, rotation=1, stepX=0, stepY=0, KeyPressOn=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 - (240 + (dist + 1) * Size_X) * 3/8 != 0) { line(WallPosXLeft + dist * Size_X, WallPosYUp - (240 + dist * Size_X) * 3/8, WallPosXLeft + (dist + 1) * Size_X, WallPosYUp - (240 + (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 + (240 + (dist + 1) * Size_X) * 3/8, WallPosXLeft + dist * Size_X, WallPosYDown + (240 + 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 - (240 + dist * Size_X) * 3/8, WallPosXRight - (dist + 1) * Size_X, WallPosYUp - (240 + (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 + (240 + (dist + 1) * Size_X) * 3/8, WallPosXRight - dist * Size_X, WallPosYDown + (240 + 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 (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 (64 - dist * FADE); } intensity (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); } } void DrawFrame(void) { v_WaitRecal(); //v_doSound(); v_setBrightness(64); /* set intensity of vector beam... */ v_readButtons(); v_readJoystick1Analog(); //v_playAllSFX(); v_setBrightness(60); v_printStringRaster(-60,-120, "BACK FORWARD LEFT RIGHT", 30, -7, '\0'); 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; BuildBackgroundWall (ScreenPosX, ScreenPosX + ScreenSizeX, ScreenPosY, ScreenPosY + ScreenSizeY, ((rotation^1)&1) * -((rotation&2)-1), (rotation&1) * -((rotation&2)-1)); } int main(int argc, char **argv) { HeroPosY = 2; HeroPosX = 2; // initial square ScreenSizeX = 480; ScreenSizeY = 360; // size of scratch display ScreenPosX = -240; ScreenPosY = -180; // center Size_X = ScreenSizeX / 10; Size_Y = ScreenSizeY / 10; vectrexinit(1); v_init(); usePipeline = 1; v_setRefresh(60); for (;;) DrawFrame(); return 0; }