现在的位置: 首页 > 综合 > 正文

[转载]ApplePie的SDL经验

2013年05月21日 ⁄ 综合 ⁄ 共 4122字 ⁄ 字号 评论关闭

原文:http://fly19.51.net/applepie/
我发现在互联网上 有关于SDL的内容实在是太少了
甚至我在google上找不到关于SDL_ttf的资料

所以我觉得可以把我知道的 有关于SDL的知识和大家共享一下

我所知道的知识都是自己琢磨出来的 或是从英语资料里学来的
所以如果 我有说错的地方 请大家指出


至于sdl的主页 自己到google去找吧

我是用anjuta1.1.97 写sdl的 我不太喜欢kdevelop 因为我在gnome里

在anjuta的设定菜单里 选择“编译器及连接器设定” 
在 引用路径 里添加 /usr/include/SDL
在 函数库路径 里添加 /usr/lib
在 函数库 里添加 SDL ,SDL_image , SDL_ttf(可选, 这个ttf弄得我很郁闷 )  ,pthread(这个我也不知道是不是必须的)

好了 现在可以开始写了

#include "SDL.h"   /* All SDL App's need this */
#include <stdio.h>
int main() {
    printf("Initializing SDL./n");
    /* Initialize defaults, Video and Audio */
    if((SDL_Init(SDL_INIT_VIDEO)==-1)) {
        printf("Could not initialize SDL: %s./n", SDL_GetError());
        exit(1);
    }
    printf("SDL initialized./n");
    printf("Quiting SDL./n");
    /* Shutdown all subsystems */
    SDL_Quit();
    printf("Quiting..../n");
    exit(0);
}

如果以上这些代码编译通过的话 说明sdl没问题了


下面先来说说键盘的事情:
void rungame(void){
    SDL_Event event;
    Uint8 *keys;
    int goloop=1;
    while(goloop){
        while ( SDL_PollEvent(&event) ) {
            if ( event.type == SDL_QUIT )
                return;
        }
        keys = SDL_GetKeyState(NULL);    <----------------------
        if (keys[SDLK_ESCAPE] == SDL_PRESSED ) { <-------------------检查一个按键的值
            goloop=0;
        }
    }
    return;
}

SDL_GetKeyState这个函数在sdl的帮助文档里好象说的不多 感觉他们不鼓励使用这个函数
他们的帮助文件里使用的是SDL_PollEvent(&event)  直接从event里判断键盘的值
问题是 他不能同时返回两个键同时按下的情况  比如你在游戏里 一边砍人一边前进 就会有问题
虽然也可一用设置一个变量的方法解决(sdl主页上有个例子) 但我觉得麻烦

我觉得SDL_GetKeyState用的方便 虽然也有缺点
缺点是 必须不停的调用这个函数  结果是cpu利用率到100%  但是有谁会在意玩游戏时候的cpu呢?


下面说说图片:
比忘了加一句 #include "SDL_image"

SDL_Surface是用的最多的一个东西   虽然我对它的了解还不多

所以我找了一个现成的函数:
SDL_Surface *LoadImage(char *filename, int transparent,Uint32 key){
    SDL_Surface *image, *surface;
    image = IMG_Load(filename);
    if ( image == NULL ) {
        fprintf(stderr, "Couldn't load image %s: %s/n",
                    filename, IMG_GetError());
        return NULL;
    }
    if ( transparent ) {
        SDL_SetColorKey(image, (SDL_SRCCOLORKEY|SDL_RLEACCEL), key);
    }
    surface = SDL_DisplayFormat(image);
    SDL_FreeSurface(image);
    return(surface);
}
这个函数是从 sdl主页上的一个例子里拿来的
函数里的那个Uint32 key是我自己加上去的  原函数里没有  用来决定哪一种颜色是透明的  比如  0xFFFF00 之类的
 SDL_SetColorKey 不完全明白它的作用  所以在这里也不敢乱说
还有一个问题
虽然 image = IMG_Load(filename); 里的image不为空了
但是 surface = SDL_DisplayFormat(image); 的surface还有可能为空  最好检查一下  不知道啥原因 原作者没有检查
我还不知道 IMG_Load(filename); 里能不能用 jpg 或者 png 我使用的是bmp
总之 经过千辛万苦 你已经把一张bmp文件 变成了 SDL_Surface

下面我想偷工减料了
SDL_FillRect的作用看名字就知道 常用它清空一个SDL_Surface
如:SDL_FillRect(surface,NULL,0);

SDL_BlitSurface 用于把一个SDL_Surface复制到另一个上
懒得说了  去看看sdl的网站吧

SDL_UpdateRect(screen, 0, 0, 0, 0);用来更新屏幕  后面4个值就是坐标 如果都为0 就是更新整个屏幕

sdl主页上还有一些 不知其所云的函数  小弟笨 没看明白


下面说最让我恼火的 SDL_ttf 的问题
他的作用是在surface上写字 需要freetype 2.0以上的支持
http://www.libsdl.org/projects/SDL_ttf/   有下载

先:
if(TTF_Init()==-1) {
    printf("TTF_Init: %s/n", TTF_GetError());
    exit(2);
}

后加载ttf文件:
TTF_Font *font;
font=TTF_OpenFont("font.ttf", 16);  <---这是看某个介绍 然后照抄的后来觉得他写的不对  也可能是我误解了
if(!font) {
   
printf("TTF_OpenFont: %s/n", TTF_GetError());
}

我本以为TTF_OpenFont里的 "font.ttf" 的路径是固定的 或者说是由SDL_ttf自己决定的
但是后来发现这里一定要写相对路径 或者是绝对路径 否则就会出错
而且TTF_OpenFont 还有一个问题  只要你ttf的文件不存在 直接就会出现段错误 不会返回错误 据说是个bug
受到这个介绍的误导 浪费了很多时间  已经让我很恼火了

下面说一件更恼火的事情:
SDL_Surface *image;
image=TTF_RenderText_Solid(font,"abc",color);
TTF_RenderText_Solid用来把文字变成一个SDL_Surface    第一个参数是上文里的font  第三个参数color是一个SDL_Color
如果不出意外的话 image里 应该有了 abc 三个字了  但是不幸的是意外发生了
我反复检查了 font 和 color 的准确性 发觉都没问题 但是 image始终是null
如果你使用的是windows上的sdl 那么应该不会有这种问题 
但我用的是redhat9.0  freetype的版本是2.1.4   SDL是1.25-3    SDL_ttf是2.0.6-1 
后来到网站上去看 发觉不只是我一个人有这样的问题  
但没有发觉一个解决方法  我也没有找到(或者是找到了 但我没看明白)出现这种问题的原因

这下完了  编译通过的 但是不能用   郁闷吧!

没办法  以后要在游戏里用文字 只能用gimp画成bmp了


关于sdl_ttf的问题  我已经解决了
TTF_RenderText_Solid 是不能使用 但是可以用另一个函数代替
用TTF_RenderText_Blended  用法一样  不过我只用这个函数画过英文字  我想中文应该没问题

还有关于避免TTF_OpenFont时出现段错误的问题  我看过别人的源代码了
方法爆简单 用 <fstream>先检查文件是否存在
std::ifstream ifile(fontname);
if(ifile.fail()){
    std::cout << "file not found:" << fontname << std::endl;
    return ERR;
}
font = TTF_OpenFont(fontname,size);
if(font == NULL){
    std::cout << "Openfont Error:" << TTF_GetError() << std::endl;
    return ERR;
}

不过这样只能检查文件是否存在  如果ttf文件是一个空文件  这就没办法了  不过我还没遇到过这种问题


记得我上一次说过画中文字是很容易的吗?   我是胡扯的!
后来发觉编码问题
如果编码不对 画出来的中文都是小方格

后来自己慢慢看网上的帖子 找到了方法:
首先把带有中文字的源文件以 unicode(UTF-8) 保存 
你可以使用gedit  在保存的时候会有一个选项的    windows里我不知道用啥 editplus? maybe

然后使用 TTF_RenderUTF8_Blended(font,text,color);  函数画 就可以了
你可以下载
shoufont.c 和他的 makefile  这个文件是在sdl网站上找到的  这个文件不能显示中文  却是一个很好的例子
还有一个文件是我自己写的  可以在
这里下载    不过需要修改一下:在Label.h的16行 把我写的字体文件位置改掉

 

抱歉!评论已关闭.