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构建条件
- AC编译器(Clang,GCC …)libTMX是用C89编写的,但使用的
<stdint.h>
是C99标准的标头,因此,只要您提供该标头,就可以使用C89编译器来构建libTMX。 - ZLib用于解压缩图层(可选,在属性中选择未压缩的图层格式)。
- libxml2加载地图;libTMX使用IO api从各种来源加载(提示:如果libxml2是使用内置HTTP客户端构建的,那么libTMX将能够通过HTTP从远程服务器加载地图),以及xmlreader api来解析XML文档,和哈希API作为哈希表实现。
- 该CMake的构建系统制造商。
总结
绘制瓦片图就是逐层绘制瓦片,其中每个层都需要进行绘制。libTMX将映射加载到简单的旧C数据结构中,此页面全面介绍了该数据结构。 libTMX重用TMX格式中所有结构和结构成员的名称。