Blitting Image With Mouse Click

Hello Again,

I am having another problem. This is for a different project. I want it so that when the user clicks left mouse button, another surface(image) will be displayed on the screen where the mouse cursor is. IE where the use clicks on the screen, that image will be displayed there.

Code:

        if(event.type == SDL_MOUSEBUTTONDOWN)
        {
            if(event.button.button == SDL_BUTTON_LEFT)
            {
                mx = event.button.x;
                my = event.button.y;

                TowerRect.x = mx;
                TowerRect.y = my;

                SDL_BlitSurface(Tower,NULL,Screen,&TowerRect);
            }
        }
    }

I’m sure I’m going about this wrong, but I’m not sure how else I’d do this. I can also post the rest of my code if it is needed.

You haven’t said what’s going wrong, what’s the actual problem?------------------------
The Legend of Edgar. A 2D platformer for Windows and Linux. (http://www.parallelrealities.co.uk/p/legend-of-edgar.html)

When I click on the screen, nothing shows up. The image that is supposed to be blitted should show up on the screen. There’s no compile errors or anything like that. The code runs fine, but it dosen’t work like the way I would like it to.

You haven’t showed us where you flip the screen surface, or indeed
clear the screen. You probably shouldn’t be mixing rendering and event
logic like that. Instead, move the call to SDL_BlitSurface() outside
your event loop.

Alright, I’ll post all my code.

Code:

#include “main.h”

SDL_Surface* Screen;
SDL_Event event;
TTF_Font* Font;

int ThisTime = 0;
int LastTime = 0;
float DeltaTime = 0.0f;

const int WIDTH = 800;
const int HEIGHT = 600;
const int DEPTH = 32;
const char* TITLE = “Tower Defense”;

SDL_Color textColor = {255,255,0};

int TowerHealth = 100;
int Points = 0;

int Money = 1000;
int EnemyHealth = 50;

int Bullet_Damage = 15;
int TowerCost = 200;

SDLKey keyPressed;
SDLKey keyReleased;

bool keysHeld[323] = {false};

bool GameRunning = true;
bool GameOver = false;

SDL_Surface* Backdrop;
SDL_Rect BackdropRect;

SDL_Surface* FPS;
SDL_Rect FPSRect;
char fps[10];

SDL_Surface* POINT;
SDL_Rect POINTRect;
char point[10];

SDL_Surface* Tower;
SDL_Rect TowerRect;

SDL_Surface* TowerDamage;
SDL_Rect TowerDamageRect;
SDL_Surface* TowerDamage2;
SDL_Rect TowerDamageRect2;
SDL_Surface* TowerDamage3;
SDL_Rect TowerDamageRect3;
SDL_Surface* TowerRubble;
SDL_Rect TowerRubbleRect;

int Damage_Frames;
int Current_Frame;
const int Total_Frames = 4;

SDL_Surface* HEALTH;
SDL_Rect HealthRect;
char health[10];

SDL_Surface* MONEY;
SDL_Rect MoneyRect;
char money[10];

int mx = 0;
int my = 0;

SDL_Surface* Bullet;
SDL_Rect BulletRect;

SDL_Surface* Enemy;
SDL_Rect EnemyRect;

bool GameScreen = true;

int main(int argc, char* argv[])
{
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}

Screen = SDL_SetVideoMode(WIDTH,HEIGHT,DEPTH, SDL_HWSURFACE | SDL_DOUBLEBUF);
SDL_WM_SetCaption(TITLE,NULL);

if(TTF_Init() == -1)
{
    return 1;
}

if(Mix_OpenAudio(22050,MIX_DEFAULT_FORMAT,2,4096) == -1)
{
    return 1;
}

Backdrop = IMG_Load("Backdrop.png");
BackdropRect.x = 0;
BackdropRect.y = 0;
BackdropRect.w = 800;
BackdropRect.h = 600;

Tower = IMG_Load("Tower.png");
SDL_SetColorKey(Tower,SDL_SRCCOLORKEY,SDL_MapRGB(Tower->format,255,255,255));

TowerRect.x = 0;
TowerRect.y = 0;
TowerRect.w = 157;
TowerRect.h = 231;

//Bullet = IMG_Load("Bullet.png");
//SDL_SetColorKey(Bullet,SDL_SRCCOLORKEY,SDL_MapRGB(Bullet->format,255,255,255));

//Enemy = IMG_Load("Enemy.png");
//SDL_SetColorKey(Enemy,SDL_SRCCOLORKEY,SDL_MapRGB(Enemy->format,255,255,255));

Font = TTF_OpenFont("Arial.ttf",20);

FPSRect.x = 1;
FPSRect.y = 1;
FPSRect.w = 0;
FPSRect.h = 0;

POINTRect.x = 1;
POINTRect.y = 20;
POINTRect.w = 0;
POINTRect.h = 0;

HealthRect.x = 1;
HealthRect.y = 40;
HealthRect.w = 0;
HealthRect.h = 0;

MoneyRect.x = 1;
MoneyRect.y = 60;
MoneyRect.w = 0;
MoneyRect.h = 0;

while(GameRunning)
{
    ThisTime = SDL_GetTicks();
    DeltaTime = (float)(ThisTime - LastTime) / 1000;
    LastTime = ThisTime;

    sprintf(fps,"FPS: %.4f", DeltaTime);
    FPS = TTF_RenderText_Solid(Font,fps,textColor);

    sprintf(point,"Points: %.2d", Points);
    POINT = TTF_RenderText_Solid(Font,point,textColor);

    sprintf(health,"Health: %.3d",TowerHealth);
    HEALTH = TTF_RenderText_Solid(Font,health,textColor);

    sprintf(money,"Money: %.4d",Money);
    MONEY = TTF_RenderText_Solid(Font,money,textColor);

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

        if(event.type == SDL_KEYDOWN)
        {
            keyPressed = event.key.keysym.sym;
            keysHeld[event.key.keysym.sym] = true;

            if(keyPressed == SDLK_ESCAPE)
            {
                GameRunning = false;
            }
        }

        if(event.type == SDL_KEYUP)
        {
            keyReleased = event.key.keysym.sym;
            keysHeld[event.key.keysym.sym] = false;
        }

        if(event.type == SDL_MOUSEMOTION)
        {
            mx = event.motion.x;
            my = event.motion.y;
        }

        if(event.type == SDL_MOUSEBUTTONDOWN)
        {
            if(event.button.button == SDL_BUTTON_LEFT)
            {
                mx = event.button.x;
                my = event.button.y;

                TowerRect.x = mx;
                TowerRect.y = my;

                SDL_BlitSurface(Tower,NULL,Screen,&TowerRect);
            }
        }
    }

    SDL_FillRect(Screen,NULL,SDL_MapRGB(Screen->format,0,0,0));

    SDL_BlitSurface(Backdrop,NULL,Screen,&BackdropRect);
    SDL_BlitSurface(FPS,NULL,Screen,&FPSRect);
    SDL_BlitSurface(POINT,NULL,Screen,&POINTRect);
    SDL_BlitSurface(HEALTH,NULL,Screen,&HealthRect);
    SDL_BlitSurface(MONEY,NULL,Screen,&MoneyRect);

    if(SDL_Flip(Screen) == -1)
    {
        return 1;
    }
}

free(fps);
free(point);
free(health);
free(money);

/*for(int i = 0; i < 5; i++)
{
    SDL_FreeSurface(Tower[i]);
}

SDL_FreeSurface(Enemy);
SDL_FreeSurface(Bullet);*/
SDL_FreeSurface(MONEY);
SDL_FreeSurface(HEALTH);
SDL_FreeSurface(FPS);
SDL_FreeSurface(Backdrop);
SDL_FreeSurface(POINT);

TTF_CloseFont(Font);
TTF_Quit();
Mix_CloseAudio();
SDL_Quit();

return 0;

}

Try to consider the order of things here. Follow your code through a
couple of frames to get a feel for how it is all happening.

In particular, I see that when your click event happens, you do this:

Draw Tower
Clear Screen (SDL_FillRect)
Draw Backdrop
Draw UI
Update the display (SDL_Flip)

Jonny D

It’s likely that what you actually want to do is to place persistent
towers. For that, you need to keep a record of them all. In C++, I do
suggest that you use a class. That way, you can store all the data for
each tower in one place. Then you keep all of the towers in a list,
vector, or map. Here’s a simple class and implementation you can study,
but you need to know how to use STL lists or vectors to hold them (don’t
use arrays). Push new towers onto a list, then iterate the list and draw
each tower every frame. Do you have a good C++ book handy?

// Put this in some header file

class Tower
{
public:
SDL_Surface* image;
int x, y;

Tower(SDL_Surface* image, int x, int y);
void draw(SDL_Surface* screen) const;

};

// Put this in some source (.cpp) file

Tower::Tower(SDL_Surface* image, int x, int y)
: image(image), x(x), y(y)
{}

void Tower::draw(SDL_Surface* screen) const
{
SDL_Rect dest = {x,y};
SDL_BlitSurface(image, NULL, screen, &dest);
}

Jonny D

Thanks for the help. I have an old C++ for dummies book. I understand OOP to a degree, but its shabby.

You’re welcome. I have that same book. I was very disappointed when it
told me to learn C first. Otherwise, it’s decent. It all just takes
practice from there.

Jonny D

Hmm, you must have an older version than me, cause my book dosen’t say to learn C first. Also, can anyone help with the error I am getting? I’m using MingW(GCC) compiler. I’ve read that it can be a very picky compiler.

That’s good to hear that it has changed. Mine doesn’t cover the STL at
all, either. That would be nice.

If you need to go off the topic of SDL, you could post to the Game
Programmer mailing list (http://gameprogrammer.com/mailinglist.html). A
few of the same people here are subscribed there too. Be sure to state and
describe your errors when you do ask there.

Jonny D

My book covers certain parts of the STL, but not all of it. There used to be a book called the C++ Bible or something like that. It covered everything about C++, though I can no longer find it anywhere. Also, I understand vectors and lists to a degree as well. My main problem is trying to get the image being displayed on the screen with a mouse click. Also, can anyone help me with the compiler error, it has to do something within the tower class.

I’ll take a wild stab that it may be because for C++ you should be using
g++ rather than gcc to compile it. Maybe I’m blind but I don’t see the
error.

  • Swyped from my droid.On Mar 24, 2012 6:31 PM, “GameCoder” <g_andy at live.com> wrote:

**
My book covers certain parts of the STL, but not all of it. There used to
be a book called the C++ Bible or something like that. It covered
everything about C++, though I can no longer find it anywhere. Also, I
understand vectors and lists to a degree as well. My main problem is trying
to get the image being displayed on the screen with a mouse click. Also,
can anyone help me with the compiler error, it has to do something within
the tower class.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Oh I’m using G++

Message-ID:
<CA+DSiHbyCNZKCYQ=oDZNL8778FbYTLPuFBFf6PTan1nQbX0u7g at mail.gmail.com>
Content-Type: text/plain; charset=“iso-8859-1”

It’s likely that what you actually want to do is to place persistent
towers. For that, you need to keep a record of them all. In C++, I do
suggest that you use a class. That way, you can store all the data for
each tower in one place. Then you keep all of the towers in a list,
vector, or map. Here’s a simple class and implementation you can study,
but you need to know how to use STL lists or vectors to hold them (don’t
use arrays). Push new towers onto a list, then iterate the list and draw
each tower every frame. Do you have a good C++ book handy?

> Date: Sat, 24 Mar 2012 16:34:59 -0400

From: Jonathan Dearborn
To: sdl at lists.libsdl.org
Subject: Re: [SDL] Blitting Image With Mouse Click

From: “GameCoder” <g_andy at live.com>
To: sdl at lists.libsdl.org
Subject: Re: [SDL] Blitting Image With Mouse Click

My main problem is trying to get the image being displayed on the screen with
a mouse click.

Have you tried Jonathan’s code yet? Replace the current 'Draw Tower’
phase with a ‘Add Tower To Container’ phase. Then, use your list or
vector’s iterators to draw every tower to the screen (note: do this
after you draw the background, but before you draw the UI, otherwise
you’ll have problems).

Basically, divide the ‘Display Tower With Mouse Click’ phase into TWO phases.

Aside from the constructors parameter names looking suspiciously ambiguous,
the tower class looks ok. It’s quite possible Jonny D typed that into an
email without actually testing it first :stuck_out_tongue:

Can you post the actual compiler output and how you are trying to compile
the files? Also, attaching the source files is better than pasting into an
email, as the email formatting looks like it messed up the original code
you posted.

  • Swyped from my droid.On Mar 24, 2012 8:03 PM, “GameCoder” <g_andy at live.com> wrote:

**
Oh I’m using G++


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

OK, I’ll post all the code and the error.

main.h

Code:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <wchar.h>
#include <time.h>
#include
#include
#include
#include
#include

#include “SDL.h”
#include “SDL_image.h”
#include “SDL_ttf.h”
#include “SDL_mixer.h”

using namespace std;

Tower.h

Code:

class Tower
{
public:
SDL_Surface* Image;
int x,y;

    Tower(SDL_Surface* Image, int x, int y);
    void Draw(SDL_Surface* Screen) const;

};

Tower.cpp

Code:

#include “main.h”
#include “tower.h”

Tower::Tower(SDL_Surface* Image, int x, int y)
: Image(Image),x(x),y(y);
{}

void Tower::Draw(SDL_Surface* Screen) const
{
SDL_Rect dest = {x,y};
SDL_BlitSurface(Image,NULL,Screen,&dest);
}

main.cpp

Code:

#include “main.h”

SDL_Surface* Screen;
SDL_Event event;
TTF_Font* Font;

int ThisTime = 0;
int LastTime = 0;
float DeltaTime = 0.0f;

const int WIDTH = 800;
const int HEIGHT = 600;
const int DEPTH = 32;
const char* TITLE = “Tower Defense”;

SDL_Color textColor = {255,255,0};

int TowerHealth = 100;
int Points = 0;

int Money = 1000;
int EnemyHealth = 50;

int Bullet_Damage = 15;
int TowerCost = 200;

SDLKey keyPressed;
SDLKey keyReleased;

bool keysHeld[323] = {false};

bool GameRunning = true;
bool GameOver = false;

SDL_Surface* Backdrop;
SDL_Rect BackdropRect;

SDL_Surface* FPS;
SDL_Rect FPSRect;
char fps[10];

SDL_Surface* POINT;
SDL_Rect POINTRect;
char point[10];

int Damage_Frames;
int Current_Frame;
const int Total_Frames = 4;

SDL_Surface* HEALTH;
SDL_Rect HealthRect;
char health[10];

SDL_Surface* MONEY;
SDL_Rect MoneyRect;
char money[10];

int mx = 0;
int my = 0;

SDL_Surface* Bullet;
SDL_Rect BulletRect;

SDL_Surface* Enemy;
SDL_Rect EnemyRect;

bool GameScreen = true;

int main(int argc, char* argv[])
{
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}

Screen = SDL_SetVideoMode(WIDTH,HEIGHT,DEPTH, SDL_HWSURFACE | SDL_DOUBLEBUF);
SDL_WM_SetCaption(TITLE,NULL);

if(TTF_Init() == -1)
{
    return 1;
}

if(Mix_OpenAudio(22050,MIX_DEFAULT_FORMAT,2,4096) == -1)
{
    return 1;
}

Backdrop = IMG_Load("Backdrop.png");
BackdropRect.x = 0;
BackdropRect.y = 0;
BackdropRect.w = 800;
BackdropRect.h = 600;

//Bullet = IMG_Load("Bullet.png");
//SDL_SetColorKey(Bullet,SDL_SRCCOLORKEY,SDL_MapRGB(Bullet->format,255,255,255));

//Enemy = IMG_Load("Enemy.png");
//SDL_SetColorKey(Enemy,SDL_SRCCOLORKEY,SDL_MapRGB(Enemy->format,255,255,255));

Font = TTF_OpenFont("Arial.ttf",20);

FPSRect.x = 1;
FPSRect.y = 1;
FPSRect.w = 0;
FPSRect.h = 0;

POINTRect.x = 1;
POINTRect.y = 20;
POINTRect.w = 0;
POINTRect.h = 0;

HealthRect.x = 1;
HealthRect.y = 40;
HealthRect.w = 0;
HealthRect.h = 0;

MoneyRect.x = 1;
MoneyRect.y = 60;
MoneyRect.w = 0;
MoneyRect.h = 0;

while(GameRunning)
{
    ThisTime = SDL_GetTicks();
    DeltaTime = (float)(ThisTime - LastTime) / 1000;
    LastTime = ThisTime;

    sprintf(fps,"FPS: %.4f", DeltaTime);
    FPS = TTF_RenderText_Solid(Font,fps,textColor);

    sprintf(point,"Points: %.2d", Points);
    POINT = TTF_RenderText_Solid(Font,point,textColor);

    sprintf(health,"Health: %.3d",TowerHealth);
    HEALTH = TTF_RenderText_Solid(Font,health,textColor);

    sprintf(money,"Money: %.4d",Money);
    MONEY = TTF_RenderText_Solid(Font,money,textColor);

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

        if(event.type == SDL_KEYDOWN)
        {
            keyPressed = event.key.keysym.sym;
            keysHeld[event.key.keysym.sym] = true;

            if(keyPressed == SDLK_ESCAPE)
            {
                GameRunning = false;
            }
        }

        if(event.type == SDL_KEYUP)
        {
            keyReleased = event.key.keysym.sym;
            keysHeld[event.key.keysym.sym] = false;
        }

        if(event.type == SDL_MOUSEMOTION)
        {
            mx = event.motion.x;
            my = event.motion.y;
        }

        if(event.type == SDL_MOUSEBUTTONDOWN)
        {
            if(event.button.button == SDL_BUTTON_LEFT)
            {
                mx = event.button.x;
                my = event.button.y;
            }
        }
    }

    SDL_FillRect(Screen,NULL,SDL_MapRGB(Screen->format,0,0,0));

    SDL_BlitSurface(Backdrop,NULL,Screen,&BackdropRect);
    SDL_BlitSurface(FPS,NULL,Screen,&FPSRect);
    SDL_BlitSurface(POINT,NULL,Screen,&POINTRect);
    SDL_BlitSurface(HEALTH,NULL,Screen,&HealthRect);
    SDL_BlitSurface(MONEY,NULL,Screen,&MoneyRect);

    if(SDL_Flip(Screen) == -1)
    {
        return 1;
    }
}

SDL_FreeSurface(MONEY);
SDL_FreeSurface(HEALTH);
SDL_FreeSurface(FPS);
SDL_FreeSurface(Backdrop);
SDL_FreeSurface(POINT);

TTF_CloseFont(Font);
TTF_Quit();
Mix_CloseAudio();
SDL_Quit();

return 0;

}

Errors

Code:

C:\Users\Documents\TowerDefense\tower.cpp In constructor Tower::Tower(SDL_Surface*, int, int)': 5 C:\Users\Documents\TowerDefense\tower.cpp expected{’ before ‘;’ token
At global scope:
6 C:\Users\Documents\TowerDefense\tower.cpp expected unqualified-id before ‘{’ token
C:\Users\Documents\TowerDefense\Makefile.win [Build Error] [Objects/MingW/tower.o] Error 1

[/code]

Attach the source files.

The first 11 lines show up as:

include

I’ll hop on my linux box and see if I can hack it into shape.

  • Swyped from my droid.On Mar 24, 2012 10:21 PM, “GameCoder” <g_andy at live.com> wrote:

**
OK, I’ll post all the code and the error.

main.h

Code:

#include **
#include **
#include **
#include **
#include **
#include **
#include **
#include **
#include **
#include **
#include **

#include “SDL.h”
#include “SDL_image.h”
#include “SDL_ttf.h”
#include “SDL_mixer.h”

using namespace std;

Tower.h

Code:

class Tower
{
public:
SDL_Surface* Image;
int x,y;

    Tower(SDL_Surface* Image, int x, int y);
    void Draw(SDL_Surface* Screen) const;

};

Tower.cpp

Code:

#include “main.h”
#include “tower.h”

Tower::Tower(SDL_Surface* Image, int x, int y)
: Image(Image),x(x),y(y);
{}

void Tower::Draw(SDL_Surface* Screen) const
{
SDL_Rect dest = {x,y};
SDL_BlitSurface(Image,NULL,Screen,&dest);
}

main.cpp

Code:

#include “main.h”

SDL_Surface* Screen;
SDL_Event event;
TTF_Font* Font;

int ThisTime = 0;
int Las…

int Damage_Frames;
int Current_Frame;
const int Total_Frames = 4;

SDL_Surface* HEALTH;
SDL_Rect Hea…

//Bullet = IMG_Load("Bullet.png");
//SDL_SetColorKey(Bullet,SDL_SRCCOLORKEY,SDL_MapRGB(Bulle...

        if(event.type == SDL_MOUSEBUTTONDOWN)
        {
            if(event.button.butt...

    SDL_FillRect(Screen,NULL,SDL_MapRGB(Screen->format,0,0,0));

    SDL_BlitSurface(Backdro...

SDL_FreeSurface(MONEY);
SDL_FreeSurface(HEALTH);
SDL_FreeSurface(FPS);
SDL_FreeSurfa...

Errors

Code:

C:\Users\Documents\TowerDefense\tower.cpp In constructor
Tower::Tower(SDL_Surface*, int, int)': 5 C:\Users\Documents\TowerDefense\tower.cpp expected{’ before ‘;’ token
At global scope:
6 C:\Users\Documents\TowerDefense\tower.cpp expected unqualified-id before
’{’ token
C:\Users\Documents\TowerDefense\Makefile.win [Build Error]
[Objects/MingW/tower.o] Error 1

[/code]


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

On my linux box now, but judging by the error you posted, the constructor
line in your tower.cpp file should look like this:

Tower::Tower(SDL_Surface* Image, int x, int y) : Image(Image),x(x),y(y)
{}

without the semicolon.

Hey Thanks, it worked.