/* * Kenneth Todd Voelker * Section BI * CSE142, Spring 2000 * Homework 4 * Idyllic landscape animation * * */ #include "gp142.h" #include #include #include /******************* CONSTANTS!!! ************************/ /* Logical constants */ #define TRUE 1 #define FALSE 0 /* * For many of the GP142 functions, a line width of * zero means to fill the shape being drawn. The * constant FILL is used in function calls when a solid * shape is desired. */ #define FILL 0 /******** Menu buttons: ********/ /* Top-left coordinates of button palette */ #define MENU_TOP (-60) #define MENU_LEFT (-50) /* Height and width of buttons in pixels */ #define BUTTON_HEIGHT 25 #define BUTTON_WIDTH 125 /* Number of buttons */ #define NUM_BUTTONS 4 /* Mouse click in some button */ #define BUTTON_CLICK 1 /* Mouse click elsewhere */ #define OTHER_CLICK 0 /********** ANIMATION CONSTANTS *********/ /* Left, right, up and down */ #define LEFT -1 #define RIGHT 1 #define UP 1 #define DOWN -1 /* speed of objects */ #define BUG_SPEED 20 #define MAX_BBUGS_SPEED 50 /* sizes and quantities */ #define MAX_BBUGS_NUM 10 #define MIN_BBUGS_NUM 0 #define MAX_BUG_SIZE 10 /*********** OTHER DRAWING CONSTANTS ***************/ /* y-coordinate of the top of the ground in the landscape */ #define HORIZON (- 2 * (GP142_YMAX / 10)) /* Other constants pertaining to objects in the scene */ #define MOON_RADIUS 20 #define MOON_FULLNESS 2.5 #define MAX_STAR_RADIUS 4 /***************************************************************************** FUNCTION PROTOTYPES *****************************************************************************/ /***********************************************/ /**** INITIALIZATION PROCEDURES ****/ /**** init_moon ****/ /* Initializes the moon parameters */ void init_moon(int *moon_x, int *moon_y); /*********************************************** /**** DRAW THINGS! **** /**** draw_instructions **** /**** change_colors **** /**** draw_bug **** /**** draw_bbugs **** /**** draw_boat **** /**** draw_landscape ****/ /* Draw the instructions & new game box */ void draw_instructions(int bbugs_num, int bbugs_speed); /* Change flower field colors */ void change_colors(int *petal_color, int *flower_color); /* Draw a single bug (buttefly) */ void draw_bug(int bug_x, int bug_y, int bug_size); /* Draw the bad bugs */ void draw_bbugs(int bbugs_x, int bbugs_y, int bbugs_size); /* Draw a single boat */ void draw_boat(int boat_x, int boat_y, int boat_len, int boat_mast); /* Draw the background, including the moon at coordinates moon_x and moon_y, the stars */ /* the tree, the flower(s), the boat, and the bug(s) */ void draw_landscape(int moon_x, int moon_y, int star_x, int star_y, int star_radius, int star_color, int star2_x, int star2_y, int star2_radius, int star2_color, int flower_x, int flower_y, int flower_radius, int flower_color, int petal_radius, int petal_color, int boat_x, int boat_y, int boat_len, int boat_mast, int bug_x, int bug_y, int bug_size, int max_bug_size, int bbugs_x[], int bbugs_y[], int bbugs_size[], int *bbugs_num); /******************************************* **** BUTTONS AND MOUSE CLICKS **** **** draw_buttons **** **** classify_button_click **** **** handle_button ****/ /* Draw buttons */ void draw_buttons(void); /* Return kind of mouse click (in a button, etc.) */ int classify_mouse_click(int mouse_x, int mouse_y); /* Process button click at location x, y. React appropriately, depending on the requested event */ void handle_button(int x, int y, int *bbugs_speed, int *bbugs_num); /*********************************************** **** ANIMATED OBJECTS : NON-BUGS **** **** blink_star **** **** move_moon ****/ /* Make stars blink */ void blink_star(int *star_radius, int *star_color); /* Update moon coordinates moon_x, moon_y for one tick */ void move_moon(int *moon_x, int *moon_y); /******************************************* **** ANIMATED OBJECTS : BUGS **** **** move_bug **** **** move_bbugs **** **** bug_direction **** **** bbugs_direction **** **** bug_collision ****/ /* Move good bug */ void move_bug(int *bug_x, int *bug_y, int *bug_size, int bug_speedx, int bug_speedy, int max_bug_size); /* Move bad bugs, one at a time */ void move_bbugs(int *bbugs_x, int *bbugs_y, int *bbugs_size, int *u_or_d, int *l_or_r, int bbugs_speed); /* change the direction of the bug upon pressing a proper key */ void bug_direction (char key_pressed, int *bug_speedx, int *bug_speedy); /* change the direction of the bug, 1 in every four go a different direction */ void bbugs_direction (int num_mod, int *up_or_down, int *left_or_right); /* Check for bug collisions, return 1 if bug dies */ int bug_collision(int bug_x, int bug_y, int bug_size, int bbugs_x, int bbugs_y, int bbugs_size); /*********************************************** **** OTHER **** **** initialize_random_numbers **** **** something_is_wrong ****/ /* Display error message if internal error is detected. */ void something_is_wrong (void); /* Initialize random number generator. [Ignore or */ /* remove if your program doesn't use random numbers.] */ void initialize_random_numbers(); /***************************************************************************** MAIN : initialize variables set initial conditions draw it once go into loop (terminated by pressing quit) go into instructions loop (terminated by instructions_quit or normal quit) give instructions, allow setting of number of enemies go into event loop (terminated by new_game or normal quit) move things, eat bugs, etc. close everything up end. *****************************************************************************/ int main(void) { /************* INITIALIZE VARIABLES ******************/ /* Event handling and buttons: */ int quit, instructions_quit, game_quit; /* = "user has selected quit" */ int event; /* the most recent GP142 event */ char key_pressed; /* last keyboard character from key event */ int mouse_x, mouse_y; /* x and y coordinates of latest mouse event*/ int click_kind; /* kind of mouse click (button, etc.) */ /* Information about the moon and stars: */ int moon_x, moon_y; /* screen x and y coordinates */ int star_x, star_y; /* screen x and y coordinates */ int star_radius, star_color; /* radius and color of a star */ int star2_x, star2_y; /* screen x and y coordinates */ int star2_radius, star2_color; /* radius and color of another star */ /* Information about the flowers */ int flower_x, flower_y; /* screen x and y coordinates */ int flower_radius, petal_radius; /* flower and petal radii */ int flower_color, petal_color; /* flower and petal colors */ /* Information about the boat */ int boat_x, boat_y; /* screen x and y coordinates */ int boat_len, boat_mast; /* length of the boat and height of the mast */ /* Information about the bug */ int bug_x, bug_y, bug_size, bug_speedx = 0, bug_speedy = 0, max_bug_size = 10; /* screen x and y coordinates and size of the bug */ /* Information about the bad bugs */ int bbugs_num = 5; int bbugs_x[MAX_BBUGS_NUM], bbugs_y[MAX_BBUGS_NUM], bbugs_size[MAX_BBUGS_NUM], bbugs_move[MAX_BBUGS_NUM]; int bbugs_speed = 10; int count; /* for drawing the bad bugs */ int num_mod, up_or_down, left_or_right; /* to determine if a collision has happened or not */ int collide; /* how many bad bugs are alive? */ int alive_bbugs; /************** SET INITIAL CONDITIONS *******************/ /* Initialize random number generator */ initialize_random_numbers(); /* Initialize graphics package, clear the window, */ /* turn logging off, and start animation. */ GP142_open(); GP142_logging(LOG_OFF); GP142_clear(); GP142_animate(ANI_RUN); /* set initial location of the moon */ init_moon(&moon_x, &moon_y); /* set initial location of the stars */ star_x = GP142_XMAX - 100; star_y = GP142_YMAX - 90; star_radius = 3; star_color = WHITE; star2_x = -GP142_XMAX + 150; star2_y = GP142_YMAX - 80; star2_radius = 2; star2_color = YELLOW; /* set initial flower parameters */ flower_x = GP142_XMAX / 3; flower_y = -GP142_YMAX + 40; flower_radius = 2; flower_color = YELLOW; petal_radius = 8; petal_color = RED; /* set initial conditions for the boat */ boat_x = GP142_XMAX / 3 - 20; boat_y = HORIZON - 25; boat_len = 25; boat_mast = 40; /* set initial conditions for the buttefly */ bug_x = 1000; bug_y = 1000; bug_size = max_bug_size/2; /* set initial conditions for the bad butterflies */ for (count = 0; count < MAX_BBUGS_NUM; count++) { bbugs_x[count] = 1000; bbugs_y[count] = 1000; bbugs_size[count] = max_bug_size/2; bbugs_move[count] = TRUE; } /********** Draw initial landscape, buttons, and traffic *************/ draw_landscape(moon_x,moon_y, star_x, star_y, star_radius, star_color, star2_x, star2_y, star2_radius, star2_color, flower_x, flower_y, flower_radius, flower_color, petal_radius, petal_color, boat_x, boat_y, boat_len, boat_mast, bug_x, bug_y, bug_size, max_bug_size, bbugs_x, bbugs_y, bbugs_size, &bbugs_num); draw_buttons(); /* * Main event loop: * ---- ----- ----- * Wait for the next user action, decode it, and call an * appropriate function to handle it. Repeat until the * user selects quit. */ quit = FALSE; while (!quit) { /* * Instructions Event Loop */ instructions_quit = FALSE; while(!quit && !instructions_quit) { draw_instructions(bbugs_num, bbugs_speed); draw_buttons(); /* get next event */ event = GP142_await_event(&mouse_x, &mouse_y, &key_pressed); /* perform appropriate action depending on kind of event */ switch (event) { case GP142_QUIT: /* Quit selected */ quit = TRUE; break; case GP142_KBD: if (key_pressed == 'N' || key_pressed == 'n') instructions_quit = TRUE; break; case GP142_MOUSE: click_kind = classify_mouse_click(mouse_x, mouse_y); if (click_kind == BUTTON_CLICK) { handle_button(mouse_x, mouse_y, &bbugs_speed, &bbugs_num); } break; case GP142_PERIODIC: break; default: break; } /* end of switch statement */ } /***********************/ /* End of Instructions */ /***********************/ /* set the bad bugs back to normal */ for (count = 0; count < MAX_BBUGS_NUM; count++) { bbugs_x[count] = -GP142_XMAX + (rand() % (GP142_XMAX * 2)); bbugs_y[count] = -GP142_YMAX + (rand() % (GP142_YMAX * 2)); bbugs_size[count] = max_bug_size/2; bbugs_move[count] = TRUE; } /* set initial conditions for the buttefly */ bug_x = flower_x + 20; bug_y = flower_y + 30; bug_speedx = 0; bug_speedy = 0; max_bug_size = 10; bug_size = max_bug_size/2; /******************* * Game Event Loop * *******************/ alive_bbugs = bbugs_num; game_quit = FALSE; while(!quit && !game_quit) { /* get next event */ event = GP142_await_event(&mouse_x, &mouse_y, &key_pressed); switch (event) { /******************************/ /* If quit is selected, quit! */ case GP142_QUIT: quit = TRUE; break; /*********************************/ /* When key is pressed, move bug */ case GP142_KBD: bug_direction (key_pressed, &bug_speedx, &bug_speedy); break; /***********************************/ /* If mouse clicks a button, react */ case GP142_MOUSE: break; /*************************************************/ /* Animations: moon, stars, good bug and bad bug */ case GP142_PERIODIC: move_moon(&moon_x, &moon_y); blink_star(&star_radius, &star_color); blink_star(&star2_radius, &star2_color); move_bug(&bug_x, &bug_y, &bug_size, bug_speedx, bug_speedy, max_bug_size); /* move the bad bugs */ for (count = 0; count <= bbugs_num; count++){ num_mod = count % 4; /* every four go a different direction. */ bbugs_direction (num_mod, &up_or_down, &left_or_right); if (bbugs_move[count] == TRUE) move_bbugs(&bbugs_x[count], &bbugs_y[count], &bbugs_size[count], &up_or_down, &left_or_right, bbugs_speed); } /* stop moving the bad bugs */ break; /************************/ /* Nothing has happened */ default: break; } /*end Event Switch */ /* Redraw everything */ draw_landscape(moon_x, moon_y, star_x, star_y, star_radius, star_color, star2_x, star2_y, star2_radius, star2_color, flower_x, flower_y, flower_radius, flower_color, petal_radius, petal_color, boat_x, boat_y, boat_len, boat_mast, bug_x, bug_y, bug_size, max_bug_size, bbugs_x, bbugs_y, bbugs_size, &bbugs_num); /* Check for Bug Collisions */ for (count = 0; count <= bbugs_num; count++) { collide = FALSE; collide = bug_collision (bug_x, bug_y, bug_size, bbugs_x[count], bbugs_y[count], bbugs_size[count]); /* Bug Killer Loop */ if (collide == TRUE) { bbugs_move[count] = FALSE; /* stop the movement */ bbugs_x[count] = 1000; /* move it far off screen */ bbugs_y[count] = 1000; max_bug_size = max_bug_size + 3; /* grow the bug as it eats */ alive_bbugs = alive_bbugs - 1; } /* end Bug Killer Loop */ /* Check to see if all the bad bugs are dead */ if (alive_bbugs == -1) { game_quit = TRUE; instructions_quit = FALSE; bbugs_num = 5; bbugs_speed = 10; } } /* end Check for Bug Collisions */ } /******************** * End of Game Loop * ********************/ } /******************** * End of Main Loop * ********************/ /* Termination: shut down graphics window and exit */ GP142_close(); return 0; } /* end main */ /***************************************************************************** INITIALIZATION PROCEDURES init_moon *****************************************************************************/ /************ Initializes the moon parameters **************/ void init_moon(int *moon_x, int *moon_y) { *moon_x = GP142_XMAX - 50; *moon_y = GP142_YMAX - 35; } /***************************************************************************** DRAW THINGS! draw_instructions change_colors draw_bug draw_bbugs draw_boat draw_landscape *****************************************************************************/ /* Draw instructions */ void draw_instructions(int bbugs_num, int bbugs_speed) { GP142_rectangleXY(WHITE, -250, -180, 250, 150, FILL); GP142_printfXY(BLACK, -65, 110, 26, "Butterfly Game!"); GP142_printfXY(BLACK, -200, 80, 20, "Here's how to play:"); GP142_printfXY(BLACK, -180, 60, 14, "Fly your butterfly around the screen using the numerical keypad."); GP142_printfXY(BLACK, -180, 40, 14, "(Use 8 to fly up, 4 to fly left, 7 to fly diagonally.)"); GP142_printfXY(BLACK, -180, 20, 14, "Every time that you can catch one of the black butterflies,"); GP142_printfXY(BLACK, -180, 0, 14, "you eat it, and then grow bigger!"); GP142_printfXY(BLACK, -180, -20, 14, "Try to catch them all!"); GP142_printfXY(BLACK, -100, -50, 20, "Press N for a new game"); GP142_printfXY(BLACK, 90, -75, 12, "Current speed:"); GP142_printfXY(BLACK, 90, -90, 12, "%d", bbugs_speed); GP142_printfXY(BLACK, 90, -115, 12, "Current number of enemies:"); GP142_printfXY(BLACK, 90, -130, 12, "%d", bbugs_num + 1); } /* Change flower field colors */ void change_colors(int *petal_color, int *flower_color) { *petal_color = (*petal_color + 1) % MAX_COLORS; *flower_color = (*flower_color + 1) % MAX_COLORS; } /* Draw a single bug (butterfly) of a given size at given screen x and y coordinates */ void draw_bug(int bug_x, int bug_y, int bug_size) { GP142_triangleXY(MAGENTA, bug_x, bug_y, bug_x - bug_size, bug_y + bug_size, bug_x - bug_size, bug_y - bug_size, FILL); GP142_triangleXY(MAGENTA, bug_x, bug_y, bug_x + bug_size, bug_y + bug_size, bug_x + bug_size, bug_y - bug_size, FILL); GP142_lineXY(BLACK, bug_x, bug_y, bug_x - bug_size / 3, bug_y + bug_size / 2, 2); GP142_lineXY(BLACK, bug_x, bug_y, bug_x + bug_size / 3, bug_y + bug_size / 2, 2); } void draw_bbugs(int bbugs_x, int bbugs_y, int bbugs_size) { GP142_triangleXY(BLACK, bbugs_x, bbugs_y, bbugs_x - bbugs_size, bbugs_y + bbugs_size, bbugs_x - bbugs_size, bbugs_y - bbugs_size, FILL); GP142_triangleXY(BLACK, bbugs_x, bbugs_y, bbugs_x + bbugs_size, bbugs_y + bbugs_size, bbugs_x + bbugs_size, bbugs_y - bbugs_size, FILL); GP142_lineXY(BLACK, bbugs_x, bbugs_y, bbugs_x - 3, bbugs_y + 7, 2); GP142_lineXY(BLACK, bbugs_x, bbugs_y, bbugs_x + 3, bbugs_y + 7, 2); } /* Draw a boat at horizontal and vertical positions x and y and of the given length */ /* and mast height */ void draw_boat(int boat_x, int boat_y, int boat_len, int boat_mast) { GP142_rectangleXY(BLACK, boat_x - boat_len, boat_y, boat_x + boat_len, boat_y - 4, FILL); GP142_triangleXY(CYAN, boat_x, boat_y, boat_x, boat_y + boat_mast, boat_x + boat_mast, boat_y + 2 * boat_mast / 3, FILL); } /******** Draw the background, ********/ /*********including the moon at coordinates moon_x and moon_y and stars ********/ void draw_landscape(int moon_x, int moon_y, int star_x, int star_y, int star_radius, int star_color, int star2_x, int star2_y, int star2_radius, int star2_color, int flower_x, int flower_y, int flower_radius, int flower_color, int petal_radius, int petal_color, int boat_x, int boat_y, int boat_len, int boat_mast, int bug_x, int bug_y, int bug_size, int max_bug_size, int bbugs_x[], int bbugs_y[], int bbugs_size[], int *bbugs_num) { int text_offset = -GP142_XMAX + 15; /* horizontal offset of text */ int text_size = 12; /* size of text font */ int num; /* Draw the sky */ GP142_rectangleXY(DUSTY_PLUM, -GP142_XMAX, -GP142_YMAX, GP142_XMAX, GP142_YMAX, FILL); /* Draw the moon */ GP142_circleXY(WHITE, moon_x, moon_y, MOON_RADIUS); GP142_ovalXY(DUSTY_PLUM, moon_x, moon_y - MOON_RADIUS, moon_x + (int)(MOON_FULLNESS * MOON_RADIUS), moon_y + MOON_RADIUS, FILL); /* Draw stars */ GP142_triangleXY(star_color, star_x, star_y + star_radius, star_x + (int)(star_radius * 0.87), star_y - (int) (star_radius / 2.0), star_x - (int)(star_radius * 0.87), star_y - (int) (star_radius / 2.0), FILL); GP142_triangleXY(star_color, star_x, star_y - star_radius, star_x - (int)(star_radius * 0.87), star_y + (int) (star_radius / 2.0), star_x + (int)(star_radius * 0.87), star_y + (int) (star_radius / 2.0), FILL); GP142_triangleXY(star2_color, star2_x, star2_y + star2_radius, star2_x + (int)(star2_radius * 0.87), star2_y - (int) (star2_radius / 2.0), star2_x - (int)(star2_radius * 0.87), star2_y - (int) (star2_radius / 2.0), FILL); GP142_triangleXY(star2_color, star2_x, star2_y - star2_radius, star2_x - (int)(star2_radius * 0.87), star2_y + (int) (star2_radius / 2.0), star2_x + (int)(star2_radius * 0.87), star2_y + (int) (star2_radius / 2.0), FILL); /* Draw mountains */ GP142_triangleXY(LT_GRAY, -GP142_XMAX, HORIZON, GP142_XMAX, HORIZON, -GP142_XMAX / 8, (5 * GP142_YMAX)/6, FILL); GP142_triangleXY(MED_GRAY, -GP142_XMAX, HORIZON, GP142_XMAX, HORIZON, -GP142_XMAX / 3, (3 * GP142_YMAX)/4, FILL); GP142_triangleXY(BROWN, -GP142_XMAX, HORIZON, GP142_XMAX, HORIZON, GP142_XMAX / 4, (2 * GP142_YMAX)/3, FILL); GP142_triangleXY(OLIVE, -( 5 * GP142_XMAX/4), HORIZON, (GP142_XMAX)/3 , HORIZON, -(3 * GP142_XMAX)/4, (2 * GP142_YMAX)/3 , FILL); GP142_triangleXY(FOREST_GREEN, -GP142_XMAX / 3 , HORIZON, GP142_XMAX, HORIZON, GP142_XMAX, (2 * GP142_YMAX)/3 , FILL); /* Draw meadow */ GP142_rectangleXY(SEA_GREEN, -GP142_XMAX, -GP142_YMAX, GP142_XMAX, HORIZON, FILL); /* Draw lake */ GP142_ovalXY(BLUE, -GP142_XMAX - 100, HORIZON, GP142_XMAX / 3, HORIZON - 50, FILL); /* Draw flower */ GP142_circleXY(petal_color, flower_x, flower_y, petal_radius); GP142_circleXY(flower_color, flower_x, flower_y, flower_radius); GP142_lineXY(FOREST_GREEN, flower_x, flower_y - petal_radius, flower_x, flower_y - petal_radius - 15, 2); GP142_lineXY(FOREST_GREEN, flower_x, flower_y - petal_radius - 10, flower_x + 5, flower_y - petal_radius - 3, 2); /* Draw tree */ GP142_rectangleXY(BROWN, -GP142_XMAX + 50, -GP142_YMAX + 50, -GP142_XMAX + 60, -GP142_YMAX + 100, FILL); GP142_circleXY(FOREST_GREEN, -GP142_XMAX + 55, -GP142_YMAX + 110, 30); /* Draw boat */ draw_boat(boat_x, boat_y, boat_len, boat_mast); /* Draw buttefly */ draw_bug(bug_x, bug_y, bug_size); /* Draw the bad bugs */ for (num = 0; num <= *bbugs_num; num++) { draw_bbugs(bbugs_x[num], bbugs_y[num], bbugs_size[num]); } } /*end draw_landscape */ /***************************************************************************** BUTTONS AND MOUSE CLICKS draw_buttons classify_button_click handle_button *****************************************************************************/ /***************** Draws the buttons *****************/ void draw_buttons(void) { int i; int text_offset = MENU_LEFT+10; /* offset of button text in button */ int font_size = 12; /* size of button text */ /* draw rectangles for each button */ for(i = 0; i < NUM_BUTTONS; i++) { GP142_rectangleXY(BLACK, MENU_LEFT, MENU_TOP - i * BUTTON_HEIGHT, MENU_LEFT + BUTTON_WIDTH, MENU_TOP - (i + 1) * BUTTON_HEIGHT, 1); } /* display button text */ i = MENU_TOP - (BUTTON_HEIGHT/2) - (font_size/2); GP142_printfXY(BLACK, text_offset, i, font_size, "Speed Up Enemies"); i -= BUTTON_HEIGHT; GP142_printfXY(BLACK, text_offset, i, font_size, "Slow Down Enemies"); i -= BUTTON_HEIGHT; GP142_printfXY(BLACK, text_offset, i, font_size, "Add a Bug"); i -= BUTTON_HEIGHT; GP142_printfXY(BLACK, text_offset, i, font_size, "Subtract a Bug"); } /********** Classify mouse click at (mouse_x,mouse_y) and return kind *********/ int classify_mouse_click(int mouse_x, int mouse_y) { if ((mouse_x > MENU_LEFT) && (mouse_x < MENU_LEFT + BUTTON_WIDTH) && (mouse_y < MENU_TOP) && (mouse_y > (MENU_TOP - NUM_BUTTONS * BUTTON_HEIGHT))) return BUTTON_CLICK; else return OTHER_CLICK; } /******************* CHECK FOR BUTTON PRESS ********************/ void handle_button(int x, int y, int *bbugs_speed, int *bbugs_num) { int buttonNum; /* number of selected button */ /* Complain if x coordinate couldn't be inside a button */ if (x < MENU_LEFT || x > MENU_LEFT + BUTTON_WIDTH) { something_is_wrong(); return; } /* Convert y coordinate to button number from top. */ buttonNum = (MENU_TOP - y)/BUTTON_HEIGHT; switch(buttonNum) { case 0: /* speed up enemies */ if (*bbugs_speed < MAX_BBUGS_SPEED) *bbugs_speed = *bbugs_speed + 2; break; case 1: /* slow down enemies */ if (*bbugs_speed > 2) *bbugs_speed = *bbugs_speed - 2; break; case 2: /* Add one bug */ if (*bbugs_num < MAX_BBUGS_NUM - 1) *bbugs_num = *bbugs_num + 1; break; case 3: /* Subtract one bug */ if (*bbugs_num > MIN_BBUGS_NUM) *bbugs_num = *bbugs_num - 1; break; default: /*Bad news if this is ever reached! */ GP142_animate(ANI_HALT); something_is_wrong(); break; } } /***************************************************************************** ANIMATED OBJECTS : NON-BUGS blink_star move_moon *****************************************************************************/ /* Make the stars blink */ void blink_star(int *star_radius, int *star_color) { *star_radius = rand() % MAX_STAR_RADIUS + 1; *star_color = rand() % MAX_COLORS; } /* Update moon coordinates moon_x, moon_y by one tick */ void move_moon(int *moon_x, int *moon_y) { /* Move the moon to the left. If it reaches the edge, move it */ /* to the other side and down a bit. */ (*moon_x) --; if (*moon_x < -GP142_XMAX -30) { *moon_x = - *moon_x; (*moon_y) --; } } /***************************************************************************** ANIMATED OBJECTS : BUGS move_bug move_bbugs bug_direction bbugs_direction bug_collision *****************************************************************************/ /****************** MOVE THE GOOD BUG *******************************/ void move_bug(int *bug_x, int *bug_y, int *bug_size, int bug_speedx, int bug_speedy, int max_bug_size) { *bug_x = *bug_x + bug_speedx; *bug_y = *bug_y + bug_speedy; *bug_size = max_bug_size/2 + rand() % max_bug_size/2; /* scroll around the screen */ if (*bug_x >= GP142_XMAX + *bug_size) *bug_x = -GP142_XMAX - *bug_size; else if (*bug_x <= -GP142_XMAX - *bug_size) *bug_x = GP142_XMAX + *bug_size; if (*bug_y >= GP142_YMAX + *bug_size) *bug_y = -GP142_YMAX - *bug_size; else if (*bug_y <= -GP142_YMAX - *bug_size) *bug_y = GP142_YMAX + *bug_size; draw_bug(*bug_x, *bug_y, *bug_size); } /******************** MOVE THE BAD BUGS ********************/ void move_bbugs(int *bbugs_x, int *bbugs_y, int *bbugs_size, int *u_or_d, int *l_or_r, int bbugs_speed) { *bbugs_x = *bbugs_x + (*l_or_r * rand() % bbugs_speed); *bbugs_y = *bbugs_y + (*u_or_d * rand() % bbugs_speed); *bbugs_size = MAX_BUG_SIZE/2 + rand() % MAX_BUG_SIZE/2; /* scroll around the screen */ if (*bbugs_x >= GP142_XMAX + *bbugs_size) *bbugs_x = -GP142_XMAX - *bbugs_size; else if (*bbugs_x <= -GP142_XMAX - *bbugs_size) *bbugs_x = GP142_XMAX + *bbugs_size; if (*bbugs_y >= GP142_YMAX + *bbugs_size) *bbugs_y = -GP142_YMAX - *bbugs_size; else if (*bbugs_y <= -GP142_YMAX - *bbugs_size) *bbugs_y = GP142_YMAX + *bbugs_size; /* draw them bugs */ draw_bbugs(*bbugs_x, *bbugs_y, *bbugs_size); } /************ DIRECTION SWITCH FOR BUG : KEYBOARD INPUT *************/ void bug_direction(char key_pressed, int *bug_speedx, int *bug_speedy) { switch(key_pressed) { case '9': *bug_speedx = BUG_SPEED / 2; *bug_speedy = BUG_SPEED / 2; break; case '8': *bug_speedx = 0; *bug_speedy = BUG_SPEED; break; case '7': *bug_speedx = -BUG_SPEED / 2; *bug_speedy = BUG_SPEED / 2; break; case '6': *bug_speedx = BUG_SPEED; *bug_speedy = 0; break; case '5': *bug_speedx = 0; *bug_speedy = 0; break; case '4': *bug_speedx = -BUG_SPEED; *bug_speedy = 0; break; case '3': *bug_speedx = BUG_SPEED / 2; *bug_speedy = -BUG_SPEED / 2; break; case '2': *bug_speedx = 0; *bug_speedy = -BUG_SPEED; break; case '1': *bug_speedx = -BUG_SPEED / 2; *bug_speedy = -BUG_SPEED / 2; break; default: break; } /* end of the switch */ } /* end of the function */ /***************** BBUGS DIRECTION SWITCH: 1 of every 4 ******************/ void bbugs_direction(int num_mod, int *up_or_down, int *left_or_right) { switch(num_mod) { case 0: *up_or_down = UP; *left_or_right = RIGHT; break; case 1: *up_or_down = UP; *left_or_right = LEFT; break; case 2: *up_or_down = DOWN; *left_or_right = RIGHT; break; case 3: *up_or_down = DOWN; *left_or_right = LEFT; break; default: break; } } /********************** TEST FOR BUG COLLISIONS *****************/ int bug_collision(bug_x, bug_y, bug_size, bbugs_x, bbugs_y, bbugs_size) { int bug_xr, bug_xl, bbugs_xl, bbugs_xr; int bug_yu, bug_yd, bbugs_yu, bbugs_yd; int x_align, y_align; x_align = FALSE; y_align = FALSE; bug_xr = bug_x + bug_size; bug_xl = bug_x - bug_size; bbugs_xr = bbugs_x + bbugs_size; bbugs_xl = bbugs_x - bbugs_size; bug_yu = bug_y + bug_size; bug_yd = bug_y - bug_size; bbugs_yu = bbugs_y + bbugs_size; bbugs_yd = bbugs_y - bbugs_size; if (bbugs_xr >= bug_xl && bbugs_xr <= bug_xr) x_align = TRUE; if (bbugs_xl >= bug_xl && bbugs_xl <= bug_xr) x_align = TRUE; if (bbugs_yu >= bug_yd && bbugs_yu <= bug_yu) y_align = TRUE; if (bbugs_yd >= bug_yd && bbugs_yd <= bug_yu) y_align = TRUE; if (x_align == TRUE && y_align == TRUE) { return TRUE; } else return FALSE; } /***************************************************************************** OTHER initialize_random_numbers something_is_wrong *****************************************************************************/ /**************** Initialize random number generator ***************************/ void initialize_random_numbers() { time_t t; /* current time */ srand (time(&t)); } /*********** Display error message if internal error is detected. ****************/ void something_is_wrong (void) { GP142_printfXY (RED, 0, 0, 16, "Program error!"); }