/* ============================================================================== WordUp Graphics Toolkit Version 5.0 Demonstration Program 56 This program uses the scrolling library to create a parallax scrolling world with two layers. There are three kinds of objects in the world; clouds, yellow balls (wearing shades) that move behind the front layer, and yellow balls that move in front. 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 *** PARABACK.SPR, PARAFRON.SPR, PARASPR.SPR, PARAMAPB.WMP, PARAMAPF.WMP WATCOM C++ VERSION ============================================================================== */ #include #include #include #include #define WIND_SIZEX 20 /* Set scrolling window dimensions (in tiles) */ #define WIND_SIZEY 13 #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 backtiles[256]; /* Tiles, objects and tiles types for the */ scrollsprite backobject[200]; /* background window. */ short backtypes[256]; block fronttiles[256]; /* Tiles, objects and tiles types for the */ scrollsprite frontobject[200]; /* foreground window. */ short fronttypes[256]; block sprites[50]; /* The sprite images */ int timer; /* Counts timer ticks */ color pal[256]; short movex, movey; /* Amount to scroll the front */ short bmovex, bmovey; /* Amount to scroll the back */ short x, y; /* Current viewing coordinates */ /* The window tries to center itself on this coordinate. */ short num_clouds; /* Number of cloud sprites on background */ 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 backmap; /* Holds the scrolling map */ wgtmap frontmap; /* Holds the scrolling map */ 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_clouds = 0; for (i = 0; i < 100; i++) if (backobject[i].on) num_clouds = 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 set_cloud_movements (void) /* Sets up the movement and speed for clouds */ { short i; for (i = 0; i < num_clouds; i++) { cloud_speed[i] = (rand () % 6)-3; if (cloud_speed[i] == 0) cloud_speed[i] = 1; } } void move_clouds (scrollsprite *s) /* Moves the clouds and wraps them around the map if needed */ { short i; short maxx; maxx = mapwidth[BACKWIN] * tilewidth[BACKWIN]; for (i = 0; i < num_clouds; i++) { backobject[i].x += cloud_speed[i]; if (backobject[i].x < -80) backobject[i].x = maxx; else if (backobject[i].x > maxx) backobject[i].x = -80; } } 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 timerctr (void) { timer++; } void main (void) { float seconds, fps; int frames = 0; oldmode = wgetmode (); if (!vgadetected ()) { printf ("VGA is required to run this program..."); exit (1); } printf ("WGT Example #56\n\n"); printf ("This program uses the scrolling library to create a parallax scrolling\n"); printf ("world with two layers. There are three kinds of objects in the world\n"); printf ("clouds, yellow balls (wearing shades) that move behind the front layer,\n"); printf ("and yellow balls that move in front. Use the arrow keys to move around\n"); printf ("and ESC will exit.\n"); printf ("You can also save and load the map by pressing S and L.\n"); printf ("\nPress any key to begin\n"); getch (); vga256 (); wloadsprites (pal, "paraspr.spr", sprites, 0, 49); wloadsprites (pal, "paraback.spr", backtiles, 0, 255); wloadsprites (pal, "parafron.spr", fronttiles, 0, 255); wsetpalette (0, 255, pal); winitscroll (BACKWIN, NORMAL, 0, WIND_SIZEX / 2, WIND_SIZEY / 2, backtiles); /* Uses half the size since the background tiles are twice as big (32x32) */ winitscroll (FRONTWIN, PARALLAX, BACKWIN, WIND_SIZEX, WIND_SIZEY, fronttiles); /* Link this window to the background one */ backmap = wloadmap (BACKWIN, "paramapb.wmp", backtypes, backobject); frontmap = wloadmap (FRONTWIN, "paramapf.wmp", fronttypes, frontobject); /* Load the maps in for both windows */ wshowwindow (BACKWIN, 0, 0); wshowwindow (FRONTWIN, 0, 0); /* Set the initial viewing coordinates. */ find_sprites (); set_cloud_movements (); installkbd (); /* Install the custom keyboard handler */ timer = 0; winittimer (); wstarttimer (timerctr, TICKS(70)); do { move_clouds (backobject); 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]; bmovex = movex * 5 / 4; bmovey = movey; wscrollwindow (BACKWIN, bmovex, bmovey); /* Display the background layer. (Layers are drawn from back to front.) */ wshowobjects(BACKWIN, 0, num_clouds, sprites, backobject); /* Show the clouds next */ 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. */ if (kbdon[KEY_S]) /* Save the map */ { while (kbdon[KEY_S] == 1) wretrace (); /* Wait until the user releases the S key */ wsavemap (FRONTWIN, "savefron.wmp", frontmap, fronttypes, frontobject, num_ball_behind+1); wsavemap (BACKWIN, "saveback.wmp", backmap, backtypes, backobject, num_clouds+1); } if (kbdon[KEY_L]) /* Load the map */ { while (kbdon[KEY_L]) wretrace (); /* Wait until the user releases the L key */ wfreemap (frontmap); /* Free the maps that are already in memory */ wfreemap (backmap); frontmap = wloadmap (FRONTWIN, "savefron.wmp", fronttypes, frontobject); backmap = wloadmap (BACKWIN, "saveback.wmp", backtypes, backobject); } frames++; } while (kbdon[ESC] == 0); wstoptimer (); wdonetimer (); /* Now clean up everything */ wendscroll (FRONTWIN); wendscroll (BACKWIN); uninstallkbd (); wfreesprites (fronttiles, 0, 255); wfreesprites (backtiles, 0, 255); wfreesprites (sprites, 0, 49); wfreemap (backmap); wfreemap (frontmap); wsetmode (oldmode); seconds = (float)(timer / 70.0); fps = (float)(frames) / seconds; printf ("Frames completed: %d\n", frames); printf ("Seconds elapsed: %g\n", seconds); printf ("FPS: %g\n", fps); }