I am trying to get a knight on a horse (inauspiciously named "guy") to run across the screen. The knight currently exists in my directory as 2 .png files, to simulate some poorly animated galloping. I was able to get him to appear when he was a .bmp, but I would like to utilize the transparency of png files - I've also tried and failed with opening tif files. How can I alter my code in order to get him to appear from a .png loaded into SDL correctly?
Here is my .cpp file:
#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 );
}
As I currently have it, the knight does not appear and I receive no errors (a consequence of the SDL screen being open?) Fail checks such as
if(!guy) {
cout << "IMG_LoadPNG_RW: %s\n" << IMG_GetError();
}
Have also yielded no results. my .h file is simply:
#include "SDL/SDL.h"
#include <iostream>
using namespace std;
int source_sdl( int argc, char* args[] );
And my 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 );
}
If you really want to stick with SDL in C++, I suggest you to use the SDL_image library and use a function like :
SDL_Surface * loadImage(std::string const & filename)
{
SDL_Surface * img = nullptr;
SDL_Surface * tmp = IMG_Load(filename.c_str());
if (tmp)
{
img = SDL_DisplayFormatAlpha(tmp);
SDL_FreeSurface(tmp);
}
return img;
}
An example of a more modern and safe approach would looke like this:
using SurfacePtr = std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)>;
SurfacePtr loadImage(std::string const & filename)
{
SurfacePtr img { nullptr, &SDL_FreeSurface };
SurfacePtr tmp { IMG_Load(filename.c_str()), &SDL_FreeSurface };
if (tmp)
img.reset(SDL_DisplayFormatAlpha(tmp.get()));
return img;
}
Or better, use an existing C++ Binding like libSDL2pp (I have nothing to do with them).