示例#1
0
文件: g_misc.c 项目: AQ2Chile/aq2-tng
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);
}
示例#2
0
/****************************************
* 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 ------------  */
示例#3
0
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);
	}