#include #include /* ============================================================================== WordUp Graphics Toolkit Version 5.0 Demonstration Program 68d Same as wgt68c.c, but uses timer controlled animation. *** PROJECT *** This program requires the WGT5_WC.LIB file to be linked. *** DATA FILES *** STREET.PAL, RUN.SPR WATCOM C++ VERSION ============================================================================== */ unsigned char shadowtable[256]; /* Shadow table */ unsigned char *transparency_table; /* a 65536 byte table, allocated dynamically */ color pal[256]; /* The palette used for every graphic image */ block sprites[200]; /* Array of images for the running robot */ block background; /* Holds the background scrolling image */ block work; /* Page for constructing each frame */ int oldmode; int animation_count; /* Used for animation timing */ int movement_multiplier;/* Number of times to move objects, ground, etc */ /* A structure which holds the scrolling values for each horizontal line */ typedef struct { int x; /* Current x value, shifted by 8 */ int increment; /* fixed point increment */ } line_scroll; line_scroll lines[80]; /* 80 scrolling lines along the ground */ /* A simple sprite structure */ typedef struct { int x; int y; int anm; /* Sprite number */ } sprite; sprite people[5]; int backx = 0; /* X value for the scrolling rocks */ int backinc; /* X increment for scrolling rocks */ /* Loads the graphics files, and allocates buffers */ void load_graphics (void) { work = wallocblock (320, 200); /* Allocate a work buffer */ wloadsprites (pal, "run.spr", sprites, 0, 199); background = wloadpak ("street.pak"); wsetpalette (0, 255, pal); transparency_table = (unsigned char *)malloc (65536); } /* Frees the buffers and sprites */ void free_graphics (void) { free (transparency_table); wfreesprites (sprites, 0, 199); wfreeblock (background); wfreeblock (work); } /* Set up the initial scrolling values */ void init_lines (void) { int i; int inc; inc = 128; /* slowest scrolling speed (128/256 of a pixel */ backx = 0; /* rocks x value */ backinc = inc; /* rocks same speed as the ground */ for (i = 0; i < 80; i++) { lines[i].x = 0; /* clear out the x value */ lines[i].increment = inc; /* set the scroll speed */ inc += 32; /* Make the next row move faster */ } } /* Construct the background image */ void animate_lines (void) { block source1, source2; block dest1, dest2; block origsource, origdest; int i; int x; int mult; wcopyscreen (0, 0, 319, 51, background, 0, 0, work); /* Draw the moon stationary */ /* Scroll the rocks */ for (mult = 0; mult <= movement_multiplier; mult++) { backx += backinc; if (backx >= 81920) /* 81920 is 320 << 8 */ backx -= 81920; } x = backx >> 8; /* Copy the rocks */ wcopyscreen (x, 52, 319, 119, background, 0, 52, work); if (x > 0) wcopyscreen (0, 52, x-1, 119, background, 320 - x, 52, work); origdest = abuf + 120 * 320; /* First row to copy */ origsource = background + 120 * 320; /* First row to copy */ for (i = 0; i < 80; i++) { /* Scroll this line */ for (mult = 0; mult <= movement_multiplier; mult++) { lines[i].x += lines[i].increment; if (lines[i].x >= 81920) /* 81920 is 320 << 8, wraps scroll around */ lines[i].x -= 81920; } x = lines[i].x >> 8; /* Get the x coord */ dest1 = origdest + i * 320; dest2 = dest1 + (319 - x); source1 = origsource + i * 320; source2 = source1 + x; /* Copy the line in two steps */ memcpy (dest1, source2, 320 - x); if (x > 0) memcpy (dest2, source1, x + 1); } } /* Animates and displays the running man */ void animate_man (void) { int mult; for (mult = 0; mult <= movement_multiplier; mult++) { people[0].anm++; if (people[0].anm > 29) people[0].anm = 0; } wputblock_shade (people[0].x, 158, sprites[people[0].anm+30], shadowtable, SHADE_SHADOW); wputblock_shade (people[0].x, people[0].y, sprites[people[0].anm], transparency_table, SHADE_TRANSLUCENT); } void wcreate_shadow_table (color *palette) { float fr, fg, fb; long ir, ig, ib; long absr, absg, absb; int r,g,b; short col; short findcol; unsigned long lowest; unsigned char bestfit; unsigned long coldif; for (col = 0; col < 256; col++) { fr = (float)palette[col].r * (0.5); fg = (float)palette[col].g * (0.5); fb = (float)palette[col].b * (0.5); ir = fr; ig = fg; ib = fb; lowest = 655350; for (findcol = 0; findcol < 256; findcol++) { absr = abs ( (long)palette[findcol].r - ir); absg = abs ( (long)palette[findcol].g - ig); absb = abs ( (long)palette[findcol].b - ib); coldif = absr + absg + absb; if ((coldif < lowest) && (findcol != col)) { lowest = coldif; bestfit = findcol; } } shadowtable[col] = bestfit; } } void wcreate_transparency_table (color *pal) { float lightlevel1; float lightlevel2; float fr, fg, fb; float fr2, fg2, fb2; long ir, ig, ib; long absr, absg, absb; short col, col2; short findcol; unsigned long lowest; unsigned char bestfit; unsigned long coldif; lightlevel1 = 0.5; /* Percent of color 1 */ lightlevel2 = 0.5; /* Percent of color 2 */ /* Lightlevel1 and lightlevel2 must total to 1 */ /* Transparency is created by taking two colors, multiplying the RGB values by a percentage, and adding the RGB values together. The new color will contain a little bit of each oringal color. */ /* For each of the 256 colors, we can mix with any other color, therefore we need a 256x256 table. */ wtextcolor (15); wtexttransparent (TEXTFGBG); wgtprintf (0, 0, NULL, "Making transparency table...", col2); for (col2 = 0; col2 < 256; col2++) { for (col = 0; col < 256; col++) { fr = (float)pal[col].r * lightlevel1; fg = (float)pal[col].g * lightlevel1; fb = (float)pal[col].b * lightlevel1; fr2= (float)pal[col2].r * lightlevel2; fg2= (float)pal[col2].g * lightlevel2; fb2= (float)pal[col2].b * lightlevel2; ir = (fr + fr2); ig = (fg + fg2); ib = (fb + fb2); lowest = 655350; for (findcol = 0; findcol < 256; findcol++) { absr = abs ( (long)pal[findcol].r - ir) * 30; absg = abs ( (long)pal[findcol].g - ig) * 59; absb = abs ( (long)pal[findcol].b - ib) * 11; coldif = sqrt(absr*absr + absg*absg + absb*absb); if (coldif < lowest) { lowest = coldif; bestfit = findcol; } } transparency_table[col2 * 256L + col] = bestfit; } wgtprintf (0, 8, NULL, "Color %03hi", col2); } } void animation_timer (void) { animation_count++; } int load_table (char *filename, block table, int size) { FILE *in; in = fopen (filename, "rb"); if (in == NULL) return 0; fread (table, size, 1, in); fclose (in); return 1; } void save_table (char *filename, block table, int size) { FILE *out; out = fopen (filename, "wb"); fwrite (table, size, 1, out); fclose (out); } void main (void) { oldmode = wgetmode (); if (!vgadetected ()) { printf ("VGA is required to run this program..."); exit (1); } printf ("WGT Example #68d\n\n"); printf ("This example adds timer controlled animation.\n"); printf ("\nPress any key to begin.\n"); getch (); vga256 (); load_graphics (); init_lines (); /* Set the position of the running man */ people[0].x = 120; people[0].y = 50; people[0].anm = 0; wcreate_shadow_table (pal); if (!load_table ("trans.dat", transparency_table, 65536)) { wcreate_transparency_table (pal); save_table ("trans.dat", transparency_table, 65536); } animation_count = 0; winittimer (); wstarttimer (animation_timer, TICKS (20)); do { wsetscreen (work); movement_multiplier = animation_count; if (movement_multiplier > 0) { animation_count = 0; animate_lines (); animate_man (); wnormscreen (); wputblock (0, 0, work, 0); } } while (!kbhit ()); wstoptimer (); wdonetimer (); free_graphics (); wsetmode (oldmode); }