SDL each mouse click cant display new image


#1

Hi All,
I`m new in SDL.
Please somebody to help me.
I have a c++ project almost copied from website LazyFoo.
The idea is each time when is click with mouse on the screen - a copy of one and the same image to be displayed on the screen.
The problem is that each time the previous image is moved to the new clicked place.
I want with each click - new image to be displayed.
Please please give some ideas…

Below is the code:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#include
#include
#include
using namespace std;
//Screen dimension constants
const int SCREEN_WIDTH = 1300;
const int SCREEN_HEIGHT = 600;
const int FIGURE_WIDTH = 40;
const int FIGURE_HEIGHT = 40;

enum
{
BLACK_POOL,
WHITE_POOL
};

//Texture wrapper class
class LTexture
{
public:
//Initializes variables
LTexture();

//Deallocates memory
~LTexture();

//Loads image at specified path
bool loadFromFile( std::string path );

//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, SDL_Rect* clip = NULL );

//Gets image dimensions
int getWidth();
int getHeight();
void setWidth(int);
void setheight(int);

int getX();
int getY();
void setX(int);
void setY(int);

private:
//The actual hardware texture
SDL_Texture* mTexture;

//Image dimensions
int mWidth;
int mHeight;
int x;
int y;

};

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

//The window we’ll be rendering to
SDL_Window* gWindow = NULL;

//The window renderer
SDL_Renderer* gRenderer = NULL;

//Images
LTexture gBackground;
LTexture imageForCrop;

SDL_Rect rec;
//LTexture gBluePawn;
//LTexture gGreenPawn;
//LTexture gYellowPawn;

LTexture::LTexture()
{
//Initialize
mTexture = NULL;
mWidth = 0;
mHeight = 0;
x = 0;
y = 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, 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;

}

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, SDL_Rect* clip )
{
//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;
    renderQuad.h = clip->h;
}

//Render to screen
SDL_RenderCopy( gRenderer, mTexture, clip, &renderQuad );

}

int LTexture::getWidth()
{
return mWidth;
}

int LTexture::getHeight()
{
return mHeight;
}

void LTexture::setWidth( int width)
{
mWidth = width;
}
void LTexture::setheight(int height)
{
mHeight = height;
}

int LTexture::getX()
{
return x;
}

int LTexture::getY()
{
return y;
}

void LTexture::setX(int x_){
x = x_ ;
}

void LTexture::setY(int y_)
{
y = y_;
}

//help vectors for function cropImages()
vector<SDL_Rect> rects1;

void pushInVector()
{
if ( !imageForCrop.loadFromFile( “poolSprite.png” ) )
{
printf(“Failed to load figures”);
}
else
{
rec.x = 0;
rec.y = 0;
rec.w = FIGURE_WIDTH;
rec.h = FIGURE_HEIGHT;

        for (size_t j = 0; j < 2; j++)
        {
            rects1.push_back(rec);
            rec.x += FIGURE_WIDTH -1;
        }
      //  rec.x = 0;
      //  rec.y += FIGURE_HEIGHT -1;

        cout << "here"; //tuk vliza samo 1 put

}

}

int main( int argc, char* args[] )
{
//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;
        int currentX = 0 ;
        int currentY = 0 ;

        //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;
                }

                if (e.type == SDL_MOUSEBUTTONDOWN )
                {

                	SDL_GetMouseState(&currentX, &currentY);
                    currentX = e.button.x;
                    currentY = e.button.y;
                    cout << currentX<<endl;
                    cout << currentY<<endl;




                }


            }



            //Clear screen
            SDL_SetRenderDrawColor( gRenderer, 0xff, 0xff, 0xff, 0xff );
            SDL_RenderClear( gRenderer );



            gBackground.setWidth(1300);
            gBackground.setheight(600);
            //Render background
            gBackground.render( 0, 0, NULL );


            imageForCrop.render(currentX, currentY, &rects1.at(WHITE_POOL));


            SDL_RenderPresent(gRenderer);
      //      imageForCrop.render(15, 15 , &rects1.at(WHITE_POOL));

//commented code
// for (int i = 0; i <5; i++)
// {
// imageForCrop.render(15, 15+(40i) , &rects1.at(WHITE_POOL));
// imageForCrop.render(15,(SCREEN_HEIGHT-50)- (40
i),&rects1.at(BLACK_POOL));
// imageForCrop.render(320,15+(40i),&rects1.at(BLACK_POOL));
//
// if (i < 3)
// {
// imageForCrop.render(215, 15+(40
i),&rects1.at(BLACK_POOL));
// }
// if (i < 2)
// {
// imageForCrop.render(570,15+(40i),&rects1.at(WHITE_POOL));
// }
// }
//
// imageForCrop.render(15, 15 , &rects1.at(WHITE_POOL));
// imageForCrop.render(15, 55 , &rects1.at(WHITE_POOL));
// imageForCrop.render(15, 95 , &rects1.at(WHITE_POOL));
// imageForCrop.render(15, 135 , &rects1.at(WHITE_POOL));
// imageForCrop.render(15, 175, &rects1.at(WHITE_POOL));
//
//
// imageForCrop.render(215,15,&rects1.at(BLACK_POOL));
// imageForCrop.render(215,55,&rects1.at(BLACK_POOL));
// imageForCrop.render(215,95,&rects1.at(BLACK_POOL));
//
//
// imageForCrop.render(320,15,&rects1.at(BLACK_POOL));
// imageForCrop.render(320,55,&rects1.at(BLACK_POOL));
// imageForCrop.render(320,95,&rects1.at(BLACK_POOL));
// imageForCrop.render(320,135,&rects1.at(BLACK_POOL));
// imageForCrop.render(320,175,&rects1.at(BLACK_POOL));
//
//
// imageForCrop.render(570,15,&rects1.at(WHITE_POOL));
// imageForCrop.render(570,55,&rects1.at(WHITE_POOL));
//imageForCrop.render(15,SCREEN_HEIGHT - 50,&rects1.at(BLACK_POOL));
//
// for (int i =0 ; i <5; i++)
// {
// imageForCrop.render(15,(SCREEN_HEIGHT-50)- (40
i),&rects1.at(BLACK_POOL));
// }

        }



		  // SDL_RenderCopy()
		  SDL_RenderPresent(gRenderer);


    }
}

//Free resources and close SDL
close();

return 0;

}
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
{
    //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( "pepi", 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 vsynced renderer for window
        gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
        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;
            }
        }
    }
}

return success;

}

bool loadMedia()
{
//Loading success flag
bool success = true;

//Load sprite sheet texture
if( !gBackground.loadFromFile( "roulette.jpg" ) )
{
    printf( "Failed to load texture!\n" );
    success = false;
}

if( !imageForCrop.loadFromFile( "poolSprite.png" ) )
{
    printf( "Failed to load texture!\n" );
    success = false;
}
else
{
    pushInVector();
}


return success;

}

void close()
{

gBackground.free();
imageForCrop.free();


//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;

//Quit SDL subsystems
IMG_Quit();
SDL_Quit();

}

Many thanks in advance!


#2

Every time SDL_RenderClear is called, you have to redraw the whole screen. That means you have to store the position of every click if you want to keep displaying images at these coordinates.

You could, for example, store them in a vector.

vector<SDL_Point> sprite_pos;

When the SDL_MOUSEBUTTONDOWN event happens, you store the position in the vector.

SDL_Point mouse_position = {e.button.x, e.button.y};
sprite_pos.push_back(mouse_position);

After the screen has been cleared, you can draw them all again.

for (size_t si = 0; si < sprite_pos.size(); si++)
{
    imageForCrop.render(sprite_pos[si].x, sprite_pos[si].y, &rects1.at(WHITE_POOL));
}

Note that you can indent your code in your post with four spaces or (select the code in your post and) use the “Preformatted text” button to advice Discourse to not apply any formatting to it. This will make it more readable.


#3

Many Thanks for your help. Much appreciated ! :slight_smile:
About the formatting - I will comply with the comments next time.
Again ChliHug - thank you for the help, the great and detailed explanation!!!