void RemoteServerProxyUpdater::run() {
  while (keep_going_) {
    try {
      MessageReader reader(socket_);
      Message *message = reader.read_message();  // Need a pointer because of polymorphism
      if (message->type() == GameInitMessage::type_id()) {
        handle_objects(dynamic_cast<GameInitMessage *>(message));
      } else if (message->type() == LevelFinishedMessage::type_id()) {
        handle_level_finished(dynamic_cast<LevelFinishedMessage *>(message));
      } else if (message->type() == GameFinishedMessage::type_id()) {
        handle_game_finished(dynamic_cast<GameFinishedMessage *>(message));
      } else {
        std::stringstream ss;
        ss << std::hex
           << "Unexpected message in the RemoteServerProxyUpdater main loop with type 0x"
           << static_cast<int>(message->type());
        delete message;
        Logger::warning(ss.str());
        shutdown();
      }
      delete message;
    } catch (const InvalidMessageException& e) {
      std::stringstream ss;
      ss << "Unexpected message in the RemoteServerProxyUpdater main loop. "
         << e.what();
      Logger::error(ss.str());
      shutdown();
    }
  }
}
Beispiel #2
0
/* The main game loop */
static void do_game(game_t *p_game)
{
  uint8_t exit=FALSE;

  while(!exit)
    {
      uint16_t input = get_input(p_game);
      uint16_t fire;
      int i;

      exit = input & FE_EVENT_EXIT;
      fire = input & FE_EVENT_SELECT;

      /* Move the paddle (according to input) */
      update_paddle(&p_game->paddle, input & FE_EVENT_LEFT ? 4:0, input & FE_EVENT_RIGHT ? 4:0);

      /* Handle the ball(s) */
      p_game->free_ball = -1;
      for (i=0; i<MAX_BALLS; i++)
	{
	  /* Unused balls are skipped */
	  if (!(p_game->p_balls[i].state & BALL_STATE_ACTIVE))
	    {
	      draw_ball(&p_game->p_balls[i]);
	      p_game->free_ball = i;
	      continue;
	    }

	  /* The player is holding the ball */
	  if (p_game->p_balls[i].state & BALL_STATE_HOLDING)
	    {
	      p_game->p_balls[i].lastx = p_game->p_balls[i].x;
	      p_game->p_balls[i].x += p_game->paddle.x-p_game->paddle.lastx;

	      if (fire)
		{
		  /* The player relases the ball. The following will
		   * clear the HOLDING-bit. It will also shoot the
		   * ball away upwards.
		   */
		  p_game->p_balls[i].dx = 1;
		  p_game->p_balls[i].state &= (0xff ^ BALL_STATE_HOLDING);
		  bounce_ball_paddle(p_game, &p_game->p_balls[i]);
		}
	    }
	  else if (paddle_ball_collide(&p_game->paddle, &p_game->p_balls[i]))
	    {
	      /* Hold the ball if the pad is sticky */
	      if (p_game->paddle.type & SPECIAL_STICKY)
		{
		  p_game->p_balls[i].dy = 0;
		  p_game->p_balls[i].dx = 0;
		  p_game->p_balls[i].state |= BALL_STATE_HOLDING;
		  p_game->paddle.type--; /* Sticky for maximum 3 rounds */
		}
	      else
		bounce_ball_paddle(p_game, &p_game->p_balls[i]);
	    }
	  /* Check collisions against blocks */
	  block_ball_collide(p_game, &p_game->p_balls[i]);

	  draw_ball(&p_game->p_balls[i]);

	  /* Update the ball (and check if it moves out of the playfield) */
	  if (update_ball(p_game, &p_game->p_balls[i]))
	    {
	      /* Ball is out of bounds - Remove it */
	      init_ball(&p_game->p_balls[i], 0, 0, 0);
	      p_game->nr_balls--;
	    }
	}
      /* Handle the specials */
      p_game->free_special = -1;
      for (i=0; i<MAX_SPECIALS; i++)
	{
	  int res;

	  /* Always draw the specials for timing-reasons */
	  draw_special(&p_game->p_specials[i]);
	  /* Inactive special - continue */
	  if (!p_game->p_specials[i].type)
	    {
	      p_game->free_special = i;
	      continue;
	    }

	  /* This moves the special and also checks if it collides with the paddle */
	  res = update_special(p_game, &p_game->p_specials[i]);
	  switch(res)
	    {
	    case 1: /* Player took the special */
	      switch(p_game->p_specials[i].type)
		{
		case SPECIAL_EXTRA_BALL:
		  if (p_game->free_ball != -1) /* Check if there is free space for the ball */
		    {
		      p_game->nr_balls++;
		      init_ball(&p_game->p_balls[p_game->free_ball], p_game->paddle.x+PADDLE_WIDTH/2,
				PADDLE_Y-PADDLE_HEIGHT, BALL_STATE_ACTIVE);
		    }
		  break;
		case SPECIAL_LONG_PADDLE:
		  p_game->paddle.width = PADDLE_LONG_WIDTH;
		  break;
		case SPECIAL_SHORT_PADDLE:
		  p_game->paddle.width = PADDLE_SHORT_WIDTH;
		  break;
		case SPECIAL_EXTRA_LIFE:
		  if (p_game->lives < MAX_LIVES)
		    {
		      p_game->lives++;
		      draw_lives(p_game);
		    }
		  break;
		case SPECIAL_STICKY:
		  /*
		   * For the sticky and destroyers, we use the bits
		   * from the flag and downwards as counters.
		   *
		   * i.e: SPECIAL_STICKY is the third bit, which means
		   * that type becomes 0b00000111. type is then
		   * lowered when the ball hits the paddle and after
		   * zeroing the lower bits, the SPECIAL_STICKY bit is
		   * finally cleared. This gives a maximum of three
		   * sticky rounds.
		   *
		   * These two only adds 30 bytes to the binary :-)
		   */
		  p_game->paddle.type = (SPECIAL_STICKY | (SPECIAL_STICKY-1));
		  break;
		case SPECIAL_DESTROYER:
		  p_game->p_balls[0].state |= (BALL_STATE_DESTROYER | (BALL_STATE_DESTROYER-1));
		  break;
		case SPECIAL_FLOOR:
		  p_game->state |= (SPECIAL_FLOOR | 2); /* Three times */
		  fe_fill_area(0, SCREEN_HEIGHT-FLOOR_HEIGHT, SCREEN_WIDTH, FLOOR_HEIGHT);
		  break;
		}
	      /* Fall through */
	    case -1:
	      /* Remove the special */
	      p_game->nr_specials--;
	      fe_clear_area(p_game->p_specials[i].x, p_game->p_specials[i].y-1, SPECIAL_WIDTH, SPECIAL_HEIGHT+1);
	      p_game->p_specials[i].type = SPECIAL_NONE;
	      break;
	    }
	}

      /* No balls left in play */
      if (!p_game->nr_balls)
	{
	  if (--p_game->lives == 0)
	    exit = TRUE; /* No lives left! */
	  else
	    {
	      /* Restart the game */
	      p_game->nr_balls = 1;
	      draw_screen(p_game);
	      init_paddle(&p_game->paddle, SPECIAL_NONE, SCREEN_WIDTH/2-PADDLE_WIDTH/2);
	      init_ball(&p_game->p_balls[0], p_game->paddle.x+p_game->paddle.width/2,
			PADDLE_Y-PADDLE_HEIGHT, BALL_STATE_HOLDING | BALL_STATE_ACTIVE);
	    }
	}
      /* No blocks left to remove */
      if (!p_game->nr_blocks)
	{
	  fe_sleep(LEVEL_SLEEP_PERIOD);

	  if (handle_level_finished(p_game) < 0)
	    exit = TRUE; /* Last level */
	}

      draw_paddle(&p_game->paddle);
      /* Sleep for a short while. */
#if !defined(TARGET_REX)
      fe_sleep(SLEEP_PERIOD);
#endif /* TARGET_REX */
    }
}