rpi4-osdev/part12-wgt/samples/wgt20.c
2021-03-25 09:20:48 +00:00

469 lines
10 KiB
C

#include "include/wgtspr.h"
#include "include/mem.h"
#include "include/multicore.h"
// ######## REQUIRED FUNCTIONS ########
unsigned long state0 = 1000;
unsigned long state1 = 2000;
unsigned long rand(void)
{
unsigned long s1 = state0;
unsigned long s0 = state1;
state0 = s0;
s1 ^= s1 << 23;
s1 ^= s1 >> 17;
s1 ^= s0;
s1 ^= s0 >> 26;
state1 = s1;
return state0 + state1;
}
// ######## STUB FUNCTIONS ########
unsigned int kb = 0;
unsigned int kbhit(void) {
kb++;
return kb / 500;
}
void getch(void) {
wait_msec(0x500000);
kb = 0;
}
// ######## WGT EXAMPLES ########
/* Large example demonstrating many functions from WGT */
#define MAXEXPLOS 220
#define MAXALIEN 170
void scrolldown (void); /* scrolls the screen down */
void credits (void);
void changepalette256 (void);
void colorloop (void);
void play (void);
block scr, scr2;
block sprites[21];
typedef struct {
int x, y;
int dirx, diry;
int shootx, shooty;
int power;
} spaceship;
typedef struct {
int x, y;
int num;
} explosion;
explosion explos[MAXEXPLOS];
spaceship aliens[MAXALIEN];
int numaliens, aliensleft;
int shoot[10], sx[10], sy[10];
int ship; /* Sprite to show */
int shipx[MAXALIEN], shipy[MAXALIEN]; /* Ship coordinates */
float incx, incy, yourx, youry;
int cd;
int i, j, k; /* Loop control */
int scrll = 1; /* scrll is a counter for the scroll offset */
int ix = 30, iy = 0, ix2 = 251, iy2 = 199; /* coords of scrolling area */
int speed; /* the scrolling speed */
/* try changing speed and sign */
int nextlevel; /* Performing level change = 1 */
int leveltextx; /* X coordinate of next level text */
int level;
color palette[256];
void strrev(char *str)
{
int i;
int j;
unsigned char a;
unsigned len = strlen((const char *)str);
for (i = 0, j = len - 1; i < j; i++, j--) {
a = str[i];
str[i] = str[j];
str[j] = a;
}
}
int itoa(int num, char* str, int base)
{
int sum = num;
int i = 0;
int digit;
do {
digit = sum % base;
if (digit < 0xA) str[i++] = '0' + digit;
else str[i++] = 'A' + digit - 0xA;
sum /= base;
} while (sum);
str[i] = '\0';
strrev(str);
return 0;
}
void initialize_aliens (int numaliens)
/* Sets the initial positions of the aliens when starting a level. */
{
int i;
for (i = 0; i < numaliens; i++)
{
aliens[i].x = rand() % 200 + 30;
aliens[i].y = rand() % 50;
aliens[i].dirx = rand() % 8 - 4;
aliens[i].diry = rand() % 8 - 4;
aliens[i].power = numaliens / 3;
aliens[i].shootx = -1;
}
}
void make_starfield (void)
/* Gets two virtual screens and puts the star sprites on them to make
a starfield background. */
{
int i;
scr = wnewblock (0, 0, 319, 199); /* get two virtual screens */
scr2 = wnewblock (0, 0, 319, 199);
wsetscreen (scr2); /* go to second one */
wcls (vgapal[0]); /* clear it */
for (i = 1; i < 300; i++)
wputblock (rand() % 320, rand() % 200, sprites[5], 0);
/* sprite[5] is small stars */
for (i = 1; i < 5; i++)
wputblock (rand() % 320, rand() % 200, sprites[6], 0);
/* sprite[6] is a large star */
}
void play (void)
{
scrolldown (); /* Scroll the second
screen by copying it to
a different offset on
screen one. */
if (but == 1)
{ /* if you clicked the mouse */
for (i = 0; i <9; i++)
if (shoot[i] == 0) /* check to see if slot available */
{
shoot[i] = 1; /* make it unavailable */
sx[i] = yourx + 9; /* set coords for shot */
sy[i] = youry - 7;
break;
}
}
for (i = 0; i < 9; i++) /* if shot is active */
{
if (shoot[i] == 1) /* then show the sprite */
{
wputblock (sx[i], sy[i], sprites[4], 0); /* at the right coords */
sy[i] -= 8; /* make it go up */
if (sy[i] < 1) /* if it is at top, */
shoot[i] = 0; /* make it available again */
/* Now check to see if it hit an alien by seeing if their
rectangular regions overlap. */
for (j = 0; j < numaliens; j++)
if ((aliens[j].x != -255) &&
(sx[i] > aliens[j].x) && (sx[i] < aliens[j].x + 25) &&
(sy[i] > aliens[j].y) && (sy[i] < aliens[j].y + 20))
{
shoot[i] = 0; /* Turn off that missile */
aliens[j].power--;
if (aliens[j].power == 0)
{
aliensleft--;
if (aliensleft == 0)
{
nextlevel = 1;
leveltextx = ix2 + 100;
}
for (k = 0; k < MAXEXPLOS; k++) /* Add an explosion */
{
if (explos[k].num == 0)
{
explos[k].x = aliens[j].x;
explos[k].y = aliens[j].y;
explos[k].num = 8;
break;
}
}
aliens[j].x = -255;
}
} /* Collision */
} /* Shot active */
} /* for loop */
incx = (float)(mx - yourx) / 5.0; /* Move your spaceship according to the */
incy = (float)(my - youry) / 5.0; /* position of the mouse. */
yourx += incx;
youry += incy;
/* Tilt the ship */
if ((incx < 2) && (incx > -2))
ship = 2;
else if (incx > 5)
ship=3;
else if (incx < 5)
ship = 1;
wsetscreen (scr);
wputblock (yourx, youry, sprites[ship], 1); /* Put your ship on */
for (i = 0; i < numaliens; i++)
{
if (aliens[i].x != -255) /* Alien is still alive */
{
aliens[i].x += aliens[i].dirx; /* Make them move */
aliens[i].y += aliens[i].diry;
/* Make them bounce off the walls if they go too far in one direction. */
if (aliens[i].x <= ix)
aliens[i].dirx = rand() % 4;
else if (aliens[i].x > ix2 - 20)
aliens[i].dirx = -(rand() % 4);
if (aliens[i].y < 0)
aliens[i].diry = rand() % 4;
else if (aliens[i].y > 150)
aliens[i].diry = -(rand() % 4);
if ((aliens[i].shootx == -1) && (rand() % 10 == 1))
/* 1 in 10 chance of shooting */
{
aliens[i].shootx = aliens[i].x + 9;
aliens[i].shooty = aliens[i].y + 5;
}
if (aliens[i].power > 0)
wputblock (aliens[i].x, aliens[i].y, sprites[7], 1);
/* Display the alien's missile. */
if (aliens[i].shootx != -1)
{
wputblock (aliens[i].shootx, aliens[i].shooty, sprites[8], 1);
aliens[i].shooty += 4;
if (aliens[i].shooty > 199)
aliens[i].shootx = -1;
}
}
}
/* Now draw any explosions on the screen. */
for (i = 0; i < MAXEXPLOS; i++)
{
if (explos[i].num > 0)
{
explos[i].num++;
if (explos[i].num > 14)
explos[i].num = 0;
else
wputblock (explos[i].x, explos[i].y, sprites[explos[i].num], 1);
}
}
if (nextlevel == 1)
{
leveltextx -= 5;
wouttextxy (leveltextx, 50, NULL, "LEVEL ");
char levelstr[10];
itoa(level + 1, levelstr, 10);
wouttextxy (leveltextx + (6 * 8), 50, NULL, levelstr);
if (leveltextx < -100)
{
level++;
if (level > MAXALIEN)
level = MAXALIEN;
numaliens = level + 5;
aliensleft = numaliens;
initialize_aliens (numaliens);
nextlevel = 0;
}
}
wait_msec(0x3E9F);
wcopyscreen (ix, iy, ix2, iy2, scr, ix, iy, NULL);
/* copy the first screen */
/* to the base screen */
}
void scrolldown (void)
{
wcopyscreen (ix, scrll, ix2, iy2, scr2, ix, iy, scr);
wcopyscreen (ix, iy, ix2, scrll, scr2, ix, iy2 - scrll, scr);
/* Cut the screen into two sections, then swap them vertically on the
destination page */
scrll += speed;
if ((scrll < iy) && (speed < 0))
scrll = iy2 + 1 - abs (scrll);
if ((scrll > iy2) && (speed > 0))
scrll = abs (iy2 - scrll);
}
void credits (void)
{
wnormscreen ();
wtextcolor (vgapal[1]);
wtextbackground (vgapal[0]);
cd = 2;
/* draw a pattern on the screen */
for (i = 0; i < 320; i++)
{
colorloop ();
wsetcolor (vgapal[cd]);
wfline (160, 100, i, 0);
}
for (i = 0; i < 200; i++)
{
colorloop ();
wsetcolor (vgapal[cd]);
wfline (160, 100, 319, i);
}
for (i = 319; i >= 0; i--)
{
colorloop ();
wsetcolor (vgapal[cd]);
wfline (160, 100, i, 199);
}
for (i = 199; i >= 0; i--)
{
colorloop ();
wsetcolor (vgapal[cd]);
wfline (160, 100, 0, i);
}
changepalette256 ();
wouttextxy (50, 20, NULL, "Shoot 'Em Up Sprite Example");
wouttextxy (50, 28, NULL, "Showing what YOU could do with");
wouttextxy (50, 36, NULL, "the WordUp Graphics Toolkit!");
wouttextxy (50, 44, NULL, "Use the mouse to move");
wouttextxy (50, 52, NULL, "Left button shoots");
wouttextxy (50, 60, NULL, "Right button quits");
wouttextxy (50, 68, NULL, "Right button to start");
wsetrgb (1, 63, 63, 63, palette);
// wfade_in (0, 255, 1, palette);
do {
/*
wcolrotate (2, 106, 0, palette);
wsetpalette (2, 106, palette);
*/
wait_msec(0x3E9F);
} while (!but);
noclick();
wcls (vgapal[0]);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* change the palette to the right colours */
void changepalette256 (void)
{
wsetrgb (0, 0, 0, 0, palette);
for (i = 2; i < 54; i++)
wsetrgb (i, i, 0, 0, palette);
for (i = 54; i < 106; i++)
wsetrgb (i, 105 - i, 0, 0, palette);
wsetrgb (253, 60, 60, 60, palette);
wsetrgb (254, 45, 45, 45, palette);
wsetrgb (255, 30, 30, 30, palette);
wsetrgb (1, 63, 63, 63, palette);
}
void colorloop (void)
/* Simple loop for colours on credit screen */
{
cd++;
if (cd > 105)
cd = 2;
}
void wgt20()
{
set_clock_rate(get_max_clock());
mem_init();
vga256 (); /* Initializes WGT system */
start_core2(minit); // Start the comms engine (core 2)
while (!comms_up); // Wait for comms up
credits ();
extern unsigned char _binary_bin_space_spr_start[];
wloadsprites (palette, &_binary_bin_space_spr_start[0], sprites, 0, 20);
/* load first 10 sprites */
wsetpalette (0, 255, palette);
make_starfield ();
wnormscreen (); /* go back to normal screen */
wcls (vgapal[0]); /* clear it */
wbutt (0, 0, 29, 199); /* make some side panels */
wbutt (252, 0, 319, 199);
wtextbackground (vgapal[0]);
wtextcolor (vgapal[1]);
wtexttransparent (TEXTFG);
yourx = 128;
youry = 170;
wsetscreen (scr); /* go to first screen */
msetbounds (ix, 150, ix2 - 20, 179);
speed = -4;
nextlevel = 0;
level = 1;
numaliens = level + 5;
aliensleft = numaliens;
initialize_aliens (numaliens);
do {
play ();
} while (but != 2); /* until right button is pressed */
mdeinit (); /* Deinitialize the mouse handler */
wfreeblock (scr);
wfreeblock (scr2);
wfreesprites (sprites, 0, 20);
wnormscreen();
wcls(vgapal[0]);
}
void main()
{
wgt20();
while (1);
}