Ok update. I noticed that in Lazy’s 32nd tutorial he changed the text in real time. This is the one for handling text input. In it he has a string variable that he loads into his lTexture class everytime he wants to update. I’m trying that right now but, every time I try to call the loadfromrenderedtext function my program crashes. It is weird. It works from the loadmedia function that Lazy Foo wrote but not anywhere else.
Why is this? I’m including my code. I wrote it so that it will load a texture when you hit backspace, a which point it will crash. I’m so close to getting this is to work and any advice would be so appreciated.
Code:
/This source code copyrighted by Lazy Foo’ Productions (2004-2013)
and may not be redistributed without written permission./
//Using SDL, SDL_image, standard IO, and strings
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include
#include <SDL_ttf.h>
#include
#include
//Level Dimensions
const int LEVEL_WIDTH = 4000;
const int LEVEL_HEIGHT = 700;
//Screen dimension constants
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
const int IDLE_FRAMES = 9;
const int RUN_FRAMES = 9;
const int JUMP_FRAMES = 12;
const float JILL_SCALE = 1.5;
const float GRAVITY = 1;
const int FRAME_SIZE = 100;
const int ANIM_SPEED = 4;
const int JUMP_SPEED = 17;
// Animation Variable.
// Note the sign Convention
enum Anim{
JILL_Walk,
JILL_Run,
JILL_Idle,
JILL_Dash,
Jill_Jump
};
//Texture wrapper class
class LTexture
{
public:
//Initializes variables
LTexture();
//Deallocates memory
~LTexture();
//Loads image at specified path
bool loadFromFile( std::string path );
#ifdef _SDL_TTF_H
//Creates image from font string
bool loadFromRenderedText( std::string textureText, SDL_Color textColor );
#endif
//Deallocates texture
void free();
//Set color modulation
void setColor( Uint8 red, Uint8 green, Uint8 blue );
//Set blending
void setBlendMode( SDL_BlendMode blending );
//Set alpha modulation
void setAlpha( Uint8 alpha );
//Renders texture at given point
void render( int x, int y, float scaler, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE );
//Gets image dimensions
int getWidth();
int getHeight();
private:
//The actual hardware texture
SDL_Texture* mTexture;
//Image dimensions
int mWidth;
int mHeight;
};
class LTimer
{
private:
//The clock time when the timer started
Uint32 mStartTicks;
//The ticks stored when the timer was paused
Uint32 mPausedTicks;
//The timer status
bool mPaused;
bool mStarted;
public:
//Initializes variables
LTimer();
//The various clock actions
void start();
void stop();
void pause();
void unpause();
//Gets the timer's time
Uint32 getTicks();
//Checks the status of the timer
bool isStarted();
bool isPaused();
};
class Jill
{
public:
int framer();
//The dimensions of the dot
static constexpr int JILL_WIDTH = 100;
static constexpr int JILL_HEIGHT = 100;
//Maximum axis velocity of the dot
static constexpr float JILL_VEL = 3;
//Initializes the variables
Jill();
//Takes key presses and adjusts the dot's velocity
void handleEvent( SDL_Event& e,const Uint8* KeyStates );
//Moves the dot
void move();
//Shows the dot on the screen
void render(int camX, int camY, SDL_Rect* clip, SDL_Rect* clip2);
void land();
Anim GetAnim();
//Position accessors
int getPosX();
int getPosY();
private:
//The X and Y offsets of the dot
float mPosX, mPosY;
//The velocity of the dot
float mVelX, mVelY;
//Vertical distance
float VertDis;
//Vertical Velocity
float VertVel;
// The Current Animation
Anim JillAnim ;
// FlipState
bool IsFlipped;
bool InAir;
// Collision Detection
SDL_Rect mCollider;
// The animation frame
int Frame;
};
void printF(char *c, int x, int y);
//Starts up SDL and creates window
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
//Box collision detector
bool checkCollision( SDL_Rect a, SDL_Rect b );
//The window we’ll be rendering to
SDL_Window* gWindow = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;
//Scene textures
LTexture gKunoTexture;
LTexture gBGTexture;
LTexture gTextTexture;
// SDL_Surface *DebugText = NULL;
//SDL_Color textColor = { 0, 0, 0 };
const int ANIMATION_FRAMES = IDLE_FRAMES + RUN_FRAMES + JUMP_FRAMES;
SDL_Rect gSpriteClips[ ANIMATION_FRAMES ];
//Globally used font
TTF_Font *gFont = NULL;
//Surface
SDL_Surface* fontSurface;
SDL_Surface* screen;
SDL_Color TextColor = { 0, 0, 0, 0xFF };
SDL_Rect fontRect;
LTexture::LTexture()
{
//Initialize
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
LTexture::~LTexture()
{
//Deallocate
free();
}
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, 0xFF, 0, 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;
}
#ifdef _SDL_TTF_H
bool LTexture::loadFromRenderedText( std::string textureText, SDL_Color textColor )
{
//Get rid of preexisting texture
free();
//Render text surface
SDL_Surface* textSurface = TTF_RenderText_Solid( gFont, textureText.c_str(), textColor );
if( textSurface != NULL )
{
//Create texture from surface pixels
mTexture = SDL_CreateTextureFromSurface( gRenderer, textSurface );
if( mTexture == NULL )
{
printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
}
else
{
//Get image dimensions
mWidth = textSurface->w;
mHeight = textSurface->h;
}
//Get rid of old surface
SDL_FreeSurface( textSurface );
}
else
{
printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
}
//Return success
return mTexture != NULL;
}
#endif
void LTexture::free()
{
//Free texture if it exists
if( mTexture != NULL )
{
SDL_DestroyTexture( mTexture );
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
}
void LTexture::setColor( Uint8 red, Uint8 green, Uint8 blue )
{
//Modulate texture rgb
SDL_SetTextureColorMod( mTexture, red, green, blue );
}
void LTexture::setBlendMode( SDL_BlendMode blending )
{
//Set blending function
SDL_SetTextureBlendMode( mTexture, blending );
}
void LTexture::setAlpha( Uint8 alpha )
{
//Modulate texture alpha
SDL_SetTextureAlphaMod( mTexture, alpha );
}
void LTexture::render( int x, int y,float scaler, SDL_Rect* clip , double angle, SDL_Point* center, SDL_RendererFlip flip )
{
//Set rendering space and render to screen
SDL_Rect renderQuad = { x, y, mWidth, mHeight };
//Set clip rendering dimensions
if( clip != NULL )
{
renderQuad.w = clip->w*scaler;
renderQuad.h = clip->h*scaler;
}
//Render to screen
SDL_RenderCopyEx( gRenderer, mTexture, clip, &renderQuad, angle, center, flip );
}
int LTexture::getWidth()
{
return mWidth;
}
int LTexture::getHeight()
{
return mHeight;
}
Jill::Jill()
{
//Initialize the offsets
mPosX = 30;
mPosY = 400;
//Initialize the velocity
mVelX = 0;
mVelY = 0;
mCollider.w = JILL_WIDTH;
mCollider.h = JILL_HEIGHT;
//Initialize The Aniamtion
JillAnim = JILL_Idle;
// Set the Flip state and the other booleans
IsFlipped = false;
InAir = false;
Frame = 0;
//Vertical distance
VertDis = 0;
//Vertical Velocity
VertVel = 0;
}
int Jill::framer(){
if(JillAnim == JILL_Walk){
Frame ++;
if(Frame/ANIM_SPEED>17||(Frame/ANIM_SPEED)<9){
Frame =9*ANIM_SPEED;
}
}
else if(JillAnim == JILL_Idle){
Frame++;
if(Frame/ANIM_SPEED>8){
Frame = 0;
}
}
else if(JillAnim == Jill_Jump){
Frame++;
if((Frame/ANIM_SPEED)<18){
Frame =18*ANIM_SPEED;
}
else if(Frame/ANIM_SPEED>=29){
land();
}
}
return Frame;
}
void Jill::handleEvent( SDL_Event& e ,const Uint8* KeyStates )
{
/*
if (KeyStates[SDL_SCANCODE_DOWN]){
mPosY += KUNO_VEL;
}
*/
//If a key was pressed
if( e.type == SDL_KEYDOWN && e.key.repeat == 0)
{
//Adjust the velocity
switch( e.key.keysym.sym )
{
case SDLK_UP: mVelY -= JILL_VEL; break;
case SDLK_DOWN: mVelY += JILL_VEL; break;
case SDLK_LEFT: mVelX -= JILL_VEL; IsFlipped = true; break;
case SDLK_RIGHT: mVelX += JILL_VEL; IsFlipped = false; break;
case SDLK_SPACE: if(JillAnim != Jill_Jump){JillAnim = Jill_Jump; VertVel = JUMP_SPEED; InAir = true;} break;
}
}
//If a key was released
if( e.type == SDL_KEYUP && e.key.repeat == 0 )
{
//Adjust the velocity
switch( e.key.keysym.sym )
{
case SDLK_UP: mVelY += JILL_VEL; break;
case SDLK_DOWN: mVelY -= JILL_VEL; break;
case SDLK_LEFT: mVelX += JILL_VEL; break;
case SDLK_RIGHT: mVelX -= JILL_VEL; break;
}
//}
}
}
void Jill::move()
{
//Move the dot left or right
mPosX += mVelX;
//If the dot went too far to the left or right
if( ( mPosX < 0 ) || ( mPosX + JILL_WIDTH > LEVEL_WIDTH ) )
{
//Move back
mPosX -= mVelX;
}
mPosY += mVelY;
//If the dot went too far up or down
if( ( mPosY < 0 ) || ( mPosY + JILL_HEIGHT > LEVEL_HEIGHT ) )
{
// onGround = true;
//Move back
mPosY -= mVelY;
/*
mVelY = 0;
onGround = true;
mVelX = 0;
*/
}
VertVel-=GRAVITY;
VertDis+=VertVel;
if(VertDis<=0){
land();
}
if(((mVelX)!= 0||(mVelY)!= 0)&&!(InAir)){
JillAnim = JILL_Walk;
}
else if(!InAir){
JillAnim = JILL_Idle;
}
}
void Jill::render(int camX, int camY, SDL_Rect* clip, SDL_Rect* clip2)
{
int rendY = mPosY - VertDis - camY;
gKunoTexture.render( mPosX - camX, mPosY-camY+110,JILL_SCALE, clip2 );
if(JillAnim == Jill_Jump){
rendY -=30;
}
if(IsFlipped == false){
/* if(JillAnim == Jill_Jump){
gKunoTexture.render( mPosX - camX, mPosY - camY,JILL_SCALE, clip );
}
else{ */
gKunoTexture.render( mPosX - camX, rendY,JILL_SCALE, clip );
}
else if(IsFlipped == true){
gKunoTexture.render( mPosX - camX, rendY,JILL_SCALE, clip,0.0,NULL, SDL_FLIP_HORIZONTAL );
}
}
Anim Jill::GetAnim(){
return JillAnim;
}
int Jill::getPosX(){
return mPosX;
}
int Jill::getPosY(){
return mPosY;
}
void Jill::land(){
VertDis = 0;
VertVel = 0;
JillAnim = JILL_Idle;
InAir = false;
}
LTimer::LTimer()
{
//Initialize the variables
mStartTicks = 0;
mPausedTicks = 0;
mPaused = false;
mStarted = false;
}
void LTimer::start()
{
//Start the timer
mStarted = true;
//Unpause the timer
mPaused = false;
//Get the current clock time
mStartTicks = SDL_GetTicks();
mPausedTicks = 0;
}
void LTimer::stop()
{
//Stop the timer
mStarted = false;
//Unpause the timer
mPaused = false;
//Clear tick variables
mStartTicks = 0;
mPausedTicks = 0;
}
void LTimer::pause()
{
//If the timer is running and isn’t already paused
if( mStarted && !mPaused )
{
//Pause the timer
mPaused = true;
//Calculate the paused ticks
mPausedTicks = SDL_GetTicks() - mStartTicks;
mStartTicks = 0;
}
}
void LTimer::unpause()
{
//If the timer is running and paused
if( mStarted && mPaused )
{
//Unpause the timer
mPaused = false;
//Reset the starting ticks
mStartTicks = SDL_GetTicks() - mPausedTicks;
//Reset the paused ticks
mPausedTicks = 0;
}
}
Uint32 LTimer::getTicks()
{
//The actual timer time
Uint32 time = 0;
//If the timer is running
if( mStarted )
{
//If the timer is paused
if( mPaused )
{
//Return the number of ticks when the timer was paused
time = mPausedTicks;
}
else
{
//Return the current time minus the start time
time = SDL_GetTicks() - mStartTicks;
}
}
return time;
}
bool LTimer::isStarted()
{
//Timer is running and paused or unpaused
return mStarted;
}
bool LTimer::isPaused()
{
//Timer is running and paused
return mPaused && mStarted;
}
void printF(char *c, int x, int y){
/*fontSurface = TTF_RenderText_Solid(gFont, c, textColor);
fontRect.x = x;
fontRect.y = y;
SDL_BlitSurface(fontSurface, NULL, screen, &fontRect);
SDL_Flip(screen);
*/
}
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Enable VSync
if( !SDL_SetHint( SDL_HINT_RENDER_VSYNC, "1" ) )
{
printf( "Warning: VSync not enabled!" );
}
//Set texture filtering to linear
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
{
printf( "Warning: Linear texture filtering not enabled!" );
}
//Create window
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create renderer for window
gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Initialize renderer color
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
//Initialize SDL_ttf
if( TTF_Init() == -1 )
{
printf( "SDL_ttf could not initialize! SDL_ttf Error: %s\n", TTF_GetError() );
success = false;
}
}
}
}
return success;
}
bool loadMedia()
{
//Loading success flag
bool success = true;
gFont = TTF_OpenFont( "./Planet Of The Apes.ttf", 28 );
if( gFont == NULL )
{
printf( "Failed to load lazy font! SDL_ttf Error: %s\n", TTF_GetError() );
success = false;
}
else
{
//Render text
SDL_Color textColor = { 0, 0, 0 };
if( !gTextTexture.loadFromRenderedText( "sick", textColor ) )
{
printf( "Failed to render text texture!\n" );
success = false;
}
}
if( gFont == NULL )
{
printf( "Failed to load lazy font! SDL_ttf Error: %s\n", TTF_GetError() );
success = false;
}
//Load dot texture
// Kuno addition: load the kunoichi walk strip instead of the dot
if( !gKunoTexture.loadFromFile( "./JillSprites.png" ) )
{
printf( "Failed to load dot texture!\n" );
success = false;
}
if( !gBGTexture.loadFromFile( "./BackGround.png" ) )
{
printf( "Failed to load background texture!\n" );
success = false;
}
else
{
// int Frame_Subtotal = 0;
//Set sprite clips
// This is done in an array.
for(int i = 0; i<9;i++){
gSpriteClips[ i ].x = i*FRAME_SIZE;
gSpriteClips[ i ].y = 0;
gSpriteClips[ i ].w = FRAME_SIZE;
gSpriteClips[ i ].h = FRAME_SIZE;
}
//Frame_Subtotal += IDLE_FRAMES;
for(int i = 9; i < 18; i++){
gSpriteClips[ i ].x = (i-9)*FRAME_SIZE;
gSpriteClips[ i ].y = FRAME_SIZE;
gSpriteClips[ i ].w = FRAME_SIZE;
gSpriteClips[ i ].h = FRAME_SIZE;
}
for(int i = 18; i <30; i++){
gSpriteClips[ i ].x = (i-18)*FRAME_SIZE;
gSpriteClips[ i ].y = 2*FRAME_SIZE;
gSpriteClips[ i ].w = FRAME_SIZE;
gSpriteClips[ i ].h = FRAME_SIZE+20;
}
gSpriteClips[ 30 ].x = 0;
gSpriteClips[ 30 ].y = 400;
gSpriteClips[ 30 ].w = 100;
gSpriteClips[ 30 ].h = 50;
}
return success;
}
bool checkCollision( SDL_Rect a, SDL_Rect b )
{
//The sides of the rectangles
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;
//Calculate the sides of rect A
leftA = a.x;
rightA = a.x + a.w;
topA = a.y;
bottomA = a.y + a.h;
//Calculate the sides of rect B
leftB = b.x;
rightB = b.x + b.w;
topB = b.y;
bottomB = b.y + b.h;
//If any of the sides from A are outside of B
if( bottomA <= topB )
{
return false;
}
if( topA >= bottomB )
{
return false;
}
if( rightA <= leftB )
{
return false;
}
if( leftA >= rightB )
{
return false;
}
//If none of the sides from A are outside B
return true;
}
void close()
{
//Free loaded images
gKunoTexture.free();
gBGTexture.free();
//Free global font
TTF_CloseFont( gFont );
gFont = NULL;
//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
int main( int argc, char* args[] )
{
std::string DeBugInfo;
std::ostringstream DebugConvert;
std::string DeBugOld = "";
bool renderText = false;
std::string TestText = "testing";
//Start up SDL and create window
if( !init() )
{
printf( "Failed to initialize!\n" );
}
else
{
//Load media
if( !loadMedia() )
{
printf( "Failed to load media!\n" );
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
SDL_Color TextColor = { 0, 0, 0, 0xFF };
// gTextTexture.loadFromRenderedText( "geese", TextColor );
int frame = 11;
//The jill that will be moving around on the screen
Jill jill;
//SDL camera
SDL_Rect camera = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
else if( e.type == SDL_KEYDOWN )
{
//Handle backspace
if( e.key.keysym.sym == SDLK_BACKSPACE )
{
renderText = true;
}
}
//Handle input for the dot
// The kunoichi
const Uint8* currentKeyStates = SDL_GetKeyboardState( NULL );
jill.handleEvent( e, currentKeyStates );
}
//Move the dot
jill.move();
//Center the camera over the dot
camera.x = ( jill.getPosX() + Jill::JILL_WIDTH / 2 ) - SCREEN_WIDTH / 2;
camera.y = ( jill.getPosY() + Jill::JILL_WIDTH/ 2 ) - SCREEN_HEIGHT / 2;
//Keep the camera in bounds
if( camera.x < 0 )
{
camera.x = 0;
}
if( camera.y < 0 )
{
camera.y = 0;
}
if( camera.x > LEVEL_WIDTH - camera.w )
{
camera.x = LEVEL_WIDTH - camera.w;
}
if( camera.y > LEVEL_HEIGHT - camera.h )
{
camera.y = LEVEL_HEIGHT - camera.h;
}
// Display infor... I don't know if I should be loading every frame
DebugConvert << jill.getPosX();
DeBugInfo = DebugConvert.str();
if(renderText){
//gTextTexture.loadFromRenderedText(TestText, textColor);
gTextTexture.loadFromRenderedText("dick", TextColor);
std::cout<<"dick";
renderText = false;
}
//Clear screen
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( gRenderer );
//Render objects
gBGTexture.render( 0, 0,1, &camera );
gTextTexture.render( ( SCREEN_WIDTH - gTextTexture.getWidth() ) / 2, ( SCREEN_HEIGHT - gTextTexture.getHeight() ) / 2,1 );
jill.render(camera.x, camera.y, &gSpriteClips[jill.framer()/ANIM_SPEED], &gSpriteClips[30]);
/*
if(DeBugOld != DeBugInfo){
DeBugOld = DeBugInfo;
// printF(DeBugInfo.c_str);
// std::cout<<DeBugInfo;
std::cout<<"Debug chnged";
}
*/
//Update screen
SDL_RenderPresent( gRenderer );
}
}
}
//Free resources and close SDL
close();
return 0;
}
[/code]