Segmentation fault on library call - c++

I'm using a physics library called Chipmunk for a game that I'm writing.
In my initialize function I initialize the global variable cpSpace space. Then in update I call cpSpaceStep(space, timestep). The prototype for this function is void cpSpaceStep(cpSpace *space, cpFloat dt);. I'm getting a segfault on this function call. I've marked those two function calls in the code below.
The full code is below:
#include "../include/SDL/SDL_image.h"
#include "../include/SDL/SDL.h"
#include "../include/Player.h"
#include "../include/Timer.h"
#include "../include/Block.h"
#include "../include/ImageLoader.h"
#include "../include/chipmunk/chipmunk.h"
#include <string>
//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
//The frame rate
const int FRAMES_PER_SECOND = 60;
SDL_Event event;
SDL_Surface *screen = NULL;
SDL_Surface *player_img = NULL, *block_img = NULL;
Player *player;
Timer fps;
cpSpace *space;
bool quit = false;
void initialize();
void update();
int main( int argc, char* argv[] )
{
initialize();
update();
return 1;
}
void initialize()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
}
//Set up the screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
//If there was an error in setting up the screen
if( screen == NULL )
{
}
//Set the window caption
SDL_WM_SetCaption( "Move the Dot", NULL );
cpVect gravity = cpv(0, 100);
//******************cpSpacenew()*****************
//This is where space is init'ed
space = cpSpaceNew();
//***********************************************
}
void update()
{
//While the user hasn't quit
while( quit == false )
{
//Start the frame timer
fps.start();
while( SDL_PollEvent( &event ) )
{
//Handle events for the dot
player->handle_input( &event );
//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
quit = true;
}
}
player->update();
cpFloat timeStep = 1.0/FRAMES_PER_SECOND;
//************************Segfault**********************************************
cpSpaceStep(space, timeStep);
//******************************************************************************
//Cap the frame rate
if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
{
SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
}
}
}

Where's your cpInitChipmunk() call? Without that, it's likely that cpSpaceNew() may well return NULL (or junk).
Easy enough to check. Immediately after the call to cpSpaceNew(), insert a:
printf ("%p\n", space);
(or something equivalent, to see what the value is.
You may also want to do that immediatley before trying to use it as well, just in case something corrupts it.

Could be because space is NULL when you call cpSpaceStep(). And in cpSpaceStep() function, an attempt is done to dereference the pointer which is NULL. Check whether space is properly initialized in initialize().

Related

SIGSEGV Segmentation Fault when dereferencing a pointer

I'm aware that there are several similar questions to this one already, but I've read through them and none of them seem to cover my specific problem...
I'm trying to dereference a public pointer from a struct, but it's throwing a SIGSEV Segmentation fault, even though the pointer does point to a value
It prints 1 & 2 but does not get any further. If I change it to reference the pointer rather than the value, the error moves to wherever I reference the value, so I know the issue is with dereferencing, not the rest of the line.
If you need to see any more of my code in order to find the issue, just ask. I just didn't want to make you trawl through hundreds of lines unnecesarily...
#include <vector>
#include "Entities.cpp"
struct Chunk {
public:
std::vector<BaseEntity>* environment; // this is what I'm trying to access
Chunk() {
environment = new std::vector<BaseEntity>(1); // this is where init
environment->push_back(Grass()); // adding something to it works fine
}
~Chunk() {
delete(environment);
}
};
class World {
public:
Chunk* loaded[3][3];
World() {
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++) {
loaded[x][y] = new Chunk();
}
}
~World() {
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++) {
delete(loaded[x][y]);
}
}
};
And here's the code that accesses it (in another class & file)
void render(SDL_Renderer* gRenderer, Atlas* atlas, World* world, int SCREEN_WIDTH, int SCREEN_HEIGHT) {
printf("1");
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++) {
printf("2");
std::vector<BaseEntity> env =
*(world->loaded[x][y]->environment); // here is where the error occurs
printf("3");
printf('0' + env.size() + "");
printf("a");
for (const auto& a : env) {
printf("b");
drawTexture(gRenderer, atlas, a.atlasID,
SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
}
printf("4");
}
printf("5");
}
This is the code that calls it:
int main(int argv, char** args) {
SDL_Init( SDL_INIT_VIDEO );
//The window we'll be rendering to
SDL_Window* gWindow = SDL_CreateWindow(
title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if (gWindow == NULL) {
printf("window error");
}
//Create renderer for window
SDL_Renderer* gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
if (gRenderer == NULL) {
printf("renderer error");
}
bool quit = false; // quit flag
//Event handler
SDL_Event e;
//nice little rendering class
Renderer* renderer = new Renderer();
//World
World* world = new World();
//Texture Atlas
Atlas* atlas = new Atlas(SDL_GetWindowSurface( gWindow), gRenderer);
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
switch(e.type) {
case SDL_QUIT: //User requests quit
quit = true;
break;
}
}
//Clear screen
//SDL_SetRenderDrawColor( gRenderer, 0, 0xFF, 0, 0xFF );
SDL_RenderClear( gRenderer );
renderer->render(gRenderer, atlas, world, SCREEN_WIDTH, SCREEN_HEIGHT);
//Update the surface
SDL_RenderPresent(gRenderer);
//SDL_UpdateWindowSurface( gWindow );
}
delete (world, renderer, atlas);
return 0;
}
This allocates a std::vector with one element of BaseEntity
environment = new std::vector<BaseEntity>(1); // this is where init
then another element of Grass is appended
environment->push_back(Grass()); // adding something to it works fine
but maybe this is the first problem, since the vector only holds BaseEntitys, see What is object slicing?
This accesses the first element of the given vector, and this is not the appended Grass but the default constructed BaseEntity object from new std::vector<BaseEntity>(1)
std::vector<BaseEntity> env = *(world->loaded[x][y]->environment); // here is where the error occurs
Accessing the pointer shouldn't be a problem, because it seems to be initialized properly.
But maybe copying the BaseEntity is the real problem here. I would look into the (copy) constructor of BaseEntity (and maybe Grass) and see, if there is some problematic code.
I don't see an immediate problem with your code (except copying the vector is obviously inefficient), but I do see a problem with your printf debugging.
You should use fprintf(stderr, ...) for debug printfs, so as to avoid stdio buffering, or call fflush(NULL).
The fact that 3 is not printed does not necessarily mean that printf("3") is unreached.
You should avoid printf debugging altogether, and learn to use a real debugger (GDB or LLDB) instead.
If you run your program with Address Sanitizer (-fsanitize=address); it will likely point you straight at the bug.
Finally, when writing in C++, avoid C-style arrays, and especially multi-level arrays. Use vectors instead.

Error multiple definition when compiling using headers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am having a lot of trouble with my header files and the compilation. I have everything linked with header guards but for some reason I am still getting a lot of multiple definition errors. I'm also look for help on better way to organize code. Whatever help is appreciated!
This is the out output of my console when I do the g++ call:
g++ main.cpp close.cpp init.cpp load_media.cpp texture.cpp -w -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -o run
/tmp/cc3oNgPs.o:(.bss+0x0): multiple definition of `g_font'
/tmp/ccg0hCKW.o:(.bss+0x0): first defined here
/tmp/cc3oNgPs.o:(.bss+0x8): multiple definition of `g_window'
/tmp/ccg0hCKW.o:(.bss+0x8): first defined here
/tmp/cc3oNgPs.o:(.bss+0x10): multiple definition of `g_renderer'
/tmp/ccg0hCKW.o:(.bss+0x10): first defined here
/tmp/cc3oNgPs.o:(.bss+0x20): multiple definition of `g_text_texture'
/tmp/ccg0hCKW.o:(.bss+0x20): first defined here
/tmp/ccIgzhbZ.o:(.bss+0x0): multiple definition of `g_font'
/tmp/ccg0hCKW.o:(.bss+0x0): first defined here
/tmp/ccIgzhbZ.o:(.bss+0x8): multiple definition of `g_window'
/tmp/ccg0hCKW.o:(.bss+0x8): first defined here
/tmp/ccIgzhbZ.o:(.bss+0x10): multiple definition of `g_renderer'
/tmp/ccg0hCKW.o:(.bss+0x10): first defined here
/tmp/ccIgzhbZ.o:(.bss+0x20): multiple definition of `g_text_texture'
/tmp/ccg0hCKW.o:(.bss+0x20): first defined here
/tmp/ccQs9gPv.o:(.bss+0x0): multiple definition of `g_font'
/tmp/ccg0hCKW.o:(.bss+0x0): first defined here
/tmp/ccQs9gPv.o:(.bss+0x8): multiple definition of `g_window'
/tmp/ccg0hCKW.o:(.bss+0x8): first defined here
/tmp/ccQs9gPv.o:(.bss+0x10): multiple definition of `g_renderer'
/tmp/ccg0hCKW.o:(.bss+0x10): first defined here
/tmp/ccQs9gPv.o:(.bss+0x20): multiple definition of `g_text_texture'
/tmp/ccg0hCKW.o:(.bss+0x20): first defined here
/tmp/ccxzUgM2.o:(.bss+0x0): multiple definition of `g_font'
/tmp/ccg0hCKW.o:(.bss+0x0): first defined here
/tmp/ccxzUgM2.o:(.bss+0x8): multiple definition of `g_window'
/tmp/ccg0hCKW.o:(.bss+0x8): first defined here
/tmp/ccxzUgM2.o:(.bss+0x10): multiple definition of `g_renderer'
/tmp/ccg0hCKW.o:(.bss+0x10): first defined here
/tmp/ccxzUgM2.o:(.bss+0x20): multiple definition of `g_text_texture'
/tmp/ccg0hCKW.o:(.bss+0x20): first defined here
collect2: error: ld returned 1 exit status
here are my 2 header files:
isolation.h
//include //include guard
#ifndef ISOLATION_H
#define ISOLATION_H
//include dependencies
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <string>
//include headers
#include "texture.h"
//Screen dimension constants
const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 800;
//forward delcarlation
//class Texture;
//start up SDL create window
bool init();
//load all media
bool load_media();
//free all and shut down SDL
void close();
//load global front
TTF_Font* g_font = NULL;
//window
SDL_Window* g_window = NULL;
//renderer
SDL_Renderer* g_renderer = NULL;
//load jpeg + font
//Texture background_texture;
//rendered font texture
Texture g_text_texture;
#endif
texture.h
//include guard
#ifndef TEXTURE_H
#define TEXTURE_H
//include dependencies
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <string>
//include headers
//#include "isolation.h"
class Texture {
public:
//initializes variables
Texture();
//deallocates memory
~Texture();
//load image from path
bool load_from_file( std::string path );
//create image from font string
bool load_from_rendered_text( std::string textureText, SDL_Color text_color );
//deallocates texture
void free();
//set color modulation
void set_color( Uint8 red, Uint8 green, Uint8 blue );
//set blend mode
void set_blend_mode( SDL_BlendMode blending );
//set alpha
void set_alpha( Uint8 alpha );
//render texture at point
void render( int x, int y, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE ) const;
//get image dimensions
int get_width() const;
int get_height() const;
private:
//texture pointer
SDL_Texture* m_texture;
//dimensions
int m_width;
int m_height;
};
#endif
init.cpp
#include "isolation.h"
//#include "texture.h"
bool init() {
//initialization flag
bool success = true;
//initialize SDL
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
printf( "SDL could not initialized. SDL Error: %s\n", SDL_GetError() );
success = false;
}
else {
//set texture filtering linear
if ( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) ) {
printf( "Warning: Linear filtering not enabled\n" );
}
//create window
g_window = SDL_CreateWindow( "Isolation", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if ( g_window == NULL ) {
printf( "Window could not be created. SDL Error: %s\n", SDL_GetError() );
success = false;
}
else {
//create vsynced renderer
g_renderer = SDL_CreateRenderer( g_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
if ( g_renderer == NULL ) {
printf( "Renderer could not be created. SDL Error: %s\n", SDL_GetError() );
success = false;
}
else {
//initialize renderer color
SDL_SetRenderDrawColor (g_renderer, 0xFF, 0xFF, 0xFF, 0xFF );
//initialize JPEG loading
int img_flags = IMG_INIT_JPG;
if ( !( IMG_Init( img_flags ) & img_flags ) ) {
printf( "SDL_image could not be initialize. SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
//initialize SDL_ttf
if (TTF_Init() == -1 ) {
printf( "SDL_ttf could not be initialize. SDL_ttf Error: %s\n", TTF_GetError() );
}
}
}
}
return success;
}
load_media.cpp
#include "isolation.h"
//s#include "texture.h"
bool load_media() {
bool success = true;
//load background img
//if( !background_texture.load_from_file( "img/vancouver.jpg" ) ) {
// printf( "Failed to load background texture!\n" );
// success = false;
//}
//open font
g_font = TTF_OpenFont( "lazy.ttf", 28 );
if ( g_font == NULL ) {
printf( "Failed to load lazy font. SDL_ttf Error: %s\n", TTF_GetError() );
success = false;
}
else {
//render texture
SDL_Color text_color = { 0, 0, 0 };
if ( !g_text_texture.load_from_rendered_text( "hello from the other side ", text_color ) ) {
printf( "Failed to render text texture\n" );
success = false;
}
}
return success;
}
close.cpp
#include "isolation.h"
//#include "texture.h"
void close() {
//free loaded text
g_text_texture.free();
//free font
TTF_CloseFont( g_font );
g_font = NULL;
//destroy window
SDL_DestroyWindow( g_window );
SDL_DestroyRenderer( g_renderer );
g_window = NULL;
g_renderer = NULL;
//quit SDL subsystems
TTF_Quit();
IMG_Quit();
SDL_Quit();
}
main.cpp
#include "isolation.h"
//#include "texture.h"
int main( int argc, char* args[] ) {
//start up SDL
if ( !init() ) {
printf( "Failed to initialize.\n" );
}
else {
//load media
if ( !load_media() ) {
printf( "Failed to load media.\n" );
}
else{
//main loop flag
bool quit = false;
//event handler
SDL_Event e;
//while running
while ( !quit ) {
//handle events on queue
while ( SDL_PollEvent( &e ) != 0 ) {
//user quit
if ( e.type == SDL_QUIT ) {
quit = true;
}
}
//clear screen
SDL_SetRenderDrawColor( g_renderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( g_renderer );
//render frame
g_text_texture.render( ( SCREEN_WIDTH - g_text_texture.get_width() ) / 2, ( SCREEN_HEIGHT - g_text_texture.get_height() ) / 2 );
//update screen
SDL_RenderPresent( g_renderer );
}
}
}
//free memory and close SDL
close();
return 0;
}
Do not mix declaration with definition/instantiation in a .h file. Your are instantiating g_font, g_window and g_renderer in isolation.h file. The correct is instantiating only once, usually, in a .cpp
To solve your problem, change isolation.h to declare those variables as external linkage:
//load global front
extern TTF_Font* g_font;
//window
extern SDL_Window* g_window;
//renderer
extern SDL_Renderer* g_renderer;
and instantiate them only once in an appropriate .cpp file, for example, init.cpp

Displaying a PNG in SDL?

I am trying to get a knight on a horse (inauspiciously named "guy") to run across the screen. The knight currently exists in my directory as 2 .png files, to simulate some poorly animated galloping. I was able to get him to appear when he was a .bmp, but I would like to utilize the transparency of png files - I've also tried and failed with opening tif files. How can I alter my code in order to get him to appear from a .png loaded into SDL correctly?
Here is my .cpp file:
#include "SDL/SDL.h"
#include <iostream>
#include "source_sdl.h"
# include <string>
using namespace std;
int source_sdl( int argc, char* args[] ) {
int switch = 1;
int running = 1;
// surface & rect declarations
SDL_Surface* ground = NULL;
SDL_Surface* guy = NULL;
SDL_Surface* guy2 = NULL;
SDL_Rect guylocationRect;
SDL_Rect groundlocationRect;
// initialize SDL & the screen
SDL_Init( SDL_INIT_EVERYTHING );
screen = SDL_SetVideoMode( 875, 625, 32, SDL_SWSURFACE );
// open .png files
SDL_RWops* guy_rwop;
SDL_RWops* guy2_rwop;
guy_rwop = SDL_RWFromFile("tiffKnight.png", "rb");
guy2_rwop = SDL_RWFromFile("tiffKnight2.png", "rb");
guy = IMG_LoadPNG_RW(guy_rwop);
guy2 = IMG_LoadPNG_RW(guy2_rwop);
guylocationRect.x = 300;
guylocationRect.y = 300;
groundlocationRect.x = 300;
groundlocationRect.y = 300;
SDL_Event occur;
// animation loop (currently endless)
while (running == 1){
SDL_Flip( screen );
SDL_Delay( 300 );
if (gallop > 89) gallop=0;
// draw the ground
for( int yu = 0; yu<35; yu++){
groundlocationRect.x=25*yu;
groundlocationRect.y=5*25;
SDL_BlitSurface( ground, NULL, screen, &groundlocationRect );
}
// draw the gallopping
guylocationRect.x=10*gallop;
guylocationRect.y=5*25;
if( switch ){
SDL_BlitSurface( guy, NULL, screen, &guylocationRect );
}else{
SDL_BlitSurface( guy2, NULL, screen, &guylocationRect );
}
gallop++;
switch = (switch+1)%2;
for(int u = 6; u < 25; u++){
for(int yu = 0; yu < 35; yu++){
groundlocationRect.x = 25*yu;
groundlocationRect.y = 25*u;
SDL_BlitSurface( ground, NULL, screen, &groundlocationRect );
}
}
}
SDL_FreeSurface( guy );
SDL_FreeSurface( guy2 );
SDL_FreeSurface( ground );
}
As I currently have it, the knight does not appear and I receive no errors (a consequence of the SDL screen being open?) Fail checks such as
if(!guy) {
cout << "IMG_LoadPNG_RW: %s\n" << IMG_GetError();
}
Have also yielded no results. my .h file is simply:
#include "SDL/SDL.h"
#include <iostream>
using namespace std;
int source_sdl( int argc, char* args[] );
And my main.cpp:
#include "SDL/SDL.h"
#include <iostream>
#include "source_sdl.h"
using namespace std;
int main( int argc, char* args[] ){
source_sdl( argc, args );
}
If you really want to stick with SDL in C++, I suggest you to use the SDL_image library and use a function like :
SDL_Surface * load_image(std::string const & filename)
{
SDL_Surface * img = NULL;
SDL_Surface * tmp = IMG_Load(filename.c_str());
if (tmp)
{
img = SDL_DisplayFormatAlpha(tmp);
SDL_FreeSurface(tmp);
}
return img;
}
An example of a more modern and safe approach would looke like this:
using surface_ptr = std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)>;
surface_ptr load_image (std::string const & filename)
{
surface_ptr img { nullptr, &SDL_FreeSurface };
surface_ptr tmp { IMG_Load(filename.c_str()), &SDL_FreeSurface };
if (tmp)
img.reset(SDL_DisplayFormatAlpha(tmp.get()));
return img;
}
Or better, use an existing C++ Binding like libSDL2pp (I have nothing to do with them).

Modifying pointer leads to SIGSEGV signal

this is my first experience,so don't be picky.
It's SIGSEGV problem, and it appears only in class linking.
The problem within "SDL_surface *ScreenSurface" pointer.
Here goes the code...
Screen header
class screen
{
public:
screen();
SDLclass_Window *MainWindow=NULL;
SDL_Surface *ScreenSurface=NULL; //this is the problem pointer to the struct that cause error
//Those pointer are't NULL, see below
virtual ~screen();
protected:
private:
const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 726;
bool init();
};
Screen code
screen::screen()
{
if(!init())
{
std::cout<<"ERROR at INIT";
SDL_Delay( 4000 );
}
else
{
bool quit=0;
SDL_Event e;
while (!quit)
{
SDL_UpdateWindowSurface(MainWindow);
//Looking for events
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
}
}
}
this->~screen();
}
bool screen::init() //Initialization
{
bool succses=1;
if (SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
std::cout<< "SDL could not initialize! SDL_Error:"<< SDL_GetError()<<std::endl;
succses=0;
return succses;
}
MainWindow= SDL_CreateWindow( "Arachy: WIP Version", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); //Setting parameters to SDL_window
if (MainWindow==NULL)
{
std::cout<<"can't create window"<<SDL_GetError()<<std::endl;
succses=0;
return succses;
}
else
{
//Get window surface
ScreenSurface = SDL_GetWindowSurface( MainWindow );// telling ScreenSurface that it our main screen surface
}
return succses;
}
screen::~screen()
{
SDL_Quit();
}
Activity header
(another class that uses SDL_Surface which defined above in class Screen)
class activity
{
public:
activity();
virtual ~activity();
protected:
private:
screen mainScreen;
void load();
};
Activity code (I'm trying to modify SDL_Surface with SDL_FillRect() after that i got SIGSEGV signal during debug
activity::activity()
{
SDL_FillRect(mainScreen.ScreenSurface,NULL,SDL_MapRGB(mainScreen.ScreenSurface->format,255,000000,255));
}
Please , help me to find out...
Thank you
The problem is twofold:
A) It's likely that the destructor of screen is called twice, causing SDL_DestroyWindow() and SDL_FreeSurface() to be called on invalid, non-NULL pointers.
If you absolutely, positively want to call your destructor twice, you should at least reset these pointers to NULL after destroying the objects they point to.
But in most cases you should simply, you know, not explicitly call the destructor...
B) As set now, activity's constructor body will never be called until the main event loop is over.

C++ SDL Reaction Time Game

Me and my friend needs to create a reaction time game.
Something like this.
Right now we just managed to show an image of the red button, but we need help how to make a hitbox, where if you click the red button, it becomes green.
Would someone could show us how?
We are using SDL, I guess that's important to mention.
Here is our code so far:
#include <SDL/SDL.h>
void Plot(SDL_Surface *sur, int x, int y, SDL_Surface *dest)
{
SDL_Rect rect = {x, y};
SDL_BlitSurface(sur, NULL, dest, &rect);
}
SDL_Surface *LoadImage(const char *filename)
{
SDL_Surface *sur = NULL;
sur = SDL_LoadBMP(filename);
if(sur == NULL)
{
printf("Img not found");
}
SDL_Surface *opsur = NULL;
if(sur != NULL)
{
opsur = SDL_DisplayFormat(sur);
SDL_SetColorKey(opsur, SDL_SRCCOLORKEY, 0xFFFFFF);
if(opsur != NULL)
SDL_FreeSurface(sur);
}
return opsur;
}
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
SDL_WM_SetCaption("Eksamensprojekt", NULL);
SDL_Event Event;
bool Running = true;
SDL_Surface *sur = LoadImage("Red.bmp");
while(Running)
{
while(SDL_PollEvent(&Event))
{
if(Event.type == SDL_QUIT)
Running = false;
}
SDL_FillRect(screen, &screen->clip_rect, 0x000000);
Plot(sur, 215, 140, screen);
SDL_Flip(screen);
}
}
You can use SDL_Rect as a hit box. You can use SDL's own event handling system for checking when mouse button is clicked and the position of it. Then you just need to check if the mouse position is within the SDL_Rect.
You can read more about SDL here.
So... a little help on the way. You have a main loop and you pull events.
if ( event.type == SDL_MOUSEBUTTONDOWN ){
//Get mouse coordinates
int x = event.motion.x;
int y = event.motion.y;
//If the mouse is over the button
if( checkSpriteCollision( x, y ) ){
// Yay, you hit the button
doThings();
}
else
{
// D'oh I missed
}
}
Add this to the while, that will at least get you started.
Like this?
while(Running)
{
while(SDL_PollEvent(&Event))
{
if(Event.type == SDL_QUIT)
Running = false;
if ( event.type == SDL_MOUSEBUTTONDOWN ){
//Get mouse coordinates
int x = event.motion.x;
int y = event.motion.y;
//If the mouse is over the button
if( checkSpriteCollision( x, y ) ){
// Yay, you hit the button
doThings();
}
else {
// D'oh I missed
}
}
}
SDL_FillRect(screen, &screen->clip_rect, 0x000000);
Plot(sur, 215, 140, screen);
SDL_Flip(screen);
}
}