#include "link2.h" #include #include #include "SFont.h" #include extern int SCR_X; extern int SCR_Y; extern SDL_Surface *screen; extern void (*commander) (Node*); #include "ai.h" #include "files.h" extern int ai; extern object adam, david, ball; extern int difficult; extern char file_path[]; int number_points = 0; SDL_Surface *blue, *red; void really_quit(Node*); SDL_Surface *LoadImage(char *datafile); void main_menu(Node*); void quit(Node*); void options(Node*); void toggle_ai(Node*); void game_menu(Node*); void change_name(Node*); void change_user_adam(Node*); void change_user_david(Node*); void change_difficulty(Node*); void change_points(Node*); void points_up(Node*); void points_down(Node*); void write_my_config(Node*); void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: *p = pixel; break; case 2: *(Uint16 *)p = pixel; break; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; } else { p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; } break; case 4: *(Uint32 *)p = pixel; break; } } //Loads an image using the right path SDL_Surface *LoadImage(char *datafile) { SDL_Surface *image; char datatemp[70]; sprintf(datatemp, "%s%s", file_path, datafile); image = IMG_Load(datafile); if(image == NULL) { image = IMG_Load(datatemp); } return (image); } // generates a horizonal line void h_line(int x, int y, int dest_x, Uint32 color) { for( ; x < dest_x; x++) putpixel(screen, x, y, color); } // generates a vertical line line void v_line(int x, int y, int dest_y, Uint32 color) { for( ; y < dest_y; y++) putpixel(screen, x, y, color); } // inserts a new menu option into the list void make_option(Node *&head, int y, char * message, void (*command_pointer) (Node*), Node *ptr) { Node temp; SDL_Rect rect; rect.x = SCR_X/2 - TextWidth(message)/2; rect.y = y; rect.w = TextWidth(message); rect.h = blue->h; temp.data.rect = rect; temp.data.mesg = message; temp.data.command = command_pointer; temp.data.ptr = ptr; list_head_insert(head, temp); } // goes through the linked list and displays the menu options void display_options(Node *head, SDL_Surface *font) { Node * cursor; cursor = head; InitFont(font); while(cursor != NULL) { PutString(screen, cursor->data.rect.x, cursor->data.rect.y, cursor->data.mesg); SDL_UpdateRects(screen, 1, &cursor->data.rect); cursor = cursor->link; } } // loads the fonts and initializes the cursor void start_me() { blue=LoadImage("24P_Copperplate_Blue.png"); if(blue == NULL) { fprintf(stderr, "Can't load blue. Get it stupid!"); SDL_Quit(); exit(1); } red = LoadImage("red.png"); if(red == NULL) { fprintf(stderr, "Can't load red. Get it stupid!"); SDL_Quit(); exit(1); } InitFont(blue); SDL_ShowCursor(1); } // check to see if the x and y coordinates are within a predefined rect region int check_rect(SDL_Rect rect, int x, int y) { if((x >= rect.x) && (x <= (rect.x + rect.w))) { if((y >= rect.y) && (y <= (rect.y + rect.h))) return 1; } return 0; } // checks to see if the mouse is over a menu option int check_region(Node *head, SDL_Event event) { Node *cursor; cursor = head; int number = 1; while(cursor!=NULL) { if(check_rect(cursor->data.rect, event.motion.x, event.motion.y)) return number; else { cursor = cursor->link; number++; } } return 0; } // makes a box around a rect void make_box(SDL_Rect rect) { Uint32 c_red = SDL_MapRGB(screen->format, 255, 0, 0); h_line(rect.x, rect.y, rect.x + rect.w, c_red); v_line(rect.x, rect.y, rect.y + rect.h - 1, c_red); v_line(rect.x + rect.w - 1, rect.y, rect.y + rect.h, c_red); h_line(rect.x, rect.y + rect.h - 1, rect.x + rect.w, c_red); } // updates a single menu option with a specified font void update_region(Node *region, SDL_Surface *font, int underline) { InitFont(font); if(!underline) { Uint32 black = SDL_MapRGB(font->format, 0, 0, 0); SDL_FillRect(screen, ®ion->data.rect, black); } PutString(screen, region->data.rect.x, region->data.rect.y, region->data.mesg); if(underline) { //Uint32 c_red = SDL_MapRGB(screen->format, 0xff, 0x00, 0x00); SDL_LockSurface(screen); make_box(region->data.rect); SDL_UnlockSurface(screen); } SDL_UpdateRects(screen, 1, ®ion->data.rect); } // Handles menu events void menu(Node *head) { Node *temp; SDL_Event event; int region, new_region = 0; while(1) { while(SDL_WaitEvent(&event)) { switch(event.type) { case SDL_QUIT: SDL_Quit(); exit(0); break; case SDL_MOUSEMOTION: region = check_region(head, event); if(region != new_region) { if(region != 0) { if(list_locate(head, region)->data.command != NULL) update_region(list_locate(head, region), red, 1); } if(region == 0) update_region(list_locate(head, new_region), blue, 0); new_region = region; } break; case SDL_MOUSEBUTTONDOWN: region = check_region(head, event); if(region != 0) { temp = list_locate(head,region); if(temp->data.command != NULL) { temp->data.command(temp->data.ptr); } } break; } } } } // clears a specified surface void clear_surface(SDL_Surface *surface) { Uint32 black; SDL_Rect rect; rect.x = 0; rect.y = 0; rect.w = surface->w; rect.h = surface->h; black = SDL_MapRGB(surface->format, 0, 0, 0); SDL_FillRect(surface, &rect, black); SDL_UpdateRects(surface, 1, &rect); } void start_menu(Node *head, SDL_Surface *font) { if(head != NULL) { //SDL_WarpMouse(SCR_X/2, (list_locate(head, list_length(head))->data.rect.y + list_locate(head, list_length(head))->data.rect.h/2)); display_options(head, font); menu(head); } } // quits the program void quit(Node* head) { printf("Destroying data . . . \n"); write_config_file(); SDL_Quit(); exit(0); } void change_user_adam(Node* head) { clear_surface(screen); PutString(screen, SCR_X/2-TextWidth("Enter Name:"), 100, "Enter Name:"); SDL_UpdateRect(screen, 0,0,0,0); SFont_Input(screen,SCR_X/2-100, 150 ,200, adam.name); change_name(head); } void change_user_david(Node*head) { clear_surface(screen); PutString(screen, SCR_X/2-TextWidth("Enter Name:"), 100, "Enter Name:"); SDL_UpdateRect(screen, 0,0,0,0); SFont_Input(screen,SCR_X/2-100, 150 ,200, david.name); change_name(head); } void change_name(Node* head) { char temp[50]; char temp2[50]; sprintf(temp, "Change %s\'s Name", adam.name); clear_surface(screen); make_option(head, 100, temp, &change_user_adam, head); sprintf(temp2, "Change %s\'s Name", david.name); make_option(head, 200, temp2, &change_user_david, head); make_option(head, 300, "Return to Main Menu", &game_menu, head); start_menu(head, blue); } /* void points_up(Node *head) { number_points++; david.points++; adam.points++; change_points(head); } void points_down(Node *head) { number_points--; david.points--; adam.points--; change_points(head); } void change_points(Node* head) { list_clear(head); clear_surface(screen); char temp[50]; sprintf(temp, "Number of Lives: %d", number_points); InitFont(blue); PutString(screen, SCR_X/2-TextWidth(temp)/2, 50, temp); SDL_UpdateRect(screen, 0,0,0,0); make_option(head, 175, "Have More Lives", &points_up, head); make_option(head, 250, "Have Less Lives", &points_down, head); make_option(head, 450, "Return to Main Menu", &options, head); start_menu(head, blue); } */ void change_difficulty(Node* head) { switch(difficult) { case 0: difficult++; break; case 1: difficult++; break; case 2: difficult = 0; break; default: break; } options(head); } void write_my_config(Node* head) { write_config_file(); } // turns on/off ai void toggle_ai(Node* head) { if(ai == 0) ai = 1; else ai = 0; options(head); } // option menu void options(Node* head) { list_clear(head); clear_surface(screen); make_option(head, 50, "Change Name", &change_name, head); if(ai == 0) make_option(head, 120, "Turn on AI", &toggle_ai, head); else { make_option(head, 120, "Turn off AI", &toggle_ai, head); make_option(head, 190, "Difficulty (click to change):", NULL, NULL); switch(difficult) { case 0: make_option(head, 260, "Easy", &change_difficulty, head); break; case 1: make_option(head, 260, "Hard", &change_difficulty, head); break; case 2: make_option(head, 260, "Impossible", &change_difficulty, head); break; } } //make_option(head, 330, "Change the Number of Lives", &change_points, head); //make_option(head, 400, "Save Options to Config File", &write_my_config, head); make_option(head, 470, "Return to Main Menu", &game_menu, head); start_menu(head, blue); } // displays the main option menu // just change make_option so that you can add your own menu // options and pass functions into them void main_menu(Node *head) { head = NULL; clear_surface(screen); make_option(head, 100, "New Game", commander, head); make_option(head, 200, "Options", &options, head); make_option(head, 300, "Quit", &really_quit, head); //start_menu(head, blue); } void game_menu(Node *head) { head = NULL; clear_surface(screen); make_option(head, 150, "Continue", commander, head); make_option(head, 225, "Options", &options, head); make_option(head, 300, "Quit", &really_quit, head); start_menu(head, blue); } // hmm . . .really quit?? this asks the user if he/she wants to quit void really_quit(Node *original) { Node *head; list_clear(head); clear_surface(screen); make_option(head, 100, "Are you sure?", NULL, NULL); make_option(head, 250, "Yes", &quit, original); make_option(head, 310, "No", &game_menu, head); start_menu(head, blue); }