/* ============================================================================== WordUp Graphics Toolkit Version 5.0 Demonstration Program 68 This program uses the scrolling library to create a parallax scrolling world with two layers. The background layer is a 640x400 bitmap. Use the arrow keys to move around and ESC will exit. *** PROJECT *** This program requires the files WGT5_WC.LIB and WSCR_WC.LIB to be linked. *** DATA FILES *** PARAFRON.SPR, PARASPR.SPR, PARAMAPF.WMP, SHIP.PCX WATCOM C++ VERSION ============================================================================== */ #include #include #include #include #define WIND_SIZEX 18 /* Set scrolling window dimensions (in tiles) */ #define WIND_SIZEY 12 #define SPEED 8 /* Speed of scrolling */ #define LEFT 75 /* Keyboard codes */ #define RIGHT 77 #define UP 72 #define DOWN 80 #define ESC 1 #define KEY_S 31 #define KEY_L 38 #define BACKWIN 0 /* The NORMAL layer */ #define FRONTWIN 1 /* The PARALLAX layer */ block fronttiles[256]; /* Tiles, objects and tiles types for the */ scrollsprite frontobject[200]; /* foreground window. */ short fronttypes[256]; block sprites[50]; /* The sprite images */ color pal[256]; short movex, movey; /* Amount to scroll the front */ short backx, backy; /* Coordinates of the background screen */ short x, y; /* Current viewing coordinates */ /* The window tries to center itself on this coordinate. */ short num_ball_behind; /* Number of yellow balls behind front layer. All yellow balls with object numbers 100-199 are drawn between the background and foreground layers. */ short num_ball_infront; /* Number of yellow balls in front of every layer */ short cloud_speed[100]; /* Movement speed and direction for clouds */ short oldmode; /* Old video mode */ wgtmap frontmap; /* Holds the scrolling map */ float xscale, yscale; /* Difference between size of map and size of background picture */ block backgroundpic; /* A 640x400 picture */ void find_sprites (void) /* Searches for the maximum object numbers for each of the three categories of wobjects. (clouds, ball behind, ball in front) */ { short i; num_ball_behind = 0; for (i = 100; i < 200; i++) if (frontobject[i].on) num_ball_behind = i; num_ball_infront = 0; for (i = 0; i < 100; i++) if (frontobject[i].on) num_ball_infront = i; } void move_balls (void) /* Moves the balls around randomly */ { short i; short maxx, maxy; maxx = mapwidth[BACKWIN] * tilewidth[BACKWIN]; maxy = mapheight[BACKWIN] * tileheight[BACKWIN]; for (i = 0; i <= num_ball_infront; i++) { frontobject[i].x += (rand () % 17) - 8; /* Randomly move the ball */ frontobject[i].y += (rand () % 17) - 8; if (frontobject[i].x < 0) /* Check the X boundaries */ frontobject[i].x = 0; else if (frontobject[i].x > maxx) frontobject[i].x = maxx; if (frontobject[i].y < 0) /* Check the Y boundaries */ frontobject[i].y = 0; else if (frontobject[i].y > maxy) frontobject[i].y = maxy; } for (i = 100; i <= num_ball_behind; i++) /* Do the same with the balls behind the front layer. */ { frontobject[i].x += (rand () % 17) - 8; frontobject[i].y += (rand () % 17) - 8; if (frontobject[i].x < 0) frontobject[i].x = 0; else if (frontobject[i].x > maxx) frontobject[i].x = maxx; if (frontobject[i].y < 0) frontobject[i].y = 0; else if (frontobject[i].y > maxy) frontobject[i].y = maxy; } } void main (void) { struct dostime_t t1, t2; float seconds, fps; int frames = 0; oldmode = wgetmode (); if (!vgadetected ()) { printf ("VGA is required to run this program..."); exit (1); } printf ("WGT Example #69\n\n"); printf ("This program uses the scrolling library to create a parallax scrolling\n"); printf ("world with two layers. The background layer is a 640x400 bitmap.\n"); printf ("Use the arrow keys to move around and ESC will exit.\n"); printf ("\nPress any key to begin.\n"); getch (); vga256 (); wloadsprites (pal, "paraspr.spr", sprites, 0, 49); wloadsprites (pal, "parafron.spr", fronttiles, 0, 255); backgroundpic = wloadpcx ("ship.pcx", pal); wsetpalette (0, 255, pal); winitscroll (BACKWIN, NORMAL, 0, WIND_SIZEX, WIND_SIZEY, fronttiles); /* Make a background window using the same tile sizes. We won't use tiles on this layer but we still need to set up the window with the correct size. */ winitscroll (FRONTWIN, PARALLAX, BACKWIN, WIND_SIZEX, WIND_SIZEY, fronttiles); /* Link this window to the background one */ frontmap = wloadmap (FRONTWIN, "paramapf.wmp", fronttypes, frontobject); wcopymap (FRONTWIN, BACKWIN); /* Load the maps in for both windows */ wshowwindow (FRONTWIN, 0, 0); /* Set the initial viewing coordinates. */ x = 0 * tilewidth[FRONTWIN]; y = 0 * tileheight[FRONTWIN]; xscale = (float)(wgetblockwidth (backgroundpic) - windowmaxx [FRONTWIN] - 1) / (float)worldmaxx [FRONTWIN]; yscale = (float)(wgetblockheight (backgroundpic) - windowmaxy [FRONTWIN] - 1) / (float)worldmaxy [FRONTWIN]; find_sprites (); installkbd (); /* Install the custom keyboard handler */ _dos_gettime (&t1); do { move_balls (); if (kbdon[LEFT]) /* Change the viewing coordinates */ { x -= 8; if (x < 0) x = 0; } if (kbdon[RIGHT]) { x += 8; if (x > worldmaxx[FRONTWIN]) x = worldmaxx[FRONTWIN]; } if (kbdon[UP]) { y -= 8; if (y < 0) y = 0; } if (kbdon[DOWN]) { y += 8; if (y > worldmaxy[FRONTWIN]) y = worldmaxy[FRONTWIN]; } /* Move the foreground by finding the difference between the actual world coordinates and the desired world coordinates. This will make sure the window is centered on the (x,y) coordinate. */ movex = x - worldx[FRONTWIN]; movey = y - worldy[FRONTWIN]; backx = x * xscale; backy = y * yscale; wsetscreen (scrollblock [BACKWIN]); wputblock (-backx, -backy, backgroundpic, 0); wshowobjects(BACKWIN, 100, num_ball_behind, sprites, frontobject); /* Show the balls that are behind the front layer. (They will be just in front of the clouds) */ wscrollwindow (FRONTWIN, movex, movey); /* Display the foreground layer */ wshowobjects(FRONTWIN, 0, num_ball_infront, sprites, frontobject); /* Show the balls that are in front of everything else. */ wnormscreen (); /* Uncomment the following line to time with the vertical retrace */ //wretrace(); wputblock (0, 0, scrollblock[BACKWIN], 0); /* Once the image is built, display the whole thing on the visual screen. */ frames++; } while (kbdon[ESC] == 0); _dos_gettime (&t2); /* Now clean up everything */ wendscroll (FRONTWIN); wendscroll (BACKWIN); uninstallkbd (); wfreeblock (backgroundpic); wfreesprites (fronttiles, 0, 255); wfreesprites (sprites, 0, 49); wfreemap (frontmap); wsetmode (oldmode); }