Mouse Over in SDL/C++ not working - c++

I have a simple script where by i want the script to load a second button when the mouse is hovering over the first initial button. But it won't return true so i can't seem to get it to work.
This is my class which checks the situation:
class Button
{
private:
int m_x, m_y;
int m_width, m_height;
public:
Button(int x, int y, int width, int height)
{
m_x = x;
m_y = y;
m_width = width;
m_height = height;
}
bool IsIn( int mouseX, int mouseY )
{
if (((mouseX > m_x) && (mouseX < m_x + m_width))
&& ((mouseY > m_y) && (mouseY < m_y + m_height ) ) ) {
return true;
} else {
return false;
}
}
void Render(SDL_Surface *source,SDL_Surface *destination)
{
SDL_Rect offset;
offset.x = m_x;
offset.y = m_y;
offset.w = m_width;
offset.h = m_height;
source = IMG_Load("button.png");
SDL_BlitSurface( source, NULL, destination, &offset );
}
};
Its the IsIn function I am trying to get to work... in my main loop i have:
while(!quit){
while( SDL_PollEvent( &event ) )
switch( event.type ){
case SDL_QUIT: quit = true; break;
case SDL_MOUSEMOTION: mouseX = event.motion.x; mouseY = event.motion.y; break;
}
Button btn_quit(screen->w/2,screen->h/2,0,0);
btn_quit.Render(menu,screen);
if(btn_quit.IsIn(mouseX,mouseY)){
Button btn_settings(screen->w/2,screen->h/2+70,0,0);
btn_settings.Render(menu,screen);
}
SDL_Quit works fine but i can't seem to get the if statement after the case statement to return true when i hover the mouse over the btn_quit button. Any ideas why this might be ?

Because btn_quit has no width or height, and therefore you can never be inside it's bounds.
Button btn_quit(screen->w/2,screen->h/2,0,0);
You checks will fail because your mouse position can never be >x && <x+0 or >y && <y+0.
Perhaps a better way would be to define the location of your button, and let get the dimensions from the loaded image?
class Button
{
public:
// Construct the button with an image name, and position on screen.
// This is important, your existing code loaded the image each render.
// That is not necessary, load it once when you construct the class.
Button(std::string name, int x, int y) : img(IMG_Load(name))
{
if(img) // If the image didn't load, NULL is returned.
{
// Set the dimensions using the image width and height.
offset.x = x; offset.y = y;
offset.w = img.w; offset.h = img.h;
}
else { throw; } // Handle the fact that the image didn't load somehow.
}
~Button() { SDL_FreeSurface(img); } // Make sure you free your resources!
void Render(SDL_Surface *destination)
{
// Simplified render call.
SDL_BlitSurface(img, NULL, destination, &offset );
}
bool Contains(int x, int y)
{
if((x>offset.x) && (x<offset.x+offset.w)
&& (y>offset.y) && (y<offset.y+offset.h))
return true; // If your button contains this point.
return false; // Otherwise false.
}
private:
SDL_Rect offset; // Dimensions of the button.
SDL_Surface* img; // The button image.
}

Related

SDL C++ Collision on multiple objects?

So I was determined to get collision working myself from online resources without asking for help & I successfully followed a tutorial on lazyfoo to get collision working but quickly realised other problems.
So I started trying to get my collision working on my player (just a rect with controls atm) but couldn't actually access the rect inside the player class, I had to initialize it in main & use that for collision which meant transferring my collision function to main (not exactly perfect).
My question: So my collision is limited to two rects which I dedicated to the player & a single asteroid but my idea was to create multiple asteroids coming from the top of the screen, how would I go about altering the below code to accept a vector of "asteroids". Any advice about altering my code to be better object oriented etc is more then welcome but my main problem is collision. Please read collision carefully before posting, the specific X and Y params from the .cpp provides are hardcoded there.
Below Code order:
My current way of defining both player & asteroid for collision
Collision function
Asteroid.cpp & Player.cpp
My new way of loading asteroids - This is what I need collision to work with
Player aPlayer(200, 50, 50, 50);
Asteroid oneAsteroid(200, -50, 50, 50);
bool check_collision(SDL_Rect aPlayer, SDL_Rect oneAsteroid) {
//The sides of the rectangles
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;
//Calculate the sides of rect A
leftA = aPlayer.X;
rightA = aPlayer.X + aPlayer.width;
topA = aPlayer.Y;
bottomA = aPlayer.Y + aPlayer.height;
//Calculate the sides of rect B
leftB = oneAsteroid.X;
rightB = oneAsteroid.X + oneAsteroid.width;
topB = oneAsteroid.Y;
bottomB = oneAsteroid.Y + oneAsteroid.height;
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;
}
#include "asteroids.h"
Asteroid::Asteroid()
{
}
Asteroid::~Asteroid()
{
}
Asteroid::Asteroid(int x, int y, int w, int h)
{
X = x; Y = y; width = w; height = h;
//SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Square Constructed with Param(&p)", this);
}
void Asteroid::Render(SDL_Renderer * aRenderer)
{
printf("");
SDL_Rect* aAsteroid = new SDL_Rect();
aAsteroid->x = X; aAsteroid->y = Y; aAsteroid->w = width; aAsteroid->h = height;
SDL_SetRenderDrawColor(aRenderer, 0, 0, 0, 255);
SDL_RenderFillRect(aRenderer, aAsteroid);
}
void Asteroid::Init()
{
velocity.X = 0;
velocity.Y = 5;
}
void Asteroid::Update()
{
Y = Y + velocity.Y;
// printf("%d \n", Astero);
if (Y > 650) {
Y = -50;
}
}
#include "Player.h"
#include "asteroids.h"
using namespace std;
Player::Player()
{
}
Player::~Player()
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Player Destroyed (&p)", this);
}
Player::Player(int x, int y, int w, int h)
{
X = x; Y = y; width = w; height = h;
//SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Square Constructed with Param(&p)", this);
}
void Player::Init()
{
velocity.X = 10;
velocity.Y = 10;
}
void Player::Update()
{
Y = Y + floorStart;
if (X < 0) {
X = 0;
}
if (KEY_RIGHT == true) {
X++;
}
if (X > SCREEN_WIDTH - 50) {
X = SCREEN_WIDTH - 50;
}
if (Y > SCREEN_HEIGHT - 100) {
Y = SCREEN_HEIGHT - 100;
}
if (KEY_LEFT == true) {
X--;
}
}
void Player::Input(SDL_Event event)
{
if (event.type == SDL_KEYDOWN && event.key.repeat == NULL)
{
if (event.key.keysym.sym == SDLK_LEFT) {
KEY_LEFT = true;
}
else {
KEY_LEFT = false;
}
if (event.key.keysym.sym == SDLK_RIGHT) {
KEY_RIGHT = true;
}
else {
KEY_RIGHT = false;
}
}
if (event.type == SDL_KEYUP && event.key.repeat == NULL) {
if (event.key.keysym.sym == SDLK_LEFT) {
KEY_LEFT = false;
}
if (event.key.keysym.sym == SDLK_RIGHT) {
KEY_RIGHT = false;
}
}
}
void Player::Render(SDL_Renderer * aRenderer)
{
SDL_Rect* thePlayer = new SDL_Rect;
thePlayer->x = X; thePlayer->y = Y; thePlayer->w = width; thePlayer->h = height;
SDL_SetRenderDrawColor(aRenderer, 0, 0, 0, 255);
SDL_RenderFillRect(aRenderer, thePlayer);
//SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Rendering (&p)", this);
}
What I need collision to work with, a vector of asteroids:
std::vector<Asteroid*> asteroidList;
asteroidList.push_back(new Asteroid(150, 350, 50, 50));
asteroidList.push_back(new Asteroid(70, 120, 125, 125));
The function to check collision in main.cpp
if (check_collision(aPlayer.thePlayer, oneAsteroid.aAsteroid)) {
printf("#######################");
}
And lastly, how would I go about rendering the array of asteroids?

Collision with more than 1 Object SDL 2.0-C++

I'am new there. I've been learning classes and tried to make a very simple platform game. But I have problem now. I've wanted to set Class "Player" to collide with 2 objects of Class "Block" But Collision do not work for one of them.
Here is my code:
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#undef main
class Block
{
private:
SDL_Texture *BlockTexture;
public:
Block(SDL_Renderer *renderTarget, std::string filePath, int xPos, int yPos, int Width, int Height);
~Block();
void Draw(SDL_Renderer *renderTarget);
SDL_Rect BlockPos;
};
Block::Block(SDL_Renderer *renderTarget, std::string filePath, int xPos, int yPos, int Width, int Height)
{
SDL_Surface *surface = IMG_Load(filePath.c_str());
{
BlockTexture = SDL_CreateTextureFromSurface(renderTarget, surface);
}
SDL_FreeSurface(surface);
BlockPos.x = xPos;
BlockPos.y = yPos;
BlockPos.w = Width;
BlockPos.h = Height;
}
Block::~Block()
{
SDL_DestroyTexture(BlockTexture);
}
void Block::Draw(SDL_Renderer *renderTarget)
{
SDL_RenderCopy(renderTarget, BlockTexture, NULL, &BlockPos);
}
class Player
{
private:
SDL_Texture *Texture;
float moveSpeed;
float jumpSpeed;
int falling = 0;
SDL_Scancode keys [3];
public:
SDL_Rect PlayerPos;
Player(SDL_Renderer *renderTarget, std::string filePath, int PosX, int PosY, int Width, int Height);
~Player();
void Update(float delta, const Uint8 *Keystate);
void Draw(SDL_Renderer *renderTarget);
bool Collision(Block &p);
};
Player::Player(SDL_Renderer *renderTarget, std::string filePath, int PosX, int PosY, int Width, int Height)
{
SDL_Surface *surface = IMG_Load(filePath.c_str());
{
Texture = SDL_CreateTextureFromSurface(renderTarget, surface);
}
SDL_FreeSurface(surface);
PlayerPos.x = PosX;
PlayerPos.y = PosY;
PlayerPos.w = Width;
PlayerPos.h = Height;
keys[0] = SDL_SCANCODE_UP;
keys[1] = SDL_SCANCODE_LEFT;
keys[2] = SDL_SCANCODE_RIGHT;
moveSpeed = 200.f;
jumpSpeed = 100.f;
}
Player::~Player()
{
SDL_DestroyTexture(Texture);
}
void Player::Update(float delta, const Uint8 *KeyState)
{
if(KeyState[keys[0]])
{
PlayerPos.y -= moveSpeed * delta;
}
if(KeyState[keys[1]])
{
PlayerPos.x -= (moveSpeed / 2) * delta;
}
if(KeyState[keys[2]])
{
PlayerPos.x += moveSpeed * delta;
}
if(falling == 0)
{
PlayerPos.y += jumpSpeed * delta;
}
}
void Player::Draw(SDL_Renderer *renderTarget)
{
SDL_RenderCopy(renderTarget, Texture, NULL, &PlayerPos);
}
bool Player::Collision(Block &p)
{
if(PlayerPos.x + PlayerPos.w <= p.BlockPos.x || PlayerPos.x >= p.BlockPos.x + p.BlockPos.w ||
PlayerPos.y + PlayerPos.h <= p.BlockPos.y || PlayerPos.y >= p.BlockPos.y + p.BlockPos.h)
{
falling = 0;
return true;
}
else
falling = 1;
return false;
}
SDL_Texture *LoadTexture(std::string filePath, SDL_Renderer *Renderer)
{
SDL_Texture *texture = NULL;
SDL_Surface *surface = IMG_Load(filePath.c_str());
{
texture = SDL_CreateTextureFromSurface(Renderer, surface);
}
SDL_FreeSurface(surface);
return texture;
}
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow("Platform", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
SDL_Renderer *renderTarget = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
int imgFlags = IMG_INIT_PNG;
int currentTime = 0;
int previousTime = 0;
float delta = 0;
const Uint8 *Keystate;
Player Player(renderTarget, "BlockP.png", 100, 100, 50, 50);
Block Block1(renderTarget, "Block.png", 0, 500, 800, 100);
Block Block2(renderTarget, "Block.png", 100, 300, 300, 50);
bool isRunning = true;
SDL_Event ev;
while(isRunning)
{
Keystate = SDL_GetKeyboardState(NULL);
Player.Collision(Block1);
Player.Collision(Block2);
previousTime = currentTime;
currentTime = SDL_GetTicks();
delta = (currentTime - previousTime) / 1000.0f;
Player.Update(delta, Keystate);
while(SDL_PollEvent(&ev) != 0)
{
if(ev.type == SDL_QUIT)
isRunning = false;
}
SDL_RenderClear(renderTarget);
Player.Draw(renderTarget);
Block1.Draw(renderTarget);
Block2.Draw(renderTarget);
SDL_RenderPresent(renderTarget);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderTarget);
window = NULL;
renderTarget = NULL;
SDL_Quit();
return 0;
}
The problem with your code is that each call to Player.Collision overwrites the "falling" variable.
Player.Collision(Block1); //this call calculates a falling value
Player.Collision(Block2); //...then this call overwrites falling with a new value
So effectively your code is only testing if the player is colliding with Block2, so collisions with Block1 are ignored.
Currently your Collision function is:
bool Player::Collision(Block &p)
{
if(PlayerPos.x + PlayerPos.w <= p.BlockPos.x || PlayerPos.x >= p.BlockPos.x + p.BlockPos.w ||
PlayerPos.y + PlayerPos.h <= p.BlockPos.y || PlayerPos.y >= p.BlockPos.y + p.BlockPos.h)
{
falling = 0;
return true;
}
else
falling = 1;
return false;
}
Firstly, your "return false;" is not actually part of the else, as you don't have {}. In this particular case it makes no difference as the else is exited and then the return happens but your indentation would suggest you expect the "return false;" line to be executed as part of the else block so you should put:
else
{
falling = 1;
return false;
}
Next you want to say if you have already detected a collision (eg, with Block1) then don't set falling to 1, to do this add an if statement.
else
{
if(falling != 0) //if we haven't already detected a collision this frame
{
falling = 1;
}
return false;
}
You will however need to set falling back to 1 at the start of each frame, otherwise if a collision is detected on one frame then the player will never fall on subsequent frames, even if they are not colliding with a block.
As a side note, your Player.Update code modifies the player's y position if falling == 0, this seems counter intuitive as usually 0 is false and 1 is true, hence you seem to be saying if not falling then update y, where as it should be if falling update y. Personally I would use a bool rather than an int to hold the value of falling, and then say if(falling) update y, this would make your code clearer.

Bug in Button class - Windows triggered a breakpoint SDL

I am a novice C++ programmer, and I have been experimenting with the SDL libraries for 2d graphics. I have been messing around with try to create some simple GUI controls; however, my button control is having a weird issue that I have been unable to resolve.
Whenever I launch the program in debug mode Visual Studio immediately gives me an error window saying
"Windows has triggered a breakpoint in Default_SDL_Setup.exe.
This may be due to a corruption of the heap, which indicates a bug in
Default_SDL_Setup.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while
Default_SDL_Setup.exe has focus.
The output window may have more diagnostic information."
and pops up a file called crtexe.c in the code editor window.
I have no idea what is wrong or what is going on.
Here is my button header:
#ifndef BUTTON_T
#define BUTTON_T
#include <vector>
#include <string>
#include "SDL.h"
#include "SDL_ttf.h"
#include "SDLFunctions.h"
#endif
class button
{
private:
//refreshes the button
void refresh_image();
bool refresh;
//surface to hold the created text
SDL_Surface *message;
//color of text
SDL_Color tC;
//the different box types
struct boxColor
{
unsigned int r;
unsigned int g;
unsigned int b;
};
boxColor boxes[4];
SDL_Rect rects[4];
//font of text
TTF_Font *f;
/*button's state
* States are:
* 0 - mouseout
* 1 - mouseover
* 2 - mousedown
* 3 - mouseup
*/
int state;
public:
//autosize based off of text?
bool autoSize;
//size of text
int textSize;
//x,y,w,and h for the box
int x, y, w, h;
//text of the label
std::string text;
button(int xpos, int ypos, int width, int height);
~button();
//handles all events for the button
void handleEvents(SDL_Event *event);
//sets text's font style off of a string location, color expects a 3 dimensional array
void setFont(std::string fontFileLocation);
void setFont(int color[3]);
void setFont(std::string fontFileLocation, int color[3]);
//gets the text color as a vector
std::vector<int> textColor();
//returns the color of the specified box
std::vector<int> boxColor(int boxnum);
//sets the color of the specified box, expects a 3 dimensional array
void setBoxColor(int boxnum, int color[3]);
void render(SDL_Surface *screen);
};
Here is the button code:
#include "button.h"
using namespace std;
void button::refresh_image()
{
if (refresh)
{
if (f != NULL)
{
message = TTF_RenderText_Solid(f, text.c_str(), tC);
if ((message != NULL) && autoSize)
{
if (message->w >= w)
{
w = (message->w + 10);
}
if (message->h >= h)
{
h = (message->h + 10);
}
}
}
for (int i = 0; i != 4; ++i)
{
rects[i].x = x;
rects[i].y = y;
rects[i].w = w;
rects[i].h = h;
}
refresh = false;
}
}
button::button(int xpos, int ypos, int width, int height)
{
string defaultFontLocation = DEFAULT_FONT;
//set pos
x = xpos;
y = ypos;
w = width;
h = height;
//set text stuff
text = "";
textSize = DEFAULT_FONT_SIZE;
tC.r = 0;
tC.g = 0;
tC.b = 0;
f = TTF_OpenFont(defaultFontLocation.c_str(), textSize);
message = NULL;
//create box types
state = 0;
for (int i = 0; i != 4; ++i)
{
boxes[i].r = 255;
boxes[i].g = 255;
boxes[i].b = 255;
rects[i].x = x;
rects[i].y = y;
rects[i].w = w;
rects[i].h = h;
}
autoSize = true;
refresh = true;
refresh_image();
}
button::~button()
{
if (f != NULL)
{
TTF_CloseFont(f);
}
if (message != NULL)
{
SDL_FreeSurface(message);
}
}
void button::setFont(string fontFileLocation)
{
if (f != NULL)
{
TTF_CloseFont(f);
}
f = TTF_OpenFont(fontFileLocation.c_str(), textSize);
refresh_image();
}
void button::setFont(int color[3])
{
tC.r = color[0];
tC.g = color[1];
tC.b = color[2];
refresh_image();
}
void button::setFont(string fontFileLocation, int color[3])
{
if (f != NULL)
{
TTF_CloseFont(f);
}
f = TTF_OpenFont(fontFileLocation.c_str(), textSize);
tC.r = color[0];
tC.g = color[1];
tC.b = color[2];
refresh_image();
}
vector<int> button::textColor()
{
vector<int> colors;
colors.resize(3);
colors[0] = tC.r;
colors[1] = tC.g;
colors[2] = tC.b;
return colors;
}
vector<int> button::boxColor(int boxnum)
{
vector<int> colors;
colors.resize(3);
if ((boxnum <= 3) && (boxnum >= 0))
{
colors[0] = boxes[boxnum].r;
colors[1] = boxes[boxnum].g;
colors[2] = boxes[boxnum].b;
} else {
colors[0] = -1;
colors[1] = -1;
colors[2] = -1;
}
return colors;
}
void button::setBoxColor(int boxnum, int color[3])
{
if ((boxnum <= 3) && (boxnum >= 0))
{
boxes[boxnum].r = color[0];
boxes[boxnum].g = color[1];
boxes[boxnum].b = color[2];
//refresh_image();
}
}
void button::render(SDL_Surface *screen)
{
refresh_image();
SDL_FillRect(screen, &rects[state], SDL_MapRGB(screen->format, static_cast<Uint8>(boxes[state].r), static_cast<Uint8>(boxes[state].g), static_cast<Uint8>(boxes[state].b)));
if (message != NULL)
{
apply_surface((((x + w) - message->w) / 2), (((y + h) - message->h) / 2), message, screen);
}
refresh = true;
}
void button::handleEvents(SDL_Event *event)
{
//the mouse offsets
int mx, my;
//if mouse moved
if (event->type == SDL_MOUSEMOTION)
{
//get the mouse offsets
mx = event->motion.x;
my = event->motion.y;
//if the mouse is over the button
if ((mx > x) && (mx < (x + w)) && (my > y) && (my < (y + h)))
{
//set the button sprite
state = 1;
} else {
//set the button sprite
state = 0;
}
}
//if a mouse button was pressed
if (event->type == SDL_MOUSEBUTTONDOWN)
{
//if it was the left mouse button
if (event->button.button == SDL_BUTTON_LEFT)
{
//get the mouse offsets
mx = event->motion.x;
my = event->motion.y;
//if the mouse is over the button
if ((mx > x) && (mx < (x + w)) && (my > y) && (my < (y + h)))
{
//set the button sprite
state = 2;
}
}
}
//if a mouse button was released
if (event->type == SDL_MOUSEBUTTONUP)
{
//if it was the left mouse button
if (event->button.button == SDL_BUTTON_LEFT)
{
//get the mouse offsets
mx = event->motion.x;
my = event->motion.y;
//if the mouse is over the button
if ((mx > x) && (mx < (x + w)) && (my > y) && (my < (y + h)))
{
//set the button sprite
state = 3;
}
}
}
}
and here is the code I have been calling to create the button in my main() function:
int color1[3] = {105,240,81};
int color2[3] = {230,188,62};
button testbutton(360, 130, 50, 30);
testbutton.text = "TEST";
testbutton.setBoxColor(1, color1);
testbutton.setBoxColor(2, color2);
delete[] &color1;
delete[] &color2;
The problem is most probably in these two lines:
delete[] &color1;
delete[] &color2;
color1 and color2are automatic variables, and calling delete on them invokes undefined behavior. You should only delete variables you previously allocated with new.

Unhandled exception in font render function C++ SDL

I'm working on a PONG clone and just on the title screen. I have a class to work the title screen loop of the state machine and it uses very little, only a single sprite and a single true type font message. But when I call the function to render the message onto the SDL_Surface, it throws my program into whack. The error I receive is Unhandled exception at 0x6F4C2A9D (SDL_ttf.dll) in Pong.exe: 0xC0000005: Access violation reading location 0x00000000. Usually this means that I didn't initialize something or didn't define it in the class definition or something, but it all seems in order. So I'll post the code here in hopes that someone sees what's up with the render function or the bits surrounding it.
To be perfectly clear the exception is thrown on this line:
Title_Message = TTF_RenderText_Solid(font, "PONG", color);
//start code
/*CLASSES*/
class GameState
{
public:
virtual void events() = 0;
virtual void logic() = 0;
virtual void render() = 0;
virtual ~GameState(){};
};
class Button
{
public:
SDL_Rect button_clip[2];
SDL_Rect button;
SDL_Surface *button_sprite = NULL;
Button();
};
class Title : public GameState
{
private:
SDL_Surface *Title_Message = NULL;
SDL_Rect *clip;
Button Title_Button;
public:
void events();
void logic();
void render();
Title();
~Title();
};
/*FONTS*/
SDL_Color color = { 255, 255, 255 };
TTF_Font *font = NULL;
bool init()
{
//initialize all SDL subsystems
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return false;
}
//set up screen
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
//check screen
if (screen == NULL)
{
return false;
}
//init TTF
if (TTF_Init() == -1)
{
return false;
}
//set window caption
SDL_WM_SetCaption("PONG", NULL);
//if evetything worked
return true;
}
//load files
bool load_files()
{
font = TTF_OpenFont("PIXELITE.ttf", 45);
if (font == NULL)
{
return false;
}
return true;
}
/*CLASS DEFINITIONS*/
Button::Button()
{
}
Title::Title()
{
Title_Message = TTF_RenderText_Solid(font, "PONG", color);
Title_Button.button_sprite = load_image("Start.png");
Title_Button.button.x = 200;
Title_Button.button.y = 350;
Title_Button.button.w = 100;
Title_Button.button.h = 50;
//clips not hover
Title_Button.button_clip[0].x = 0;
Title_Button.button_clip[0].y = 0;
Title_Button.button_clip[0].w = 100;
Title_Button.button_clip[0].h = 50;
//clips hover
Title_Button.button_clip[1].x = 0;
Title_Button.button_clip[1].y = 50;
Title_Button.button_clip[1].w = 100;
Title_Button.button_clip[1].h = 50;
}
Title::~Title()
{
SDL_FreeSurface(Title_Message);
SDL_FreeSurface(Title_Button.button_sprite);
}
void Title::events()
{
int x = 0;
int y = 0;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_MOUSEMOTION)
{
x = event.motion.x;
y = event.motion.y;
if ((x > Title_Button.button.x) && (x < (Title_Button.button.x + Title_Button.button.w)) && (y > Title_Button.button.y) && (y < (Title_Button.button.y + Title_Button.button.h)))
{
clip = &Title_Button.button_clip[1];
}
else
{
clip = &Title_Button.button_clip[0];
}
}
if (event.type == SDL_QUIT)
{
quit = true;
}
}
}
void Title::logic()
{
}
void Title::render()
{
apply_surface(Title_Button.button.x, Title_Button.button.y, Title_Button.button_sprite, screen, clip);
apply_surface((SCREEN_WIDTH - Title_Message->w) / 2, 100, Title_Message, screen);
}
Anybody got an idea? Thanks!
I will post my suggestions from the comments as an actual answer:
The trouble-causing line Title_Message = TTF_RenderText_Solid(font, "PONG", color); refers to the global variable font of type TTF_Font*. The line is also part of the constructor of the class Title.
main looks like this:
int main(int argc, char* args[])
{
//init SDL
init();
//load everything
load_files();
currentState = new Title;
//...
font is initialized to NULL at declaration, an actual object is assigned only in load_files() which is executed at the beginning of main before Title is the first time instantiated.
So load_files() has to assign a valid pointer to font, otherwise the next line in main will cause an access violation.
load_files() provides a return value depending on whether creating and assigning this object was successful. However main never checks for this value and thus it is not guaranteed that font is a valid pointer.
As knefcy pointed out the problem was a wrong filename in load_files().

SDL Mouse position Cropped after resize

I'm getting some strange behaviour with the mouse position in SDL. If I re-size the window bigger, the x,y positions from either mouse events, seem to be restricted to the original window Width and Height.
If there some function call that I'm missing to tell SDL that the mousing area has increased in size.
The relevant parts of the app:
void Resize(int width, int height)
{
WindowWidth = width;
WindowHeight = height;
/* update OpenGL */
}
void Init()
{
glClearColor(0.f, 0.f, 0.f, 1.f);
Resize(WindowWidth, WindowHeight);
}
void MouseClick(int button, int state, int x, int y)
{
unsigned int MouseButton = unsigned(Mouse.z);
unsigned int b = (1 << (button-1));
if (state)
MouseButton = MouseButton | b;
else
MouseButton = MouseButton & (~b);
Mouse.z = MouseButton;
Mouse.x = x;
Mouse.y = y;
}
void MouseMove(int x, int y)
{
MouseRel.x = x - Mouse.x;
MouseRel.y = y - Mouse.y;
Mouse.x = x;
Mouse.y = y;
}
int main(int agrc, char *argv[])
{
bool quit = false;
SDL_Event event;
if ( SDL_Init(SDL_INIT_VIDEO) < 0)
return 1;
if (SDL_SetVideoMode(WindowWidth, WindowHeight, 0, SDL_OPENGL | SDL_RESIZABLE) == NULL)
return 2;
Init();
while (!quit)
{
DrawScene();
while ( SDL_PollEvent(&event) )
{
if ( event.type == SDL_VIDEORESIZE)
{
Resize(event.resize.w, event.resize.h);
}
else if ( event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP )
{
MouseClick(event.button.button, event.button.state, event.button.x, WindowHeight - event.button.y);
printf("event.button (%i, %i)\n", event.button.x, event.button.y);
MouseHandler();
}
else if ( event.type == SDL_MOUSEMOTION )
{
MouseMove(event.motion.x, WindowHeight - event.motion.y);
printf("event.motion (%i, %i)\n", event.motion.x, event.motion.y);
MouseHandler();
}
else if (event.type == SDL_QUIT)
quit |= true;
}
quit |= KeyboardHandler();
SDL_Delay(10);
}
SDL_Quit();
return 0;
}
Try re-calling SDL_SetVideoMode() in your SDL_VIDEORESIZE handler.