Sign in to follow this  
DanielWilkins

SDL - Creating surface with blits only renders one black square

Recommended Posts

DanielWilkins    108
Hi. I am writing a Bomberman clone and trying to blit parts of an explosion to a surface and then render that surface but have ran into problems. Here is my function:


[CODE]
SDL_Surface* SpriteManager::buildExplosion(int id, SDL_Surface* image, int size)
{
// Create the surface that will hold the explosion image
SDL_Surface* explosion = SDL_CreateRGBSurface(SDL_SRCALPHA, size * 32 , size * 32, 32, 0, 0, 0, 0 );

// Our source and destination surfaces
SDL_Rect srcrect;
SDL_Rect dstrect;

int parentX = sprites[id].x;
int parentY = sprites[id].y;
int middle = size / 2;

// Create the first image
srcrect.x = sprites[id].imgBlockX * 32; // default for now
srcrect.y = sprites[id].imgBlockY * 32; // default for now
srcrect.w = 32;
srcrect.h = 32;

// Get the location it should be applied to
dstrect.x = middle * 32;
dstrect.y = middle * 32;
dstrect.w = 32;
dstrect.h = 32;

// Apply the texture
SDL_BlitSurface(image, &srcrect, explosion, &dstrect);

return explosion;
}[/CODE]

As of now, it only blits the 32x32 tile at 0,0 in the image to the middle of the destination tile. I am 99% sure all the code here is correct as my debug output is consistent with where everything should be. What it ends up doing is producing an image that is the correct size BUT only has a 32x32 black tile in the upper left hand corner. I am wondering if there is a problem with the fact I am blitting from an image with an alpha mask.

Here is the image:

[url="http://i.imgur.com/eKD88.png"][img]http://i.imgur.com/eKD88.png[/img][/url]

So to recap:

I am blitting the first tile at 0, 0 with size 32x32 to the middle of the surface I have created.
What ends up happening is that it only renders a single 32x32 black tile in the upper left hand corner of the created surface (at least I know the surface is rendering in the correct place)

[url="http://i.imgur.com/cRzLk.png"][img]http://i.imgur.com/cRzLk.png[/img][/url]

In the above picture, the upper left player dropped a bomb and it exploded. It had a power of 2 meaning that the box was 5 tiles in width and height.

Let me know if you have any questions. Thank you. Edited by Chanz

Share this post


Link to post
Share on other sites
DanielWilkins    108
Bump. And I think I overly confused people. Here is what I am trying to do:

I am trying to create a composite surface by blitting to that surface. I need the surface to be initially transparent and I need to blit the image I linked above which has transparency onto it.

If need be, I can also color the background of the explosion image I linked pink and use an alpha key if that works with SDL.

Any advice? Edited by Chanz

Share this post


Link to post
Share on other sites
thecoast47    255
It looks like your blitting parts of the spritesheet to locations that dont exist on the newly allocated surface.
Right now im failing to understand the purpose of the dstrect variable.
It looks like you should just set that parameter to NULL.
Again i'm not sure why you're creating new surfaces of the same image just to render certain areas of that image when you can do the same thing with SDL_BlitSurface. It honestly just seems like a waste of memory.
Anyway,who am i to judge?
Here's a SDL app that loads the individual tiles from the sprite sheet into separate surfaces.
[source lang="cpp"]#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <stdlib.h>
#include <Math.h>
#include <vector>

SDL_Surface * mainSurface = NULL;
SDL_Event g_Event;
SDL_Surface * spriteSheet = NULL;
std::vector<SDL_Surface*> subSurfaceList;
bool running = true;

void handleEvents(SDL_Event & event){
if(event.type == SDL_QUIT){
running = false;
}
}

void getSubSurfaces(){
SDL_Rect sheetArea;
sheetArea.w = 32;
sheetArea.h = 32;
for(unsigned int y = 0; y < 4; y++){
for(unsigned int x = 0; x < 7; x++){
sheetArea.x = x*32;
sheetArea.y = y*32;
SDL_Surface * newSurface = SDL_CreateRGBSurface(SDL_HWSURFACE,32,32,32,0,0,0,0);
SDL_BlitSurface(spriteSheet,&sheetArea,newSurface,NULL);
subSurfaceList.push_back(newSurface);
}
}
}

void clearSurface(SDL_Surface * surface,int r,int g, int b){
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = surface->w;
rect.h = surface->h;

Uint32 color = SDL_MapRGB(surface->format,r,g,b);
SDL_FillRect(surface,&rect,color);
}

int main ( int argc, char** argv ){
//initalizing SDL
if(SDL_Init(SDL_INIT_VIDEO) == -1){
fprintf(stderr,"Failed to Initalize Video\n");
return 0;
}else{
fprintf(stdout,"Suceeded to Initalize Video\n");
atexit(SDL_Quit);
}
//setup window
mainSurface = SDL_SetVideoMode(640,480,32,SDL_RESIZABLE | SDL_HWACCEL | SDL_DOUBLEBUF);
//load sprite
spriteSheet = IMG_Load("spriteSheet.png");
getSubSurfaces();

//begin main loop
int index = 0;
int size = subSurfaceList.size();
SDL_Rect sheetArea;
sheetArea.x = 0;
sheetArea.y = 0;
sheetArea.w = 32;
sheetArea.h = 32;

while(running){
SDL_PollEvent(&g_Event);
SDL_Flip(mainSurface);
handleEvents(g_Event);
clearSurface(mainSurface,0,0,0);

index = (index +1) % size;
SDL_BlitSurface(subSurfaceList[index],&sheetArea,mainSurface,NULL);

SDL_Delay(1000);
}
return 0;
}[/source]

Again i'm not sure why you're loading tiles into separate surfaces, I highly recommend that you just use the sprite sheet itself as the source and blit parts of the sprite sheet onto the main surface like this:
[source lang="cpp"]void renderExplosion(int x,int y,int intensity,int orientation,SDL_Surface* explositonSheet,SDL_Surface * mainSurface){
SDL_Rect sheetArea;
SDL_Rect sheetPosition;

sheetPosition.x = x;
sheetPosition.y = y;
sheetPosition.w = mainSurface->w;
sheetPosition.h = mainSurface->h;

sheetArea.w = 32;
sheetArea.h = 32;

sheetArea.x = (orientation%7 )*32;
sheetArea.y = (intensity%4)*32;
SDL_BlitSurface(explositonSheet,&sheetArea,mainSurface,&sheetPosition);
}[/source]

Share this post


Link to post
Share on other sites
DanielWilkins    108
Thank you for the reply. Someone else suggested SDL_gfx which supports blitting semi transparent surfaces to other semitransparent surfaces (RGBA to RGBA). It works perfectly. To recap, the reason I do this is so I build the sprite completely and then ship it off to the renderer without sending them in pieces (8 or 9 render calls per explosion).

Cheers!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this