赞
踩
在游戏开发中,使用的图片一般情况下的格式为PNG,在我看来PNG有着以下几个好处:
以上的几个特性使得PNG在游戏开发中大放异彩。另外,主流就是使用PNG+TexturePacker,把碎图整合成一张大的图片(一般是POT Power Of Two,图片的宽和高是2的幂),然后再在程序中使用。这样做的好处主要是为了兼容旧的设备、方便对齐处理以及字节对齐。
SDL支持一些主流的图片格式,比如png、jpg等。而这其中并不包括GIF。
表情包经常会出现各种各样的动图,这种大多是GIF。一个GIF格式的图片文件中内部一般都会有着多于一帧的图片,由于GIF格式的特性,使得它在每隔一段时间会切换当前显示的图片,以达到动画的效果,这也是目前的2D游戏中的动画的最常用的形式。
如上图,则是一个标准的动图。
虽然SDL官方并没有提供一个解析GIF的方式,不过网上是有着对应的库的。
这个并不是我开发的,是一个外国人,好像从2006年起就没有更新过了,在以前心血来潮,就发了封邮件给SDL官方,官方说并不提供 animated gif,然后推荐了个网址,源文件是以SDL1.x写的,因为现在的主流是SDL2,所以就稍微改变了下代码。
SDL_AniGIF是我更改后的文件,SDL_AniGIF-1.0.0是原先的文件,具体关于gif解码的,我就不多说了(我也不会。。)见附件
在游戏开发中,一般的动画是每隔一段时间就切换图片,如果第一张和倒数第二张图片有着明显连贯性的时候,就会感觉到非常流畅,就比如上面贴的关羽的图片。
SDL_angif会先判断这个文件有着几帧,之后在申请到足够的空间后调用相应的函数后,就会得到一个帧数组,它里面包含着每一帧图片以及对应的坐标(在这里指的是SDL_Surface,如果使用的SDL 2.x,建议转换成SDL_Texture)以及该图片的持续时间。注意需要预先设置好SDL2的开发环境。
代码:
- #include <iostream>
- #include <SDL.h>
- #include <cstdio>
- #include <vector>
-
- #include "SDL_anigif.h"
- using namespace std;
首先包含到这个例子所需要的库文件和外国热心网友写的gif解析库。
- int main(int argc,char**argv)
- {
- SDL_Event event;
- bool g_bRunning = true;
- int currentFrame = 0;
- SDL_Init(SDL_INIT_EVERYTHING);
- SDL_Window*gWin = SDL_CreateWindow("gif test",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,640,480,SDL_WINDOW_SHOWN);
- SDL_Renderer*gRen = SDL_CreateRenderer(gWin,-1,SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
使用SDL的时候,需要先初始化SDL库(SDL_Init),接着创建一个窗口(SDL_CreateWindow)和渲染器(SDL_CreateRenderer)。
- //先获取最大数量
- int number = AG_LoadGIF("2.gif",NULL,0);
- AG_Frame*frames = new AG_Frame[number];
- AG_LoadGIF("2.gif",frames,number);
SDL_angif库仅仅提供了几个简单的函数,而用得最多的就是AG_LoadGIF,它的使用过程如下:
- //由frames创建texture
- std::vector<SDL_Texture*> textures;
- for(int i=0;i<number;i++)
- {
- SDL_Texture*texture = SDL_CreateTextureFromSurface(gRen,frames[i].surface);
- textures.push_back(texture);
- }
SDL 1.x使用的是SDL_Surface进行图片的绘制;而在SDL 2.x后,就转而创建了一个新的结构体SDL_Texture,代替了SDL_Surface的大部分功能。
- SDL_Rect destRect = { 0,0,0,0 };
- SDL_Rect srcRect = { 0, 0, 0, 0 };
- SDL_SetRenderDrawColor(gRen,255,200,100,255);
- while(g_bRunning)
- {
- //①
- while(SDL_PollEvent(&event))
- {
- switch(event.type)
- {
- case SDL_QUIT:
- g_bRunning = false;
- break;
- }
- }
- //②
- SDL_RenderClear(gRen);
-
- destRect.x = frames[currentFrame].x;
- destRect.y = frames[currentFrame].y;
- srcRect.w = destRect.w = frames[currentFrame].surface->w;
- srcRect.h = destRect.h = frames[currentFrame].surface->h;
-
- SDL_RenderCopy(gRen, textures.at(currentFrame), &srcRect, &destRect);
- SDL_RenderPresent(gRen);
- SDL_Delay(frames[currentFrame].delay);
- currentFrame = (currentFrame + 1) % number;
- }
无论什么游戏,其底层一般都是一个大的循环体,在这个循环体的内部则进行绘制以及事件响应等。
在①处注释中,这个循环体是为了从事件队列中拿取事件,使用循环的原因是要在每次循环时把事件队列取空,以避免延迟响应。
在②处注释后,则是具体的绘制代码,SDL_RenderClear()的功能是清空画布;而SDL_RenderPresent()则是把已经绘制的图片显示到画布上。由于SDL内部提供了双缓冲机制,所以一般不需要自己再实现双缓冲机制。
在SDL_RenderClear()和SDL_RenderPresent()的中间进行调用绘制函数进行绘制即可。
在之前的AG_LoadGIF中,已经读取到了图片,所以在这个时候只需要调用SDL_RenderCopy()绘制图片即可。srcRect表示从源图片中按照srcRect进行提取;然后把取出的图片绘制到destRect大小的矩形之中。
虽然是同一个GIF,但是内部的图片的大小和偏移可能会不同,所以在绘制的过程中还需要加上一定的偏移。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。