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