【问题标题】:Displaying a .png file in SDL using C++使用 C++ 在 SDL 中显示 .png 文件
【发布时间】:2014-05-07 12:29:48
【问题描述】:

用 C++ 编写:我试图让骑在马上的骑士(不吉利地命名为“家伙”)穿过屏幕。骑士目前作为 2 个 .png 文件存在于我的目录中,以模拟一些动画效果不佳的疾驰。当他是 .bmp 时,我能够让他出现,但我想利用 png 文件的透明度——我也尝试过打开 tif 文件但失败了。如何更改我的代码以使他从正确加载到 SDL 的 .png 中出现?这是我的 .cpp 文件:

#include "SDL/SDL.h"
#include <iostream>
#include "source_sdl.h"
# include <string>

using namespace std;

int source_sdl( int argc, char* args[] ) {

int switch = 1;
int running = 1;

// surface & rect declarations
SDL_Surface* ground = NULL;
SDL_Surface* guy = NULL;
SDL_Surface* guy2 = NULL;
SDL_Rect guylocationRect;
SDL_Rect groundlocationRect;

// initialize SDL & the screen
SDL_Init( SDL_INIT_EVERYTHING );
screen = SDL_SetVideoMode( 875, 625, 32, SDL_SWSURFACE );

// open .png files
SDL_RWops* guy_rwop;
SDL_RWops* guy2_rwop;
guy_rwop = SDL_RWFromFile("tiffKnight.png", "rb");
guy2_rwop = SDL_RWFromFile("tiffKnight2.png", "rb");
guy = IMG_LoadPNG_RW(guy_rwop);
guy2 = IMG_LoadPNG_RW(guy2_rwop);
guylocationRect.x = 300;
guylocationRect.y = 300;
groundlocationRect.x = 300;
groundlocationRect.y = 300;

SDL_Event occur;

// animation loop (currently endless)
while (running == 1){

    SDL_Flip( screen );
    SDL_Delay( 300 );

    if (gallop > 89) gallop=0;

    // draw the ground
    for( int yu = 0; yu<35; yu++){
         groundlocationRect.x=25*yu;
         groundlocationRect.y=5*25;
         SDL_BlitSurface( ground, NULL, screen, &groundlocationRect );
    }
    // draw the gallopping
    guylocationRect.x=10*gallop;
    guylocationRect.y=5*25;
    if( switch ){
        SDL_BlitSurface( guy, NULL, screen, &guylocationRect );
    }else{
        SDL_BlitSurface( guy2, NULL, screen, &guylocationRect );
    }
    gallop++;
    switch = (switch+1)%2;
    for(int u = 6; u < 25; u++){
        for(int yu = 0; yu < 35; yu++){ 
            groundlocationRect.x = 25*yu;
            groundlocationRect.y = 25*u;
            SDL_BlitSurface( ground, NULL, screen, &groundlocationRect );
        }
    }
}
SDL_FreeSurface( guy );
SDL_FreeSurface( guy2 );
SDL_FreeSurface( ground );
}

正如我目前拥有的那样,骑士没有出现,我也没有收到任何错误(SDL 屏幕打开的结果?)失败检查,例如

if(!guy) {
    cout << "IMG_LoadPNG_RW: %s\n" << IMG_GetError();
}

也没有产生任何结果。我的 .h 文件很简单:

#include "SDL/SDL.h"
#include <iostream>

using namespace std;
 int source_sdl( int argc, char* args[] );

还有我的 main.cpp:

#include "SDL/SDL.h"
#include <iostream>
#include "source_sdl.h"
using namespace std;

int main( int argc, char* args[] ){

    source_sdl( argc, args );

}

任何见解都会很棒,因为这个骑士最终应该是塔防游戏中的敌人!提前谢谢!

这是我从中获得有关如何将不同文件类型加载到 SDL 中的信息的页面:http://www.libsdl.org/projects/SDL_image/docs/SDL_image.html#SEC24

【问题讨论】:

  • 因为 guy 是 != null 您可以尝试查看加载的表面是否符合预期: printf("Surface %s: w:%dh:%d bpp:%d\n", " guy", guy->w, guy->h, guy->format->BitsPerPixel);
  • 也许检查 SDL_BlitSurface 返回码?
  • 只是出于好奇:在 C++ 中编码时为什么要使用 SDL?那么SFML不是更好的选择吗?由于 SDL 是基于 C 的,而 SFML 是基于 C++ 的。
  • 为什么要使用表面?纹理更快。您可以使用 IMG_LoadTexture() 轻松将 .png 加载到纹理中。

标签: c++ png sdl


【解决方案1】:

如果你真的想在 C++ 中坚持使用 SDL,我建议你使用 SDL_image library 并使用如下函数:

SDL_Surface * load_image(std::string const & filename)
{
    SDL_Surface * tmp;
    SDL_Surface * img;

    img = NULL;
    if ((tmp = IMG_Load(filename.c_str())))
    {
      img = SDL_DisplayFormatAlpha(tmp);
      SDL_FreeSurface(tmp);
    }
    return img;
}

如果您想要使用该库的更现代、更安全的方法:

surface_ptr load_image (std::string const & filename)
{
    using surface_ptr = std::unique_ptr<SDL_Surface, decltype(SDL_FreeSurface) *>;

    surface_ptr img { nullptr, SDL_FreeSurface };
    surface_ptr tmp { IMG_Load(filename.c_str()), SDL_FreeSurface };

    if (tmp)
        img.reset(SDL_DisplayFormatAlpha(tmp.get()));

    return img;
}

【讨论】:

  • 我在理解现代方法中的一些语法时遇到了麻烦,也许只是因为 MSVC++ 2012 不会编译它...是否有替代方案(更清晰/更传统也许?)surface_ptr img { nullptr, SDL_FreeSurface }; 的语法?
  • 当然,改用surface_ptr img(nullptr, SDL_FreeSurface);
猜你喜欢
  • 2017-05-19
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-05-11
  • 2014-10-06
  • 1970-01-01
  • 1970-01-01
  • 2020-11-09
相关资源
最近更新 更多