Beispiel #1
0
void game_render(SDL_Surface *buffer, camera *camera, PLAYERS *players, float interpolation) {
  int w, h;

  SDL_Rect terrain_rect = {gsl_vector_get(camera->vector, 0), gsl_vector_get(camera->vector, 1), WIDTH * ZOOM_LEVEL, HEIGHT * ZOOM_LEVEL}; 
  SDL_BlitSurface(background, &terrain_rect, buffer, NULL);

  player *pl;
  division *div;
  unit *un;

  for(int i = 0; i < players->num; i++) {
    pl = players->players[i];
    for(int j = 0; j < pl->num_divisions; j++) {
      div = pl->divisions[j];
      for(int k = 0; k < div->size; k++) {
        un = div->units[k];
        display_unit(buffer, camera, un, pl->color, interpolation);
        /* displays the closest node
        ai_node *closest = find_closest_node(un->vector);
        if(closest == NULL) {
          printf("couldn't find a node for (%f, %f)\n",
              gsl_vector_get(un->vector, 0),
              gsl_vector_get(un->vector, 1));
        } else {
          //printf("closest to (%f, %f) -> (%d, %d)\n", 
          //  gsl_vector_get(un->vector, 0),
          //  gsl_vector_get(un->vector, 1),
          //  closest->x, closest->y);
          gsl_vector *v = calculate_display_position(closest->x, closest->y, camera);
          filledCircleRGBA(buffer, gsl_vector_get(v, 0), gsl_vector_get(v, 1), 3, 0, 0xff, 0, 0xff);
          gsl_vector_free(v);
        }*/
      }
    }
  }

  // display the title in the upper left 
  SDL_BlitSurface(title, NULL, buffer, NULL);

  // display the zoom level in the bottom left
  char zoom[7];
  snprintf(zoom, 7, "Zoom %i", ZOOM_LEVEL);
  TTF_SizeUTF8(font, zoom, &w, &h);
  SDL_Surface *zoom_surf = draw_text(zoom);
  SDL_Rect zo = { 0, HEIGHT - h, w, h };
  SDL_BlitSurface(zoom_surf, NULL, buffer, &zo);
  SDL_FreeSurface(zoom_surf);

  if(paused) {
    paused_state.render(buffer, camera, players, interpolation);
  } else {
    update_camera_position(camera);
  }

}
Beispiel #2
0
/**
 * main
 *
 * TODO: Write function block once this is cleaned up.
 */
int main(int argc, char** argv)
{
  /*
   * Local Variables.
   */
  SDL_Event transient_event;
  SCREEN *screen;
  MATCH_STATE *match_state;
  Uint32 frame_start_time;
  Uint32 frame_time_taken_ms;
  Uint32 physics_time_delta;
  Uint32 last_physics_update;
  Uint32 ai_time_delta;
  Uint32 last_ai_update;
  Uint32 ms_per_frame;
  int rc;
  StrMap *config_table;
  Uint32 last_animation_update = 0;
  Uint32 animation_ms_per_frame;
  int max_fps;
  FONT *font;
  char disc_graphic_file[MAX_CONFIG_VALUE_LEN + 1];
  char grass_tile_file[MAX_CONFIG_VALUE_LEN + 1];
  char o_xml_file[MAX_CONFIG_VALUE_LEN + 1];
  char d_xml_file[MAX_CONFIG_VALUE_LEN + 1];
  int ii;
  SDL_Color white = {0xFF, 0xFF, 0xFF, 0x00};

  /*
   * Begin logging.
   */
  DT_INIT_LOG;

  /*
   * TODO: Move loading and retrieving constants using defaults from the config
   * file to a different folder, code file. Simple api.
   */
  load_config_to_str_map("config.txt", &config_table);
  if (!get_config_value_int(config_table,
                            cv_animation_ms_per_frame,
                            (int *)&animation_ms_per_frame))
  {
    game_exit("Programmer error: animation ms per frame not handled in cfg.");
  }
  if (!get_config_value_int(config_table, cv_max_fps, &max_fps))
  {
    game_exit("Programmer error: max fps not handled in cfg.");
  }
  ms_per_frame = (int) MILLISECONDS_PER_SECOND / max_fps;
  if (!get_config_value_str(config_table, cv_disc_graphic, (char *)disc_graphic_file))
  {
    game_exit("Programmer error: disc graphic not handled in cfg.");
  }
  if (!get_config_value_str(config_table, cv_grass_tile_filename, (char *)grass_tile_file))
  {
    game_exit("Programmer error: grass tile graphic not handled in cfg.");
  }
  if (!get_config_value_str(config_table, cv_o_xml_file, (char *)o_xml_file))
  {
    game_exit("Programmer error: O XML file not handled in cfg.");
  }
  if (!get_config_value_str(config_table, cv_d_xml_file, (char *)d_xml_file))
  {
    game_exit("Programmer error: D XML file not handled in cfg.");
  }
  DT_DEBUG_LOG("Config file loaded\n");

  /*
   * Create the screen object and use it to initialise the window system.
   */
  screen = create_screen();
  rc = init_window_system(screen, SCREEN_WIDTH, SCREEN_HEIGHT, BPP);
  if (INIT_OK != rc)
  {
    game_exit("Window system could not be initialised.");
  }
  DT_DEBUG_LOG("Graphics subsystem created and initialized\n");

  /*
   * Initialise Audio subsystem
   */
  rc = init_audio_subsystem(config_table);
  if (INIT_AUDIO_SYSTEM_OK != rc)
  {
    /*
     * Don't exit just because we can't output audio. The audio code will
     * handle this case.
     */
    DT_DEBUG_LOG("Audio subsystem could not be initialised\n");
  }
  else
  {
    DT_DEBUG_LOG("Audio subsystem created and initialized\n");
  }

  /*
   * Initialise the opengl components of the screen.
   */
  rc = init_gl(screen);
  if (GL_INIT_OK != rc)
  {
    game_exit("Could not do opengl initialisation.");
  }
  DT_DEBUG_LOG("OpenGL setup complete\n");

  /*
   * TODO: Proper font management system where more than one font can be loaded
   *
   * Create the font object that is going to be used to write text throughout
   * the game.
   */
  rc = create_font("..\\..\\resources\\Fonts\\LucidaSansRegular.ttf",
                   &font,
                   30,
                   TTF_STYLE_NORMAL,
                   white);
  if (BUILD_FONT_OK != rc)
  {
    game_exit("Could not load up LucidaSansRegular font.");
  }
  DT_DEBUG_LOG("Lucida sans regular font loaded\n");

  /*
   * TODO: Constants to move from here.
   *
   * Create a new match state object before starting the game loop.
   */
  match_state = create_match_state(15,
                                   60 * 60,
                                   disc_graphic_file,
                                   grass_tile_file,
                                   o_xml_file,
                                   d_xml_file,
                                   create_o_automaton_states,
                                   create_automaton_events);
  if (NULL == match_state)
  {
    game_exit("Failed to create match state.");
  }
  init_pitch(match_state->pitch);
  DT_DEBUG_LOG("Match state created and initialized\n");

  /*
   * Scale the pitch by an arbitrary amount to account for the otherwise small
   * scaling.
   */
  scale_camera(match_state->camera_handler, 10.0f);

  /*
   * Load the animation data.
   */
  rc = load_animation_data(match_state->animation_handler);
  if (LOAD_ANIMATION_DATA_OK != rc)
  {
    game_exit("Failed to load animation data.");
  }
  DT_DEBUG_LOG("Animation data loaded\n");

  /*
   * Initialise the timings
   */
  last_physics_update = SDL_GetTicks();
  last_ai_update = SDL_GetTicks();

  /*
   * Initialise and start a new match.
   */
  start_match(match_state);

  // @@@DAT testing
  throw_multi_player_ai_event_by_name(match_state->teams,
                                      match_state->players_per_team,
                                      match_state->teams[0]->players[0]->automaton,
                                      AUTOMATON_EVENT_PULL_THROWN);

  /*
   * Game loop
   */
  while(true)
  {
    /*
     * Frame time is tracked so that we can determine how long to wait before
     * displaying the next frame. i.e. to fix the FPS.
     */
    frame_start_time = SDL_GetTicks();

    /*
     * Look at disc
     */
    look_at_location(match_state->camera_handler,
                     match_state->disc->position.x,
                     match_state->disc->position.y,
                     screen);

    /*
     * While there are events to process, do so.
     */
    while(SDL_PollEvent(&transient_event))
    {
      /*
       * First check whether it is an SDL_QUIT event. If so then exit with
       * message.
       */
      if (transient_event.type == SDL_QUIT)
      {
        destroy_match_state(match_state);
        game_exit("User requested exit via SDL_QUIT event.");
      }
      else if ((transient_event.type == SDL_KEYDOWN) ||
               (transient_event.type == SDL_KEYUP))
      {
        /*
         * The event was the user either depressing or releasing a key so call
         * to the keyboard event handler to deal with the event.
         */
        handle_keyboard_event(&(transient_event.key),
                              transient_event.type,
                              match_state,
                              screen);
      }
      else if ((transient_event.type == SDL_MOUSEBUTTONDOWN) ||
               (transient_event.type == SDL_MOUSEBUTTONUP))
      {
        /*
         * The event was the user either depressing or releasing a mouse button
         * so pass to the mouse button event handler to deal with it. This
         * includes the mouse wheel moving.
         */
        handle_mousebutton_event(&(transient_event.button), match_state);
      }
    }

    /*
     * Perform an update on all the ai objects.
     */
    ai_time_delta = SDL_GetTicks() - last_ai_update;
    process_all_player_ai(match_state->teams,
                          match_state->players_per_team,
                          ai_time_delta);
    last_ai_update = SDL_GetTicks();

    /*
     * Process the automaton timed event queue to see if any events need to be
     * popped.
     */
    pop_all_timed_events(match_state->automaton_handler->timed_event_queue,
                         SDL_GetTicks(),
                         match_state);

    /*
     * Do physics processing. This updates the positions of all moving entities
     * in the game.
     *
     * WARNING - If this takes longer than the amount of time allocated per
     * frame then there might be 'interesting' problems in the frame refresh.
     */
    physics_time_delta = SDL_GetTicks() - last_physics_update;
    calculate_positions(match_state,
                        physics_time_delta);
    last_physics_update = SDL_GetTicks();

    /*
     * Having moved all of the objects to their new positions we need to
     * detect collisions and verify the new locations.
     *
     * At the end of this function the positions of all objects will have been
     * updated.
     */
    detect_and_handle_collisions(match_state->teams,
                                 match_state->players_per_team,
                                 match_state->disc);

    /*
     * Update the camera object.
     */
    update_camera_position(match_state);

    /*
     * TODO: Is this management of animations sufficient?
     *
     * Update the animation frame counters.
     */
    if (SDL_GetTicks() - last_animation_update >= animation_ms_per_frame)
    {
      last_animation_update = SDL_GetTicks();
      for (ii = 0; ii < match_state->players_per_team; ii++)
      {
        increment_animation_frame_counter(match_state->teams[0]->players[ii],
                                          match_state->animation_handler);
        increment_animation_frame_counter(match_state->teams[1]->players[ii],
                                          match_state->animation_handler);
      }
    }

    /*
     * If the frame has taken less than the maximum allowed amount of time to
     * render then delay the screen update.
     */
    frame_time_taken_ms = SDL_GetTicks() - frame_start_time;
    if (frame_time_taken_ms < ms_per_frame)
    {
      SDL_Delay(ms_per_frame - frame_time_taken_ms);
    }

    /*
     * Redraw the screen.
     */
    redraw_screen(screen, match_state, font);
  }

  return(0);
}