SDL2游戏开发-tilemap瓦片图渲染

2020-09-14  本文已影响0人  追梦人在路上不断追寻

1.初始化SDL

#include <stdio.h>
#include <tmx.h>
#include <SDL.h>
#include <SDL_events.h>

#define DISPLAY_H 600
#define DISPLAY_W 800

static SDL_Renderer *ren = NULL;

Uint32 timer_func(Uint32 interval, void *param) {
  SDL_Event event;
  SDL_UserEvent userevent;

  userevent.type = SDL_USEREVENT;
  userevent.code = 0;
  userevent.data1 = NULL;
  userevent.data2 = NULL;

  event.type = SDL_USEREVENT;
  event.user = userevent;

  SDL_PushEvent(&event);
  return(interval);
}

int main(int argc, char **argv) {
  SDL_Window *win;
  SDL_Event ev;
  SDL_TimerID timer_id;

  SDL_SetMainReady();
  if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_EVENTS|SDL_INIT_TIMER) != 0) {
    fputs(SDL_GetError(), stderr);
    return 1;
  }

  if (!(win = SDL_CreateWindow("SDL2 example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DISPLAY_W, DISPLAY_H, SDL_WINDOW_SHOWN))) {
    fputs(SDL_GetError(), stderr);
    return 1;
  }

  if (!(ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC))) {
    fputs(SDL_GetError(), stderr);
    return 1;
  }

  SDL_EventState(SDL_MOUSEMOTION, SDL_DISABLE);

  timer_id = SDL_AddTimer(30, timer_func, NULL);

  while (SDL_WaitEvent(&ev)) {

    if (ev.type == SDL_QUIT) break;

    render_map(map); // Function to be implemented
    SDL_RenderPresent(ren);
  }

  SDL_RemoveTimer(timer_id);
  SDL_DestroyRenderer(ren);
  SDL_DestroyWindow(win);
  SDL_Quit();

  return 0;
}

2.加载map地图

tmx_map *map = tmx_load(argv[1]);
if (map == NULL) {
  tmx_perror("Cannot load map");
  return 1;
}

3.添加回调函数

void* SDL_tex_loader(const char *path) {
  return IMG_LoadTexture(ren, path);
}

/* Set the callback globs in the main function */
tmx_img_load_func = SDL_tex_loader;
tmx_img_free_func = (void (*)(void*))SDL_DestroyTexture;

tmx_map *map = tmx_load(argv[1]);
/* ... */
tmx_map_free(map);

4.声明渲染函数

void set_color(int color) {
  tmx_col_bytes col = tmx_col_to_bytes(color);
  SDL_SetRenderDrawColor(ren, col.r, col.g, col.b, col.a);
}

void render_map(tmx_map *map) {
  set_color(map->backgroundcolor);
  SDL_RenderClear(ren);
  draw_all_layers(map, map->ly_head); // Function to be implemented
}

5.绘制所有层

void draw_all_layers(tmx_map *map, tmx_layer *layers) {
  while (layers) {
    if (layers->visible) {

      if (layers->type == L_GROUP) {
        draw_all_layers(map, layers->content.group_head); // recursive call
      }
      else if (layers->type == L_OBJGR) {
        draw_objects(layers->content.objgr); // Function to be implemented
      }
      else if (layers->type == L_IMAGE) {
        draw_image_layer(layers->content.image); // Function to be implemented
      }
      else if (layers->type == L_LAYER) {
        draw_layer(map, layers); // Function to be implemented
      }
    }
    layers = layers->next;
  }
}

6.画出渲染图片

void draw_image_layer(tmx_image *image) {
  SDL_Rect dim;
  dim.x = dim.y = 0;

  SDL_Texture *texture = (SDL_Texture*)image->resource_image; // Texture loaded by libTMX
  SDL_QueryTexture(texture, NULL, NULL, &(dim.w), &(dim.h));
  SDL_RenderCopy(ren, texture, NULL, &dim);
}

7.声明渲染层函数

void draw_layer(tmx_map *map, tmx_layer *layer) {
  unsigned long i, j;
  unsigned int gid, x, y, w, h, flags;
  float op;
  tmx_tileset *ts;
  tmx_image *im;
  void* image;
  op = layer->opacity;
  for (i=0; i<map->height; i++) {
    for (j=0; j<map->width; j++) {
      gid = (layer->content.gids[(i*map->width)+j]) & TMX_FLIP_BITS_REMOVAL;
      if (map->tiles[gid] != NULL) {
        ts = map->tiles[gid]->tileset;
        im = map->tiles[gid]->image;
        x  = map->tiles[gid]->ul_x;
        y  = map->tiles[gid]->ul_y;
        w  = ts->tile_width;
        h  = ts->tile_height;
        if (im) {
          image = im->resource_image;
        }
        else {
          image = ts->image->resource_image;
        }
        flags = (layer->content.gids[(i*map->width)+j]) & ~TMX_FLIP_BITS_REMOVAL;
        draw_tile(image, x, y, w, h, j*ts->tile_width, i*ts->tile_height, op, flags); // Function to be implemented
      }
    }
  }
}

8.绘制物体和图形

void draw_polyline(double **points, double x, double y, int pointsc) {
  int i;
  for (i=1; i<pointsc; i++) {
    SDL_RenderDrawLine(ren, x+points[i-1][0], y+points[i-1][1], x+points[i][0], y+points[i][1]);
  }
}

void draw_polygon(double **points, double x, double y, int pointsc) {
  draw_polyline(points, x, y, pointsc);
  if (pointsc > 2) {
    SDL_RenderDrawLine(ren, x+points[0][0], y+points[0][1], x+points[pointsc-1][0], y+points[pointsc-1][1]);
  }
}

void draw_objects(tmx_object_group *objgr) {
  SDL_Rect rect;
  set_color(objgr->color);
  tmx_object *head = objgr->head;
  while (head) {
    if (head->visible) {
      if (head->obj_type == OT_SQUARE) {
        rect.x =     head->x;  rect.y =      head->y;
        rect.w = head->width;  rect.h = head->height;
        SDL_RenderDrawRect(ren, &rect);
      }
      else if (head->obj_type  == OT_POLYGON) {
        draw_polygon(head->content.shape->points, head->x, head->y, head->content.shape->points_len);
      }
      else if (head->obj_type == OT_POLYLINE) {
        draw_polyline(head->content.shape->points, head->x, head->y, head->content.shape->points_len);
      }
      else if (head->obj_type == OT_ELLIPSE) {
        /* FIXME: no function in SDL2 */
      }
    }
    head = head->next;
  }
}

libtmx构建条件

总结

绘制瓦片图就是逐层绘制瓦片,其中每个层都需要进行绘制。libTMX将映射加载到简单的旧C数据结构中,此页面全面介绍了该数据结构。 libTMX重用TMX格式中所有结构和结构成员的名称。

上一篇 下一篇

猜你喜欢

热点阅读