Anyways, now for the problems. I'm trying to make a sort of game in C++ and SDL2, where you can move all around and collide with blocks and enemies. When I start debugging it, this window comes up:
This is what the "Call Stack" says (no idea what the call stack is):
The First Error
So, the first error it shows is line 509. Here's the function that uses that line:
Code: Select all
void Texture::free()
{
// if a texture exists, get rid of it and reinitialize everything
if (txTexture != NULL)
{
SDL_DestroyTexture(txTexture); // THIS IS LINE 509
txTexture = NULL;
txRect.w = DEFAULT_W;
txRect.h = DEFAULT_H;
txRect.x = DEFAULT_X;
txRect.y = DEFAULT_Y;
}
}
This function is part of the Texture class. The Texture class is used for each game object's texture, and each variable inside of the Texture class is prefixed with "tx". The function checks to make sure that the pointer that points to an SDL_Texture is actually pointing to a texture and not empty. Then, it calls SDL_DestroyTexture and re-initializes the pointer and variables.
txTexture is a texture pointer, so I'm not using incorrect function parameters.
Not gonna lie, a lot of my code is based off of
Lazy Foo's tiling tutorial. I wrote this program completely from scratch, using his tutorial for reference. Anyways, this is the code he uses in his tutorial:
Code: Select all
void LTexture::free()
{
//Free texture if it exists
if( mTexture != NULL )
{
SDL_DestroyTexture( mTexture );
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
}
His version runs just fine. Not really sure how my code would make anything different happen. I dunno.
The Second Error
Here's the code that includes line 464:
Code: Select all
bool Texture::loadF(string path)
{
// keeps track of whether a failure occurred
bool success = true;
// free the current texture (if it exists)
free();
// the texture that we will (hopefully) end up with
SDL_Texture* createdTexture = NULL; // THIS IS LINE 464
// the surface that the texture's image will be loaded onto
SDL_Surface* imageSurface = IMG_Load(path.c_str());
if (imageSurface == NULL)
{
// output a message if the surface failed to load
printf("Error loading image at the specified path: %s\n", path);
printf("IMG_GetError: %s\n", IMG_GetError());
success = false;
}
else
{
// set the color key
SDL_SetColorKey(imageSurface, SDL_TRUE, SDL_MapRGB(imageSurface->format, 0, 255, 255));
// create the texture itself from the surface
createdTexture = SDL_CreateTextureFromSurface(gRenderer, imageSurface);
if (createdTexture == NULL)
{
// output an error
printf("Error creating texture from surface. SDL_GetError: %s\n", SDL_GetError());
}
else
{
txRect.w = imageSurface->w;
txRect.h = imageSurface->h;
}
}
// the surface isn't needed anymore
SDL_FreeSurface(imageSurface);
// make the texture member point to the newly created texture
txTexture = createdTexture;
// return whether everything ran successfully or not
return success;
}
This code frees the current texture, loads an image surface, sets the color key, creates a SDL_Texture from the surface, sets the Texture's rect's width and height, frees the unneeded surface, and makes the Texture's pointer point to the SDL_Texture.
I have no idea how line 464 could cause an error. I'm just declaring (or defining? not good with vocabulary) a pointer to an SDL_Texture.
Again, this is similar to Lazy Foo's code, which runs fine:
Code: Select all
bool LTexture::loadFromFile( std::string path )
{
//Get rid of preexisting texture
free();
//The final texture
SDL_Texture* newTexture = NULL;
//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
}
else
{
//Color key image
SDL_SetColorKey( loadedSurface, SDL_TRUE, SDL_MapRGB( loadedSurface->format, 0, 0xFF, 0xFF ) );
//Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );
if( newTexture == NULL )
{
printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
}
else
{
//Get image dimensions
mWidth = loadedSurface->w;
mHeight = loadedSurface->h;
}
//Get rid of old loaded surface
SDL_FreeSurface( loadedSurface );
}
//Return success
mTexture = newTexture;
return mTexture != NULL;
}
No clue why I get an error.
The Third Error
Sprite variables are prefixed with sp (I have Player and Enemy classes which inherit from the Sprite class). The code with line 321:
Code: Select all
Player::Player(int passedX = DEFAULT_X, int passedY = DEFAULT_Y, int passedW = DEFAULT_W, int passedH = DEFAULT_H)
{
// initialize variables
spRect.x = passedX;
spRect.y = passedY;
spRect.w = passedW;
spRect.h = passedH;
spFrames = 4;
// load the player's texture
spTexture->loadF("resources/cubeman.png");
// center the camera around the player
centerCamera(); // THIS IS LINE 321
}
This function (which is the Player class's constructor) assigns the variables, loads the player's texture, and centers the camera around the player.
Again, no idea what's with the error. Here's the centerCamera function (Camera variables prefixed with cm):
Code: Select all
void Player::centerCamera()
{
// variable to represent the camera
SDL_Rect* camera = &gCamera.cmRect;
camera->w = WINDOW_W;
camera->h = WINDOW_H;
// determines whether the camera is at the level's edge or not
bool edge = false;
// represents the camera when it moves
SDL_Rect moddedRect;
// set moddedRect properties
moddedRect.x = camera->x;
moddedRect.y = camera->y;
moddedRect.w = camera->w;
moddedRect.h = camera->h;
// set moddedRect to camera's next move
moddedRect.x++;
moddedRect.y++;
// if camera is about to go off the left of the screen, stop its movement
if (moddedRect.x < camera->w / 2)
{
camera->x = 0;
edge = true;
}
// if it is about to go off the right, stop it
if (moddedRect.x > LEVEL_W - camera->w / 2)
{
camera->x = LEVEL_W - camera->w;
edge = true;
}
// if it is about to go off the top, stop it
if (moddedRect.y > camera->h / 2)
{
camera->y = 0;
edge = true;
}
// if it is about to go off the bottom, stop it
if (moddedRect.y > LEVEL_H - camera->h / 2)
{
camera->y = LEVEL_H - camera->h;
edge = true;
}
// if not at the edge of the level, keep camera centered around player
if (!edge)
{
camera->x = spRect.x - (camera->w / 2);
camera->y = spRect.y - (camera->h / 2);
}
}
This function makes an SDL_Rect pointer that points to the camera's rect, and sets all the variables. Then it defines another SDL_Rect that represents where the camera is about to move to. If the place where the camera is about to move is the edge of the screen, then the camera needs to stop moving in that direction so that it doesn't scroll offscreen.
The Fourth Error
Here's line 253:
Code: Select all
// player, camera, and background
Player gPlayer(0, 0, 64, 64); // THIS IS LINE 253
Camera gCamera(0, 0, 64, 64);
Background gBackground(0, 0, 64, 64);
The parameters in all those functions are the x and y positions, followed by the width and height. I gave the constructors default parameters, but when I omit the parameters in the above declarations it gives me an error for some reason. I have no idea why; here's the gPlayer constructor definition:
Code: Select all
Player::Player(int passedX = DEFAULT_X, int passedY = DEFAULT_Y, int passedW = DEFAULT_W, int passedH = DEFAULT_H)
{
// initialize variables
spRect.x = passedX;
spRect.y = passedY;
spRect.w = passedW;
spRect.h = passedH;
spFrames = 4;
// load the player's texture
spTexture->loadF("resources/cubeman.png");
// center the camera around the player
centerCamera();
}
So, I guess there's two questions with this one. Why am I getting a dynamic initializer error, and why are my default parameters not working? Perhaps they're connected somehow?
And I'm not sure what the last two lines of the Call Stack mean. Maybe they're important?