// original author 'CatOnTreeStudio' at scratch.mit.edu // hacked by gtoal@gtoal.com // Run the project at https://scratch.mit.edu/projects/249442352/ by // clicking on the Green Flag. // 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_LEFT 1 #define KEY_RIGHT 2 #define KEY_UP 3 #define KEY_DOWN 4 void line(int fx, int fy, int tx, int ty) { } int key(int code) { } void intensity(int i) { } static int dist, rotation, stepX, stepY, KeyPressOn, 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 '?'s 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[] = { "?????????????????????" "?11111111111111111111", "?19991911999119999111", "?19111999919999449111", "?19111111919444449111", "?19111111919999949991", "?19999998911194444491", "?19111193911199949491", "?19119993999111999491", "?11119333339111919991", "?19919993339991911111", "?19111193333391999911", "?19999993993391911991", "?19111193393391911191", "?19111193393391111191", "?19119199399999919991", "?19999119393391999191", "?19119199393391111191", "?19119193393391199991", "?19119199399991111121", "?11111111333311111111", }; // 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 (60 - dist * 21); 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 (60 - dist * 21); } intensity (60 - (dist - 1) * 21); 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) { if (rotation == 0) { stepX = 1; stepY = 0; } else if (rotation == 90) { stepX = 0; stepY = 1; } else if (rotation == 180) { stepX = -1; stepY = 0; } else /* rotation == 270 */ { stepX = 0; stepY = -1; } if (key(KEY_LEFT)) { if (KeyPressOn == 0) { rotation += 270; KeyPressOn = 1; // was -= 90 but this ensures "% 360" below will be safe. } } if (key(KEY_RIGHT)) { if (KeyPressOn == 0) { rotation += 90; KeyPressOn = 1; } } rotation = rotation % 360; if (key(KEY_UP)) { if (KeyPressOn == 0) { if (Level[(HeroPosY + stepY)][(HeroPosX + stepX)] > '7') { HeroPosX += stepX; HeroPosY += stepY; } KeyPressOn = 1; } } if (key(KEY_DOWN)) { if (KeyPressOn == 0) { if (Level[(HeroPosY - stepY)][(HeroPosX - stepX)] > '7') { HeroPosX -= stepX; HeroPosY -= stepY; } KeyPressOn = 1; } } { // THIS WILL NEED WORK FOR THE VECTREX // Key debouncing will need to be handled differently from system // to system. The Scratch system had an 'any key' test which it used // to debounce the keys. KeyPressOn = 0; } if (rotation == 0) BuildBackgroundWall (ScreenPosX, ScreenPosX + ScreenSizeX, ScreenPosY, ScreenPosY + ScreenSizeY, 1, 0); if (rotation == 90) BuildBackgroundWall (ScreenPosX, ScreenPosX + ScreenSizeX, ScreenPosY, ScreenPosY + ScreenSizeY, 0, 1); if (rotation == 180) BuildBackgroundWall (ScreenPosX, ScreenPosX + ScreenSizeX, ScreenPosY, ScreenPosY + ScreenSizeY, -1, 0); if (rotation == 270) BuildBackgroundWall (ScreenPosX, ScreenPosX + ScreenSizeX, ScreenPosY, ScreenPosY + ScreenSizeY, 0, -1); } void 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; rotation = 90; for (;;) { DrawFrame(); } }