void SP_misc_strogg_ship (edict_t * ent) { if (!ent->target) { gi.dprintf ("%s without a target at %s\n", ent->classname, vtos (ent->absmin)); G_FreeEdict (ent); return; } if (!ent->speed) ent->speed = 300; ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_NOT; ent->s.modelindex = gi.modelindex ("models/ships/strogg1/tris.md2"); VectorSet (ent->mins, -16, -16, 0); VectorSet (ent->maxs, 16, 16, 32); NEXT_FRAME(ent, func_train_find); ent->use = misc_strogg_ship_use; ent->svflags |= SVF_NOCLIENT; ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = ent->speed; gi.linkentity (ent); }
/**************************************** * TitleScreen: Display the title screen * ***************************************** * display title screen, get input */ void TitleScreen(void) { Uint32 frame = 0; Uint32 start = 0; /* NOTE for 'depth', think pages like a restaurant menu, */ /* not heirarchical depth - choice of term is misleading */ int menu_depth; // how deep we are in the menu int i, j, tux_frame = 0; int done = 0; int firstloop = 1; int menu_opt = NONE; int sub_menu = NONE; int update_locs = 1; int redraw = 0; int key_menu = 1; int old_key_menu = 5; if (settings.sys_sound) { settings.menu_sound = 1; settings.menu_music = 1; } start = SDL_GetTicks(); /* * Display the Standby screen.... */ show_logo(); snd_welcome = LoadSound("harp.wav"); if (snd_welcome && settings.menu_sound) { PlaySound(snd_welcome); } /* Load media and menu data: */ if (!load_media()) { fprintf(stderr, "TitleScreen - load_media() failed!"); return; } SDL_WM_GrabInput(SDL_GRAB_ON); // User input goes to TuxType, not window manager /*************************** * Tux and Title animations * ***************************/ LOG( "->Now Animating Tux and Title onto the screen\n" ); Tuxdest.x = 0; Tuxdest.y = screen->h; Tuxdest.w = Tux->frame[0]->w; Tuxdest.h = Tux->frame[0]->h; Titledest.x = screen->w; Titledest.y = 10; Titledest.w = title->w; Titledest.h = title->h; spkrdest.x = screen->w - speaker->w - 10; spkrdest.y = screen->h - speaker->h - 10; spkrdest.w = speaker->w; spkrdest.h = speaker->h; /* --- wait if the first time in the game --- */ if (settings.show_tux4kids) { while ((SDL_GetTicks() - start) < 2000) { SDL_Delay(50); } settings.show_tux4kids = 0; } SDL_ShowCursor(1); /* FIXME not sure the next line works in Windows: */ TransWipe(CurrentBkgd(), RANDOM_WIPE, 10, 20); /* Make sure background gets drawn (since TransWipe() doesn't */ /* seem to work reliably as of yet): */ SDL_BlitSurface(CurrentBkgd(), NULL, screen, NULL); SDL_UpdateRect(screen, 0, 0, 0, 0); /* --- Pull tux & logo onscreen --- */ for (i = 0; i <= (PRE_ANIM_FRAMES * PRE_FRAME_MULT); i++) { start = SDL_GetTicks(); SDL_BlitSurface(CurrentBkgd(), &Tuxdest, screen, &Tuxdest); SDL_BlitSurface(CurrentBkgd(), &Titledest, screen, &Titledest); Tuxdest.y -= Tux->frame[0]->h / (PRE_ANIM_FRAMES * PRE_FRAME_MULT); Titledest.x -= (screen->w) / (PRE_ANIM_FRAMES * PRE_FRAME_MULT); /* Don't go past 0; */ if (Tuxdest.y < 0) Tuxdest.y = 0; if (Titledest.x < 0) Titledest.x = 0; SDL_BlitSurface(Tux->frame[0], NULL, screen, &Tuxdest); SDL_BlitSurface(title, NULL, screen, &Titledest); SDL_UpdateRect(screen, Tuxdest.x, Tuxdest.y, Tuxdest.w, Tuxdest.h); SDL_UpdateRect(screen, Titledest.x, Titledest.y, Titledest.w + 40, Titledest.h); while ((SDL_GetTicks() - start) < 33) { SDL_Delay(2); } } recalc_rects(); /* Pick speaker graphic according to whether music is on: */ if ( settings.menu_music ) SDL_BlitSurface(speaker, NULL, screen, &spkrdest); else SDL_BlitSurface(speakeroff, NULL, screen, &spkrdest); /* Start playing menu music if desired: */ if (settings.menu_music) MusicLoad( "tuxi.ogg", -1 ); LOG( "Tux and Title are in place now\n" ); SDL_WM_GrabInput(SDL_GRAB_OFF); /**************************** * Main Loop Starts Here ... * ****************************/ menu_depth = 1; firstloop = 1; Tuxdest.y = screen->h - Tux->frame[0]->h; while (!done) { start = SDL_GetTicks(); /* ---process input queue --- */ menu_opt = NONE; // clear the option so we don't change twice! old_key_menu = key_menu; /* Retrieve any user interface events: */ while (SDL_PollEvent(&event)) { switch (event.type) { /* Update "selection" if mouse moves within a menu entry: */ case SDL_MOUSEMOTION: { cursor.x = event.motion.x; cursor.y = event.motion.y; for (j = 1; j <= TITLE_MENU_ITEMS; j++) if (inRect(menu_button[j], cursor.x, cursor.y)) key_menu = j; break; } /* Handle mouse clicks based on mouse location: */ case SDL_MOUSEBUTTONDOWN: { cursor.x = event.motion.x; cursor.y = event.motion.y; for (j = 1; j <= TITLE_MENU_ITEMS; j++) { if (inRect(menu_button[j], cursor.x, cursor.y)) { menu_opt = menu_item[j][menu_depth]; if (settings.menu_sound) { PlaySound(snd_select); } DEBUGCODE { fprintf(stderr, "->>BUTTON CLICK menu_opt = %d\n", menu_opt); fprintf(stderr, "->J = %d menu_depth=%d\n", j, menu_depth); } } } /* If mouse over speaker, toggle menu music off or on: */ if (inRect(spkrdest, cursor.x, cursor.y)) { if (settings.menu_music) { MusicUnload(); settings.menu_music = 0; } else { settings.menu_music = 1; MusicLoad("tuxi.ogg", -1); } redraw = 1; } break; } case SDL_QUIT: { menu_opt = QUIT_GAME; break; } /* Handle key press events based on key value: */ case SDL_KEYDOWN: { switch (event.key.keysym.sym) { case SDLK_ESCAPE: { /* Go to main menu (if in submenu) or quit: */ if (menu_depth != 1) menu_opt = MAIN; else menu_opt = QUIT_GAME; if (settings.menu_sound) PlaySound(snd_select); break; } /* Toggle screen mode: */ case SDLK_F10: { SwitchScreenMode(); recalc_rects(); redraw = 1; break; } /* Toggle menu music: */ case SDLK_F11: { if (settings.menu_music) { MusicUnload( ); settings.menu_music = 0; } else { settings.menu_music = 1; MusicLoad("tuxi.ogg", -1); } redraw = 1; break; } /* --- reload translation/graphics/media: for themers/translaters --- */ case SDLK_F12: { unload_media(); LoadLang(); load_media(); redraw = 1; break; } case SDLK_UP: case SDLK_k: { if (settings.menu_sound) PlaySound(snd_move); key_menu--; if (key_menu < 1) key_menu = 5; break; } case SDLK_DOWN: case SDLK_j: { key_menu++; if (settings.menu_sound) PlaySound(snd_move); if (key_menu > 5) key_menu = 1; break; } case SDLK_RETURN: { if (key_menu) { menu_opt = menu_item[key_menu][menu_depth]; if (settings.menu_sound) PlaySound(snd_select); } break; } default: /* Some other key pressed - do nothing: */ { break; } } /* End of switch(event.key.keysym.sym) statement */ } /* End of case: SDL_KEYDOWN: */ default: /* Some other type of SDL event - do nothing; */ { break; } } /* End of switch(event.type) statement */ } /* End of while (SDL_PollEvent(&event)) loop */ /* --- do menu processing --- */ if (menu_opt == QUIT_GAME) done = 1; if (menu_opt == LASER) { menu_depth = LASER_SUBMENU; sub_menu = LASER; update_locs = 1; redraw = 1; } if (menu_opt == CASCADE) { menu_depth = CASCADE_SUBMENU; sub_menu = CASCADE; update_locs = 1; redraw=1; } if (menu_opt == OPTIONS) { menu_depth = OPTIONS_SUBMENU; sub_menu = OPTIONS; update_locs = 1; redraw = 1; } if (menu_opt == MAIN) { menu_depth = ROOTMENU; update_locs = 1; redraw = 1; } if (menu_opt == EDIT_WORDLIST) { ChooseListToEdit(); redraw = 1; } if (menu_opt == PROJECT_INFO) { ProjectInfo(); redraw = 1; } if (menu_opt == LESSONS) { // not_implemented(); SDL_BlitSurface(CurrentBkgd(), NULL, screen, NULL); SDL_Flip(screen); unload_media(); if (settings.menu_music) MusicUnload( ); XMLLesson(); load_media(); redraw = 1; if (settings.menu_music) MusicLoad( "tuxi.ogg", -1 ); } if (menu_opt == SET_LANGUAGE) { unload_media(); ChooseTheme(); LoadLang(); LoadKeyboard(); load_media(); redraw = 1; if (settings.menu_music) MusicLoad( "tuxi.ogg", -1 ); } if (menu_opt == LEVEL1) { if (chooseWordlist()) { unload_media(); switch (sub_menu) { case CASCADE: PlayCascade( EASY ); break; case LASER: PlayLaserGame( EASY ); break; } } load_media(); if (settings.menu_music) MusicLoad("tuxi.ogg", -1); redraw = 1; } if (menu_opt == LEVEL2) { if (chooseWordlist()) { unload_media(); switch (sub_menu) { case CASCADE: PlayCascade( MEDIUM ); break; case LASER: PlayLaserGame( MEDIUM ); break; } if (settings.menu_music) MusicLoad( "tuxi.ogg", -1 ); } load_media(); redraw = 1; } if (menu_opt == LEVEL3) { if (chooseWordlist()) { unload_media(); switch (sub_menu) { case CASCADE: PlayCascade( HARD ); break; case LASER: PlayLaserGame( HARD ); break; } if (settings.menu_music) MusicLoad( "tuxi.ogg", -1 ); } load_media(); redraw = 1; } if (menu_opt == LEVEL4) { if (chooseWordlist()) { unload_media(); switch (sub_menu) { case CASCADE: PlayCascade( INSANE ); break; case LASER: PlayLaserGame( INSANE ); break; } if (settings.menu_music) MusicLoad( "tuxi.ogg", -1 ); } load_media(); redraw = 1; } if (menu_opt == INSTRUCT) { // not_implemented(); unload_media(); switch (sub_menu) { case CASCADE: InstructCascade(); break; case LASER: InstructLaser(); break; } load_media(); if (settings.menu_music) MusicLoad( "tuxi.ogg", -1 ); redraw = 1; } if (menu_opt == PHRASE_TYPING) { // not_implemented(); unload_media(); Phrases(NULL); load_media(); if (settings.menu_music) MusicLoad( "tuxi.ogg", -1 ); redraw = 1; } /* ------ End menu_opt processing ----------- */ if (redraw) { LOG("TitleScreen() - redraw requested\n"); recalc_rects(); SDL_BlitSurface(CurrentBkgd(), NULL, screen, NULL); SDL_BlitSurface(title, NULL, screen, &Titledest); if ( settings.menu_music ) SDL_BlitSurface(speaker, NULL, screen, &spkrdest); else SDL_BlitSurface(speakeroff, NULL, screen, &spkrdest); /* Screen will be updated due to update_locs - see ~30 lines down: */ // SDL_UpdateRect(screen, 0, 0, 0, 0); frame = redraw = 0; // so we redraw tux update_locs = 1; // so we redraw menu firstloop = 1; } /* --- create new menu screen when needed --- */ if (update_locs) { LOG("TitleScreen() - update_locs requested\n"); /* --- erase the last menu --- */ for (i = 1; i <= TITLE_MENU_ITEMS; i++) { text_dst[i].x = screen->w/2 - 70;//290; text_dst[i].w = reg_text[i][menu_depth]->w; text_dst[i].h = reg_text[i][menu_depth]->h; SDL_BlitSurface(CurrentBkgd(), &menu_button[i], screen, &menu_button[i]); menu_button[i].w = menu_width[menu_depth] + 20; } update_locs = 0; /* --- draw the full menu --- */ for (j = 1; j <= TITLE_MENU_ITEMS; j++) { DOUT(j); DrawButton(&menu_button[j], 10, REG_RGBA); if (reg_text[j][menu_depth] != NULL) SDL_BlitSurface(reg_text[j][menu_depth], NULL, screen, &text_dst[j]); if (menu_gfx[j][menu_depth] != NULL) SDL_BlitSurface(menu_gfx[j][menu_depth]->default_img, NULL, screen, &menu_gfxdest[j]); } SDL_UpdateRect(screen, 0, 0, 0, 0); LOG("TitleScreen() - update_locs completed\n"); } /* --- make tux blink --- */ switch (frame % TUX6) { case 0: tux_frame = 1; break; case TUX1: tux_frame = 2; break; case TUX2: tux_frame = 3; break; case TUX3: tux_frame = 4; break; case TUX4: tux_frame = 3; break; case TUX5: tux_frame = 2; break; default: tux_frame = 0; } if (tux_frame) { SDL_Rect blink_src, blink_dest; blink_src.x = 0; blink_src.y = 0; blink_src.w = Tuxdest.w; blink_src.h = Tuxdest.h; blink_dest.x = Tuxdest.x + blink_src.x; blink_dest.y = Tuxdest.y + blink_src.y; blink_dest.w = blink_src.w; blink_dest.h = blink_src.h; // SDL_BlitSurface(CurrentBkgd(), , screen, &Tuxdest); SDL_BlitSurface(Tux->frame[tux_frame - 1], &blink_src, screen, &blink_dest); } /* --- check if mouse is in a menu option --- */ // key_menu = 0; /* for (j = 1; j <= TITLE_MENU_ITEMS; j++) { if ((cursor.x >= menu_button[j].x && cursor.x <= (menu_button[j].x + menu_button[j].w)) && (cursor.y >= menu_button[j].y && cursor.y <= (menu_button[j].y + menu_button[j].h))) { key_menu = j; // update menu to point break; // Don't need to check rest of menu } }*/ /* --- return old selection to unselected state --- */ if (old_key_menu && (key_menu != old_key_menu)) { SDL_BlitSurface(CurrentBkgd(), &menu_button[old_key_menu], screen, &menu_button[old_key_menu]); DrawButton(&menu_button[old_key_menu], 10, REG_RGBA); SDL_BlitSurface(reg_text[old_key_menu][menu_depth], NULL, screen, &text_dst[old_key_menu]); SDL_BlitSurface(menu_gfx[old_key_menu][menu_depth]->default_img, NULL, screen, &menu_gfxdest[old_key_menu]); } /* --- draw current selection --- */ if ((key_menu != 0) && ((old_key_menu != key_menu) || (frame % 5 == 0))) // Redraw every fifth frame? { if (key_menu != old_key_menu) { REWIND(menu_gfx[key_menu][menu_depth]); PlaySound(snd_move); } SDL_BlitSurface(CurrentBkgd(), &menu_button[key_menu], screen, &menu_button[key_menu]); DrawButton(&menu_button[key_menu], 10, SEL_RGBA); SDL_BlitSurface(sel_text[key_menu][menu_depth], NULL, screen, &text_dst[key_menu]); SDL_BlitSurface(menu_gfx[key_menu][menu_depth]->frame[menu_gfx[key_menu][menu_depth]->cur], NULL, screen, &menu_gfxdest[key_menu]); NEXT_FRAME(menu_gfx[key_menu][menu_depth]); } // HACK This is still more than we need to update every frame but // it cuts cpu on my machine %60 so it seems better... if ( settings.menu_music ) SDL_BlitSurface(speaker, NULL, screen, &spkrdest); else SDL_BlitSurface(speakeroff, NULL, screen, &spkrdest); SDL_UpdateRect(screen, spkrdest.x, spkrdest.y, spkrdest.w, spkrdest.h); for (i = 1; i < 6; i++) { SDL_UpdateRect(screen, menu_button[i].x, menu_button[i].y, menu_button[i].w, menu_button[i].h); } if (tux_frame) SDL_UpdateRect(screen, Tuxdest.x, Tuxdest.y, Tuxdest.w, Tuxdest.h); if (firstloop) SDL_UpdateRect(screen, Tuxdest.x, Tuxdest.y, Tuxdest.w, Tuxdest.h); firstloop = 0; /* Wait so we keep frame rate constant: */ while ((SDL_GetTicks() - start) < 33) { SDL_Delay(20); } frame++; } /* ----------- End of 'while(!done)' loop ------------ */
int PlayLaserGame(int diff_level) { int i, img, done, quit, frame, lowest, lowest_y, tux_img, old_tux_img, tux_pressing, tux_anim, tux_anim_frame, tux_same_counter, level_start_wait, num_cities_alive, num_comets_alive, paused, picked_comet, gameover; Uint16 key_unicode; SDL_Event event; Uint32 last_time = 0; Uint32 now_time = 0; SDLKey key; SDL_Rect src, dest; /* str[] is a buffer to draw the scores, waves, etc. (don't need wchar_t) */ char str[64]; LOG( "starting Comet Zap game\n" ); DOUT( diff_level ); SDL_ShowCursor(0); laser_load_data(); /* Clear window: */ SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); SDL_Flip(screen); /* --- MAIN GAME LOOP: --- */ done = 0; quit = 0; src.w = src.h = 0; /* Prepare to start the game: */ wave = 1; score = 0; gameover = 0; level_start_wait = LEVEL_START_WAIT_START; /* (Create and position cities) */ for (i = 0; i < NUM_CITIES; i++) { cities[i].alive = 1; cities[i].expl = 0; cities[i].shields = 1; } /* figure out x placement: */ calc_city_pos(); num_cities_alive = NUM_CITIES; num_comets_alive = 0; /* (Clear laser) */ laser.alive = 0; /* Reset remaining stuff: */ laser_reset_level(diff_level); /* --- MAIN GAME LOOP!!! --- */ frame = 0; paused = 0; picked_comet = -1; tux_img = IMG_TUX_RELAX1; tux_anim = -1; tux_anim_frame = 0; tux_same_counter = 0; ans_num = 0; MusicPlay(musics[MUS_GAME + (rand() % NUM_MUSICS)], 0); do { frame++; last_time = SDL_GetTicks(); old_tux_img = tux_img; tux_pressing = 0; /* Handle any incoming events: */ while (SDL_PollEvent(&event) > 0) { if (event.type == SDL_QUIT) { /* Window close event - quit! */ exit(0); } else if (event.type == SDL_KEYDOWN) { key = event.key.keysym.sym; if (key == SDLK_F10) { SwitchScreenMode(); calc_city_pos(); recalc_comet_pos(); } if (key == SDLK_F11) SDL_SaveBMP( screen, "laser.bmp"); if (key == SDLK_ESCAPE) paused = 1; /* --- eat other keys until level wait has passed --- */ if (level_start_wait > 0) key = SDLK_UNKNOWN; key_unicode = event.key.keysym.unicode; //key_unicode = event.key.keysym.unicode & 0xff; DEBUGCODE { fprintf(stderr, "key_unicode = %d\n", key_unicode); } /* For now, tuxtype is case-insensitive for input, */ /* with only uppercase for answers: */ if (key_unicode >= 97 && key_unicode <= 122) key_unicode -= 32; //convert lowercase to uppercase if (key_unicode >= 224 && key_unicode <= 255) key_unicode -= 32; //same for non-US chars LOG ("After checking for lower case:\n"); DEBUGCODE { fprintf(stderr, "key_unicode = %d\n", key_unicode); } /* Now update with case-folded value: */ ans[ans_num++] = key_unicode; } } /* Handle answer: */ for (;ans_num>0;ans_num--) { /* Pick the lowest shootable comet which has the right answer: */ lowest_y = 0; lowest = -1; for (i = 0; i < MAX_COMETS; i++) if (comets[i].alive && comets[i].shootable && comets[i].expl == 0 && comets[i].ch == ans[ans_num -1 ] && comets[i].y > lowest_y) { lowest = i; lowest_y = comets[i].y; } /* If there was an comet with this answer, destroy it! */ if (lowest != -1) { /* Destroy comet: */ comets[lowest].expl = COMET_EXPL_START; /* Make next letter in word shootable: */ comets[lowest].shootable = 0; if (comets[lowest].next) comets[lowest].next->shootable = 1; /* Fire laser: */ laser.alive = LASER_START; /* this is a hack so drawing to the center of the screen works */ if (abs(comets[lowest].x - screen->w/2) < 10) { laser.x1 = screen->w / 2; laser.y1 = screen->h; laser.x2 = laser.x1; laser.y2 = comets[lowest].y; } else { laser.x1 = screen->w / 2; laser.y1 = screen->h; laser.x2 = comets[lowest].x; laser.y2 = comets[lowest].y; } PlaySound(sounds[SND_LASER]); /* 50% of the time.. */ if (0 == (rand() % 2)) { /* ... pick an animation to play: */ if (0 == (rand() % 2)) tux_anim = IMG_TUX_YES1; else tux_anim = IMG_TUX_YAY1; tux_anim_frame = ANIM_FRAME_START; } /* Increment score: */ laser_add_score( (diff_level+1) * 5 * ((screen->h - comets[lowest].y)/20 )); } else { /* Didn't hit anything! */ PlaySound(sounds[SND_BUZZ]); if (0 == (rand() % 2)) tux_img = IMG_TUX_DRAT; else tux_img = IMG_TUX_YIPE; laser_add_score( -25 * wave); } } /* Handle start-wait countdown: */ if (level_start_wait > 0) { level_start_wait--; if (level_start_wait > LEVEL_START_WAIT_START / 4) tux_img = IMG_TUX_RELAX1; else if (level_start_wait > 0) tux_img = IMG_TUX_RELAX2; else tux_img = IMG_TUX_SIT; if (level_start_wait == LEVEL_START_WAIT_START / 4) PlaySound(sounds[SND_ALARM]); } /* If Tux pressed a button, pick a new (different!) stance: */ if (tux_pressing) { while (tux_img == old_tux_img) tux_img = IMG_TUX_CONSOLE1 + (rand() % 3); PlaySound(sounds[SND_TOCK]); } /* If Tux is being animated, show the animation: */ if (tux_anim != -1) { tux_anim_frame--; if (tux_anim_frame < 0) tux_anim = -1; else tux_img = tux_anim + 1 - (tux_anim_frame / (ANIM_FRAME_START / 2)); } /* Reset Tux to sitting if he's been doing nothing for a while: */ if (old_tux_img == tux_img) { tux_same_counter++; if (tux_same_counter >= 20) old_tux_img = tux_img = IMG_TUX_SIT; if (tux_same_counter >= 60) old_tux_img = tux_img = IMG_TUX_RELAX1; } else tux_same_counter = 0; /* Handle comets: */ num_comets_alive = 0; distanceMoved += speed; for (i = 0; i < MAX_COMETS; i++) { if (comets[i].alive) { num_comets_alive++; comets[i].x = comets[i].x + 0; comets[i].y = comets[i].y + speed; if (comets[i].y >= (screen->h - images[IMG_CITY_BLUE]->h) && comets[i].expl == 0) { /* Disable shields or destroy city: */ if (cities[comets[i].city].shields) { cities[comets[i].city].shields = 0; PlaySound(sounds[SND_SHIELDSDOWN]); laser_add_score(-50 * (diff_level+1)); } else { cities[comets[i].city].expl = CITY_EXPL_START; PlaySound(sounds[SND_EXPLOSION]); laser_add_score(-100 * (diff_level+1)); } tux_anim = IMG_TUX_FIST1; tux_anim_frame = ANIM_FRAME_START; /* Destroy comet: */ comets[i].expl = COMET_EXPL_START; } /* Handle comet explosion animation: */ if (comets[i].expl != 0) { comets[i].expl--; if (comets[i].expl == 0) comets[i].alive = 0; } } } /* Handle laser: */ if (laser.alive > 0) laser.alive--; /* Comet time! */ if (level_start_wait == 0 && (frame % 5) == 0 && gameover == 0) { if (num_attackers > 0) { /* More comets to add during this wave! */ if ((num_comets_alive < 2 || ((rand() % 4) == 0)) && distanceMoved > 40) { distanceMoved = 0; laser_add_comet(diff_level); num_attackers--; } } else { if (num_comets_alive == 0) { /* Time for the next wave! */ /* FIXME: End of level stuff goes here */ if (num_cities_alive > 0) { /* Go on to the next wave: */ wave++; laser_reset_level(diff_level); } else { /* No more cities! Game over! */ gameover = GAMEOVER_COUNTER_START; } } } } /* Handle cities: */ num_cities_alive = 0; for (i = 0; i < NUM_CITIES; i++) if (cities[i].alive) { num_cities_alive++; /* Handle animated explosion: */ if (cities[i].expl) { cities[i].expl--; if (cities[i].expl == 0) cities[i].alive = 0; } } /* Handle game-over: */ if (gameover > 0) { gameover--; if (gameover == 0) done = 1; } if ((num_cities_alive==0) && (gameover == 0)) gameover = GAMEOVER_COUNTER_START; /* Draw background: */ SDL_BlitSurface(CurrentBkgd(), NULL, screen, NULL); /* Draw wave: */ dest.x = 0; dest.y = 0; dest.w = images[IMG_WAVE]->w; dest.h = images[IMG_WAVE]->h; SDL_BlitSurface(images[IMG_WAVE], NULL, screen, &dest); sprintf(str, "%d", wave); laser_draw_numbers(str, images[IMG_WAVE]->w + (images[IMG_NUMBERS]->w / 10)); /* Draw score: */ dest.x = (screen->w - ((images[IMG_NUMBERS]->w / 10) * 7) - images[IMG_SCORE]->w); dest.y = 0; dest.w = images[IMG_SCORE]->w; dest.h = images[IMG_SCORE]->h; SDL_BlitSurface(images[IMG_SCORE], NULL, screen, &dest); sprintf(str, "%.6d", score); laser_draw_numbers(str, screen->w - ((images[IMG_NUMBERS]->w / 10) * 6)); /* Draw comets: */ for (i = 0; i < MAX_COMETS; i++) if (comets[i].alive) { /* Decide which image to display: */ if (comets[i].expl == 0) img = IMG_COMET1 + ((frame + i) % 3); else img = (IMG_COMETEX2 - (comets[i].expl / (COMET_EXPL_START / 2))); /* Draw it! */ dest.x = comets[i].x - (images[img]->w / 2); dest.y = comets[i].y - images[img]->h; dest.w = images[img]->w; dest.h = images[img]->h; SDL_BlitSurface(images[img], NULL, screen, &dest); } /* Draw letters: */ for (i = 0; i < MAX_COMETS; i++) if (comets[i].alive && comets[i].expl == 0) laser_draw_let(comets[i].ch, comets[i].x, comets[i].y); /* Draw cities: */ if (frame%2 == 0) NEXT_FRAME(shield); for (i = 0; i < NUM_CITIES; i++) { /* Decide which image to display: */ if (cities[i].alive) { if (cities[i].expl == 0) img = IMG_CITY_BLUE; else img = (IMG_CITY_BLUE_EXPL5 - (cities[i].expl / (CITY_EXPL_START / 5))); } else img = IMG_CITY_BLUE_DEAD; /* Change image to appropriate color: */ img += ((wave % MAX_CITY_COLORS) * (IMG_CITY_GREEN - IMG_CITY_BLUE)); /* Draw it! */ dest.x = cities[i].x - (images[img]->w / 2); dest.y = (screen->h) - (images[img]->h); dest.w = (images[img]->w); dest.h = (images[img]->h); SDL_BlitSurface(images[img], NULL, screen, &dest); /* Draw sheilds: */ if (cities[i].shields) { dest.x = cities[i].x - (shield->frame[shield->cur]->w / 2); dest.h = (screen->h) - (shield->frame[shield->cur]->h); dest.w = src.w; dest.h = src.h; SDL_BlitSurface( shield->frame[shield->cur], NULL, screen, &dest); } } /* Draw laser: */ if (laser.alive) laser_draw_line(laser.x1, laser.y1, laser.x2, laser.y2, 255 / (LASER_START - laser.alive), 192 / (LASER_START - laser.alive), 64); laser_draw_console_image(IMG_CONSOLE); if (gameover > 0) tux_img = IMG_TUX_FIST1 + ((frame / 2) % 2); laser_draw_console_image(tux_img); /* Draw "Game Over" */ if (gameover > 0) { dest.x = (screen->w - images[IMG_GAMEOVER]->w) / 2; dest.y = (screen->h - images[IMG_GAMEOVER]->h) / 2; dest.w = images[IMG_GAMEOVER]->w; dest.h = images[IMG_GAMEOVER]->h; SDL_BlitSurface(images[IMG_GAMEOVER], NULL, screen, &dest); } /* Swap buffers: */ SDL_Flip(screen); /* If we're in "PAUSE" mode, pause! */ if (paused) { quit = Pause(); paused = 0; } /* Keep playing music: */ if (settings.sys_sound && !Mix_PlayingMusic()) MusicPlay(musics[MUS_GAME + (rand() % NUM_MUSICS)], 0); /* Pause (keep frame-rate event) */ DEBUGCODE { fprintf(stderr, "now_time = %d\tlast_time = %d, elapsed time = %d\n", now_time, last_time, now_time - last_time); } now_time = SDL_GetTicks(); if (now_time < last_time + FPS) SDL_Delay(last_time + FPS - now_time); }