Sign in to follow this  

SDL - object not drawing itself

This topic is 3772 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I'm working on a mini game, where a bunch of flies randomly pop up and you have o hit it with a hammer. Nothing great just to practice coding, anyway I started off with the flies being structs and all the logic and drawing was done by stand alone functions. I moved all of this to a fly class and I basically call one function in the main loop to do all of this. Now it stopped working, the flies are simply not being blitted onto the screen. This is the function being called in main.
void Fly::draw_fly(SDL_Surface* _screen)
{
    if ((this->isDead) && (this->isVisible))
    {
        if (this->deadTime.get_time() > 1000)
        {
            this->isVisible = false;
            this->visibleTime.reset();
        }
    }

    if (!this->isVisible)
    {
        if (this->visibleTime.get_time() > 2000)
        {
            this->get_random_pos();
            this->isDead = false;
            this->isVisible = false;
        }
    }

    if (this->isVisible)
    {
        if (this->isDead)
        {
            apply_surface(this->xPos, this->yPos, this->dead, _screen);
        }
        else
        {
            apply_surface(this->xPos, this->yPos, this->dead, _screen);
        }
    }
}
I just call it in main and pass it the screen surface. apply_surface is the same function from LazyFoo's tuts. I've stepped through the code and I know that it is calling apply_surface. Any ideas? Please, I've already got a bald patch from pulling out my hair.

Share this post


Link to post
Share on other sites
[quote]Original post by TooLSHeD
...

void Fly::draw_fly(SDL_Surface* _screen)
{
...
if (this->isVisible)
{
if (this->isDead)
{
apply_surface(this->xPos, this->yPos, this->dead, _screen);
}
else
{
apply_surface(this->xPos, this->yPos, this->dead, _screen);
}
}
}



....[/quote]

Nothing to do with your problem I think but are you sure you want to draw the dead picture even if the Objekt is not dead? Looks like a copy and paste error.

Share this post


Link to post
Share on other sites
just reading the code logically i found that in your second if statment, you need to set isVisible to true, not false; its already false, and since its not visible, its not being drawn.


if (!this->isVisible)
{
if (this->visibleTime.get_time() > 2000)
{
this->get_random_pos();
this->isDead = false;
//set isVisible to true
//this->isVisible = false;
this->isVisible = true;

}
}



i think this is your issue. i may have misread your purpose.
but it looks like you want to redraw the fly if its dead after 2000ms

Share this post


Link to post
Share on other sites
Quote:
Original post by Lazy Foo
We'll need to see how draw_fly is being used.

It's basically being called in the main loop with the global screen surface being passed to it, right after the background is blitted onto the screen.

Quote:
Original post by dragongame
Quote:
Original post by TooLSHeD
...
*** Source Snippet Removed ***
....


Nothing to do with your problem I think but are you sure you want to draw the dead picture even if the Objekt is not dead? Looks like a copy and paste error.

Ah yes thanks, it is a copy and paste error.

And thanks mindrot, I changed it, but it still doesn't work.

Share this post


Link to post
Share on other sites
Here it is, please note: still work in progress, please criticize anything else while you're at it.

main.cpp

#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#ifdef __APPLE__
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#else
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#endif

#include <string>
#include <sstream>
#include <ctime>
#include "Timer.h"
#include "functions.h"
#include "Fly.h"

// Some global(BAD!) constants.
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

// Maximum flies allowed on the screen.
#define MAX_FLIES 10

//The surfaces that will be used.
SDL_Surface* screen = NULL;
SDL_Surface* background = NULL;
SDL_Surface* fpsText = NULL;

// Hammer struct, this combines all the variables needed
typedef struct
{
int posX; // x position.
int posY; // y position.
int width; // Width.
int height; // Height.
SDL_Surface* up; // Up position.
SDL_Surface* down; // Down position.
bool isDown; // Down if true, else up.
} Hammer;

// Instance of Hammer, this is the main hammer.
Hammer hammer;

// flyCount, records the number of alive flies
int flyCount = 0;

// flyAlive and flyDead holds the respective surfaces
// so that it isn't loaded everytime a new fly is created.
SDL_Surface* flyAlive = NULL;
SDL_Surface* flyDead = NULL;

// The TTF fonts.
TTF_Font *fpsFont = NULL; // Font used to display the frames per second.

// Font Colors.
SDL_Color fpsFGTextColor = {255, 0, 0}; // Color for the fps foreground font.
SDL_Color fpsBGTextColor = {255, 255, 255}; // Color for the fps background font.

// Handle events.
SDL_Event event;

// get_random_x returns a random value between 25 and 590.
int get_random_x()
{
return((rand()%590) + 25);
}

// get_random_y returns a random value between 25 and 430.
int get_random_y()
{
return((rand()%430) + 25);
}

// load_image, loads any image format and converts it
// to a SDL_Surface, thanks LazyFoo.
SDL_Surface* load_image(std::string filename)
{
// The image that is loaded
SDL_Surface* loadedImage = NULL;

// The optimized image that will be used.
SDL_Surface* optimizedImage = NULL;

// Load the image using SDL_image.
loadedImage = IMG_Load(filename.c_str());

if (loadedImage != NULL)
{
// Create optimized image.
optimizedImage = SDL_DisplayFormat(loadedImage);

// Free the old image.
SDL_FreeSurface(loadedImage);
}

if (optimizedImage != NULL)
{
// Create a color key so that a chosen color can be transparent.
Uint32 colorKey = SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF);

// Set all the pixel with the color value of
// 00FFFF to be transparent
SDL_SetColorKey(optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorKey);
}

return(optimizedImage);
}

// apply_surface blits one surface onto another
// thanks again LazyFoo!
void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination)
{
// Make a temporary rectangle to hold the offsets.
SDL_Rect offset;

// Give the offsets to the rectangle.
offset.x = x;
offset.y = y;

// Blit the surface.
SDL_BlitSurface(source, NULL, destination, &offset);
}

// Initializes everything
bool init()
{
// Seed the random number generator.
srand(time(0));

// Initialize SDL.
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
printf("SDL_init FAILED: %s", SDL_GetError());
return(false);
}

// Set up the screen.
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);

// Check if there was an error.
if (screen == NULL)
{
printf("SDL_SetVideoMode FAILED: %s", SDL_GetError());
return(false);
}

// Initialize TTF
if (TTF_Init() == -1)
{
printf("TTF_Init FAILED: %s", SDL_GetError());
return(false);
}

// Set the window caption.
SDL_WM_SetCaption("Splat", NULL);

// Initialize all the hammer variables
hammer.down = NULL;
hammer.up = NULL;
hammer.isDown = false;
hammer.posX = 0;
hammer.posY = 0;
hammer.width = 50;
hammer.height = 50;

// Initialize the flies, this is the only case when
// the files aren't loaded in load_files().
flyAlive = load_image("images/fly_alive.png");
if (flyAlive == NULL)
{
printf("load_image FAILED: %s", SDL_GetError());
return(false);
}

flyDead = load_image("images/fly_dead.png");
if (flyDead == NULL)
{
printf("load_image FAILED: %s", SDL_GetError());
return(false);
}

// Hide the cursor
SDL_ShowCursor(SDL_DISABLE);

return(true);
}

// Load all the needed files
bool load_files()
{
// Load the background.
background = load_image("images/background.png");
if (background == NULL)
{
printf("load_image FAILED: %s", SDL_GetError());
return(false);
}

// Load the hammer up position
hammer.up = load_image("images/hammer_up.png");
if (hammer.up == NULL)
{
printf("load_image FAILED: %s", SDL_GetError());
return(false);
}

// Load the hammer up position
hammer.down = load_image("images/hammer_down.png");
if (hammer.up == NULL)
{
printf("load_image FAILED: %s", SDL_GetError());
return(false);
}

// Load the font.
fpsFont = TTF_OpenFont("images/comic.ttf", 12);
if (fpsFont == NULL)
{
printf("TTF_OpenFont FAILED: %s", SDL_GetError());
return(false);
}

return(true);
}


// clean_up, free all the surfaces and quit.
void clean_up()
{
// Free the background surface.
SDL_FreeSurface(background);

// Free the text surface.
SDL_FreeSurface(fpsText);

SDL_FreeSurface(flyAlive);
SDL_FreeSurface(flyDead);

SDL_FreeSurface(hammer.down);
SDL_FreeSurface(hammer.up);

// Free the fornt.
TTF_CloseFont(fpsFont);

// Quit TTF.
TTF_Quit();

// Quit SDL.
SDL_Quit();
}

int main (int argc, char** argv)
{
// Quit flag;
bool quit = false;
bool mouseDown = false; // Is the mouse button being held down?

// Mouse coords
int mouseX = 0;
int mouseY = 0;

Fly fly(flyAlive, flyDead);

// Timer instance.
Timer time = Timer();

int frameCount = 0; // The number of frames per second.

// Used to output the fps.
std::stringstream fps;

if (!init())
{
return 1;
}

if (!load_files())
{
return 1;
}

// Apply the background to the screen.
apply_surface(0, 0, background, screen);

// Update the screen
if (SDL_Flip(screen) == -1)
{
printf(SDL_GetError());
SDL_Quit();
return 1;
}

time.start();

fps << "FPS: 0";

while (quit == false)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
quit = true;
}

// Check if the mouse button is being pressed.
if (event.type == SDL_MOUSEBUTTONDOWN)
{
hammer.isDown = true;

if (!mouseDown)
{
fly.is_hit(event.motion.x, event.motion.y);
}

mouseDown = true;

}

if (event.type == SDL_MOUSEBUTTONUP)
{
hammer.isDown = false;
mouseDown = false;
}

// Track the mouse motion
if (event.type == SDL_MOUSEMOTION)
{
mouseX = event.motion.x;
mouseY = event.motion.y;
}
}

fpsText = TTF_RenderText_Shaded(fpsFont, fps.str().c_str(), fpsFGTextColor,
fpsBGTextColor);

// Apply the background to the screen.
apply_surface(0, 0, background, screen);

fly.draw_fly(screen);

// Apply the hammer.
// set the pointer in the middle of the hammer, thus position - 25.
if (hammer.isDown)
{
apply_surface(mouseX - 25, mouseY - 25, hammer.down, screen);
}
else
{
apply_surface(mouseX - 25, mouseY - 25, hammer.up, screen);
}

// Apply the fps text.
apply_surface(20, 450, fpsText, screen);

// Update the screen.
if (SDL_Flip(screen) == -1)
{
printf(SDL_GetError());
clean_up();
return 1;
}

// Calculate the frames per second.
if (time.get_time() >= 1000)
{
// If the time elapsed is greater than 1s
// then reset the timer.
time.reset();
// Clear the string.
fps.str("");
fps << "FPS: " << frameCount;
frameCount = 0;
}

frameCount++;
}
clean_up();

return 0;
}




fly.h

#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#ifdef __APPLE__
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#else
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#endif

#include <string>
#include <sstream>
#include <ctime>
#include "Timer.h"
#include "functions.h"

class Fly
{
private:

int xPos; // X position.
int yPos; // Y position.

int width; // Width.
int height; // Height.

bool isDead; // Dead if true;
bool isVisible; // Visible is true;

SDL_Surface* dead; // Dead surface.
SDL_Surface* alive; // Alive surface.

Timer visibleTime; // Makes dead flies invisible.
Timer deadTime; // Makes dead & invisible flies alive.

public:

// Default constructor.
Fly();

Fly(SDL_Surface* _alive, SDL_Surface* _dead) ;

bool is_hit(int _mouseX, int _mouseY);

void get_random_pos();

void draw_fly(SDL_Surface* _screen);

bool is_dead();

bool is_visible();

~Fly();

};


fly.cpp

#include "Fly.h"

Fly::Fly()
{
this->alive = NULL;
this->dead = NULL;

this->isDead = true;
this->isVisible = false;

this->height = 50;
this->width = 50;

this->visibleTime = Timer();
this->visibleTime.start();

this->deadTime = Timer();
this->deadTime.start();

get_random_pos();
}

Fly::Fly(SDL_Surface* _alive, SDL_Surface* _dead)
{
this->alive = _alive;
this->dead = _dead;

this->isDead = false;
this->isVisible = true;

this->height = 50;
this->width = 50;

this->visibleTime = Timer();
this->visibleTime.start();

this->deadTime = Timer();
this->deadTime.start();

get_random_pos();

}

bool Fly::is_hit(int _mouseX, int _mouseY)
{
if ((_mouseX > this->xPos) && (_mouseX < (this->xPos + this->width)) &&
(_mouseY > this->yPos) && (_mouseY < (this->yPos + this->width)))
{
if (!this->isDead)
{
this->isDead = true;
this->deadTime.reset();
return(true);
}
}

return false;
}

void Fly::get_random_pos()
{
this->xPos = (rand()%590 + 25);
this->yPos = (rand()%430 + 25);
}

void Fly::draw_fly(SDL_Surface* _screen)
{
if ((this->isDead) && (this->isVisible))
{
if (this->deadTime.get_time() > 1000)
{
this->isVisible = false;
this->visibleTime.reset();
}
}

if (!this->isVisible)
{
if (this->visibleTime.get_time() > 2000)
{
this->get_random_pos();
this->isDead = false;
this->isVisible = true;
}
}

if (this->isVisible)
{
if (this->isDead)
{
apply_surface(this->xPos, this->yPos, this->dead, _screen);
}
else
{
apply_surface(this->xPos, this->yPos, this->alive, _screen);
}
}
}

bool Fly::is_dead()
{
return(this->isDead);
}

bool Fly::is_visible()
{
return(this->isVisible);
}

Fly::~Fly()
{
SDL_FreeSurface(this->alive);
SDL_FreeSurface(this->dead);
}



At the moment I'm only trying to draw one fly, as soon as I sort out this problem then I'll have multiple flies.

Share this post


Link to post
Share on other sites
First glance - I notice you call SDL_FreeSurface twice, once in the clean_up() function and another in the deconstructor of fly - that might cause problems in the future, and the fact that you didn't mention that it is crashing or anything on exit kind of hinted at the idea that something is going wrong with your surface loading, and I found your problem in main().

You're constructing your fly with two NULL surfaces before you call init().

Just move it to right after, and you should be okay :)

Share this post


Link to post
Share on other sites
// get_random_x returns a random value between 25 and 590.
int get_random_x()
{
return((rand()%590) + 25);
}

// get_random_y returns a random value between 25 and 430.
int get_random_y()
{
return((rand()%430) + 25);
}


The way you have this code as of now, you would get a random number from 25-614 and 25-454. A way to fix this would be to do

// get_random_x returns a random value between 25 and 590.
int get_random_x()
{
return((rand()%566) + 25); // returns # from 25-590
}

// get_random_y returns a random value between 25 and 430.
int get_random_y()
{
return((rand()%406) + 25); // returns # from 25-430
}


Of course, there is probably a better way but this seemed pretty simple to me.

[Edited by - Deuce81 on August 21, 2007 7:32:54 AM]

Share this post


Link to post
Share on other sites

This topic is 3772 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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