/*
==============================================================================
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 <stdlib.h>
#include <dos.h>
#include <wgt5.h>
#include <wgtscrol.h>
#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);
}