/* Brian Jason Rogers * CSE 142 BI * * | | | | | | * | | | | | | * |---| | | | '---|- * | | | | | | * | | \/ \/ | */ #include "gp142.h" #include #include #include /* * is included so the current time can be accessed * to initialize the random number generator. If you don't * use random numbers (and you don't have to) you can either * ignore this #include or delete it. */ /* 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 /* * Symbolic constants. Change as needed. */ /* Menu buttons: */ /* Top-left coordinates of button palette */ #define MENU_TOP (GP142_YMAX - 5) #define MENU_LEFT (-GP142_XMAX + 5) /* Height and width of buttons in pixels */ #define BUTTON_HEIGHT 25 #define BUTTON_WIDTH 100 /* Number of buttons */ #define NUM_BUTTONS 3 /* Possible locations of mouse clicks: */ /* Mouse click in some button */ #define BUTTON_CLICK 1 /* Mouse click elsewhere */ #define OTHER_CLICK 0 /* Coordinates of objects in the drawing */ /* 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 #define MAX_BUG_SIZE 10 #define NUM_FLAMES 10 #define NUM_PUFFS 10 #define TREE_XMIN (-GP142_XMAX+25) #define TREE_XMAX (-GP142_XMAX+85) #define TREE_YMIN (-GP142_YMAX+80) #define TREE_YMAX (-GP142_YMAX+140) #define TREE_WIDTH (TREE_XMAX-TREE_XMIN) #define TREE_HEIGHT (TREE_YMAX-TREE_YMIN) #define PIC_WIDTH 32 #define PIC_HEIGHT 38 #define MAX_SCALE 4 /***************************************************************************** FUNCTION PROTOTYPES *****************************************************************************/ /* Initialize random number generator. [Ignore or */ /* remove if your program doesn't use random numbers.] */ void initialize_random_numbers(); /* Initializes the moon parameters */ void init_moon(int *moon_x, int *moon_y); /* Draw a single boat */ void draw_boat(int boat_x, int boat_y, int boat_len, int boat_mast); /* Draw a single bug (buttefly) */ void draw_bug(int bug_x, int bug_y, int bug_size); /* Draw fire */ void draw_fire(int fire_info[3], int fire_width, int fire_height); /* Draw smoke */ void draw_smoke(int smoke_info[3]); /* Change flower field colors */ void change_colors(int *petal_color, int *flower_color); /* 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); /* Make stars blink */ void blink_star(int *star_radius, int *star_color); /* Move bug(s) */ void move_bug(int *bug_x, int *bug_y, int *bug_size); /* Update moon coordinates moon_x, moon_y for one tick */ void move_moon(int *moon_x, int *moon_y); /* Animate flames (Fire!!) */ void move_fire (int fire_info[3]); /* Animate smoke (caused by Fire!!) */ void move_smoke (int smoke_info[3]); /* Animate boat (for wind effect) */ void move_boat (int *boat_x, int *boat_y); /* About screen picture*/ void draw_pic(int my_picture[], int *scale_factor); /* 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 *petal_color, int *flower_color, int *boat_anim, int *fire_anim); /* Display error message if internal error is detected. */ void something_is_wrong (void); /***************************************************************************** MAIN *****************************************************************************/ /* * Main program contents: * - Major program variables that persist throughout execution * - Event loop that processes GP142 events until the user quits, * and updates variables and redraws the window as needed. */ int main(void) { int for_var; /* random 'for' variable */ /* NOTE: the following was quite difficult...please consider this when giving out extra credit!! */ /* Basically, we have a 38x32 grid of different color values in order to draw a simple picture of myself */ /* all the numbers correspond to the color constants from the #define statements (RED, YELLOW, etc.) */ int my_picture[]= {1,1,1,1,1,1,2,0,0,0,0,2,2,2,0,0,0,0,0,2,2,2,2,5,5,5,0,2,1,1,1,1, 1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,2,2,2,2,0,0,0,2,2,2,5,0,2,1,1,1,1, 1,1,1,1,1,2,0,0,0,0,0,0,0,0,2,5,5,5,5,5,2,0,0,0,0,2,0,2,1,1,1,1, 1,1,1,1,1,2,0,0,0,0,0,0,0,2,5,5,5,1,1,5,5,2,0,0,0,0,0,2,1,1,1,1, 1,1,1,1,1,0,0,0,0,0,0,0,2,5,5,5,5,5,5,5,5,5,2,2,0,0,0,0,1,1,1,1, 1,1,1,1,2,0,0,0,0,0,0,2,2,5,5,5,5,5,5,5,5,5,5,2,2,0,0,0,2,1,1,1, 1,1,1,1,2,0,0,0,0,0,2,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,0,0,0,1,1,1, 1,1,1,5,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,0,0,0,1,1, 1,1,1,0,0,0,0,0,0,2,5,5,5,2,2,2,2,5,5,5,5,5,5,2,2,2,2,0,0,0,1,1, 1,1,2,0,0,0,0,0,2,5,5,5,2,2,2,2,2,2,2,2,5,5,5,5,2,2,2,0,0,0,1,1, 1,1,5,0,0,0,0,0,2,5,5,5,0,5,0,2,2,2,2,2,2,5,5,5,2,2,2,0,0,0,2,1, 1,1,2,0,0,0,0,0,5,5,5,5,2,5,1,1,1,1,5,2,2,5,5,5,2,2,2,0,2,0,0,1, 1,1,0,0,0,0,0,2,5,5,5,5,5,2,2,5,1,5,2,2,5,1,5,5,2,2,2,2,1,5,0,1, 1,1,0,0,0,0,0,2,5,5,1,5,5,5,2,2,2,2,5,5,5,5,5,5,5,2,0,2,5,2,0,1, 1,1,0,0,0,0,0,2,5,5,1,5,2,2,5,5,5,5,5,5,5,5,5,5,5,2,0,2,1,5,0,2, 1,2,0,0,0,0,2,2,2,5,5,5,2,2,5,1,5,2,5,5,5,1,5,5,5,5,0,0,5,1,0,2, 1,0,0,0,0,0,2,2,5,5,5,5,2,0,2,5,2,2,5,1,1,1,5,5,5,5,0,0,2,2,0,2, 1,0,0,0,0,0,2,2,5,5,5,5,2,2,1,5,2,5,1,1,1,1,5,5,5,5,0,0,5,2,0,0, 2,0,0,0,0,0,0,2,2,2,2,5,5,5,1,1,5,5,5,5,5,5,5,5,5,5,2,0,2,2,0,0, 2,0,0,0,0,0,0,0,0,0,5,1,1,2,5,5,2,2,5,5,1,1,5,5,5,5,2,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,5,1,2,2,5,5,2,2,2,2,1,1,5,5,5,2,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,2,2,0,2,2,2,5,5,2,2,0,0,5,2,0,2,5,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,2,2,2,2,5,5,2,0,0,0,0,0,2,2,5,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,2,5,1,5,5,2,5,5,5,2,2,2,0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,5,5,2,5,5,5,5,2,0,0,0,0,0,0,0,0,1, 0,0,0,0,0,0,0,0,2,5,5,5,5,5,1,5,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1, 5,0,0,0,0,0,0,0,2,2,5,5,5,5,5,5,5,5,2,2,2,2,2,2,0,0,0,0,0,0,1,1, 5,0,0,0,0,0,0,0,0,0,2,2,5,5,5,5,5,5,5,5,5,5,2,0,0,0,0,0,0,0,1,1, 1,5,0,0,0,0,0,0,0,0,0,0,2,5,5,5,5,5,5,5,2,0,0,0,0,0,0,0,0,5,1,1, 1,1,0,0,0,0,0,0,0,0,0,0,2,2,5,5,5,2,0,0,0,0,0,0,0,0,0,0,5,1,1,1, 1,1,2,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1, 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1, 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1,1, 1,1,1,1,1,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,5,5,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,5,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; int scale_factor=0; /* used for scaling the pixels from my_picture */ int about_screen=FALSE; /* show about screen*/ int scale_up=FALSE; /* used in about screen function for scaling pic */ /* Info for fire animation */ int fire_anim=FALSE; /* TRUE or FALSE depending on if fire button has been pressed */ int fire_info[3]={0,0,0}; /* array for storing x-coor, y-coor, and color of flames */ /* for flames 1 thru NUM_FLAMES */ int fire_width, fire_height; /* width and height of a flame */ int smoke_info[3]={0,0,0}; /* array for storing x-ccor, y-coor, and color of smoke puffs */ /* for puffs 1 thru NUM_PUFFS */ /* Event handling and buttons: */ int 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_anim=FALSE; /* TRUE or FALSE, depending on if it's moving or not */ int boat_len, boat_mast; /* length of the boat and height of the mast */ /* Information about the bug(s) */ int bug_x, bug_y, bug_size; /* screen x and y coordinates and size of the bug */ /* Dummy vars for GP142_await_event */ char dummy_event, dummy_c; /* 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 - 200; 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 = flower_x + 20; bug_y = flower_y + 30; bug_size = MAX_BUG_SIZE/2; /* set initial conditions for fire */ fire_width=10; fire_height=15; /* 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); 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) { /* 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: /* Key pressed. Not used now. If the program should */ /* react to keyboard events, insert something appropriate */ /* here. Note that scanf CANNOT be used with GP142. */ switch(key_pressed) { case 'A': case 'a': about_screen=TRUE; scale_up=TRUE; break; case 'h': case 'H': GP142_clear(); GP142_printfXY(RED,-GP142_XMAX+10, GP142_YMAX-20,14,"Help Menu"); GP142_printfXY(BLUE,-GP142_XMAX+15, GP142_YMAX-40,12,"(A)bout this program\n(H)elp screen (this one)\n\nClick the mouse to return"); while(dummy_event!=GP142_MOUSE) dummy_event=GP142_await_event(&mouse_x, &mouse_y, &dummy_c); break; default: break; } dummy_event=-GP142_MOUSE; break; case GP142_MOUSE: /* Mouse click. Determine if in a menu button */ /* or elsewhere and process accordingly. */ click_kind = classify_mouse_click(mouse_x, mouse_y); if (click_kind == BUTTON_CLICK) { handle_button(mouse_x, mouse_y, &petal_color, &flower_color, &boat_anim, &fire_anim); } else { /* insert code here (and additional else-if statements) */ /* to react to mouse clicks elsewhere on the screen (if needed) */ } break; case GP142_PERIODIC: /* Timer interval event. Update everything that needs the change */ /* as time advances. Animation should go here! */ 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); if (boat_anim==TRUE){ move_boat(&boat_x, &boat_y); } break; default: /* unknown event */ break; } /*end 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); if (fire_anim==TRUE) { for (for_var=0;for_var 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; } /* Process button click at location x, y. React appropriately: */ /* i.e. change colors, tree tops, etc. if requested. */ void handle_button(int x, int y, int *petal_color, int *flower_color, int *boat_anim, int *fire_anim) { int dummy_x, dummy_y; /* dummy variables used for GP142_await_event */ char dummy_c; 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: /* change flower field colors */ change_colors(petal_color, flower_color); break; case 1: /* set tree on fire */ if (*boat_anim==FALSE && *fire_anim!=TRUE) *fire_anim=TRUE; else *fire_anim=FALSE; if (*boat_anim==TRUE) { GP142_clear(); GP142_printfXY(RED,-GP142_XMAX,0,24," Wind is blowing too hard! Can't start fire!\n Click the mouse."); while (GP142_await_event(&dummy_x,&dummy_y,&dummy_c)!=GP142_MOUSE); } break; case 2: /* simulate wind effects (for extra credit only) - remove if not doing it */ if (*fire_anim==TRUE) { GP142_clear(); GP142_printfXY(RED,-GP142_XMAX,0,24," Wind puts out fire! Good job.\n Click the mouse."); while (GP142_await_event(&dummy_x,&dummy_y,&dummy_c)!=GP142_MOUSE); } if (*boat_anim!=TRUE) *boat_anim=TRUE; else *boat_anim=FALSE; if (*fire_anim==TRUE && *boat_anim==TRUE) *fire_anim=FALSE; break; default: /*Bad news if this is ever reached! */ GP142_animate(ANI_HALT); something_is_wrong(); break; } } /***************************************************************************** ANIMATED OBJECTS *****************************************************************************/ /* 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) --; } } /* Set tree on fire */ void move_fire(int fire_info[3]) { int rand_num; rand_num = rand()%4; switch(rand_num){ case 0: *(fire_info+2)=YELLOW; break; case 1: *(fire_info+2)=RED; break; case 2: *(fire_info+2)=WHITE; break; case 3: *(fire_info+2)=ORANGE; break; } *fire_info=rand()%TREE_WIDTH+TREE_XMIN+1; *(fire_info+1)=rand()%(TREE_HEIGHT/2)+TREE_YMIN*5/6+1; } void move_smoke(int smoke_info[3]) { int rand_num; rand_num = rand()%3; switch(rand_num){ case 0: *(smoke_info+2)=BLACK; break; case 1: *(smoke_info+2)=MED_GRAY; break; case 2: *(smoke_info+2)=LT_GRAY; break; } *smoke_info=rand()%TREE_WIDTH+TREE_XMIN+1; *(smoke_info+1)=rand()%TREE_HEIGHT/3+TREE_YMAX*4/5+1; } /* Make the bug(s) move around and flutter */ void move_bug(int *bug_x, int *bug_y, int *bug_size) { *bug_x = *bug_x + rand() % 3 - 1; *bug_y = *bug_y + rand() % 3 - 1; *bug_size = MAX_BUG_SIZE/2 + rand() % MAX_BUG_SIZE/2; draw_bug(*bug_x, *bug_y, *bug_size); } /* Make the boat move across the lake */ void move_boat(int *boat_x, int *boat_y) { (*boat_x) --; if (*boat_x < -GP142_XMAX -30) { *boat_x = GP142_XMAX / 3 - 20; (*boat_y) --; } } void draw_pic(int my_picture[], int *scale_factor) { int i; GP142_clear(); for (i=0;i