Jump to content

  • Log In with Google      Sign In   
  • Create Account


Help using multiple header and implementation files in SDL


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
15 replies to this topic

#1 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 31 October 2012 - 12:59 AM

Okay so im following Lazy Foo's sdl tutorial number 9:

http://lazyfoo.net/SDL_tutorials/lesson09/index.php

He writes his whole class and function within one .cpp file

I took a different path and made a header file and an implementation file for the button class

The problem im getting is when im making the function in the implementation files, they use global variables from the
main file, and it gives me a red squiggle line saying the variable is unidentified, but its not.

im attaching my project for all of you to see and help me

ignore the lesson09.cpp file. im just using that as a guide to write my own code.

Attached Files



Sponsor:

#2 Álvaro   Crossbones+   -  Reputation: 10828

Like
0Likes
Like

Posted 31 October 2012 - 03:45 AM

I didn't read your code, but your problem seems to have nothing to do with SDL. The way you use global variables in programs with multiple modules is this:
* Put a declaration for the variable in a header file, using the keyword "extern" (e.g. `extern int global_integer;').
* Include that header file whenever some part of the code needs access to the variable.
* Put a definition (with an optional initialization) in one of the .cpp files (e.g., `int global_integer = 5;').

You could also try to work around the issue by eliminating the need for global variables, which is almost always possible and a good idea.

#3 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 31 October 2012 - 03:41 PM

This is my main file

[source lang="cpp"]/The headers#include "SDL.h"#include "SDL_image.h"#include "SDL_ttf.h"#include <string>#include "Button.h"//the screen attributesconst int SCREEN_WIDTH = 640;const int SCREEN_HEIGHT = 480;const int SCREEN_BPP = 32;//the button states in the sprite sheetint const CLIP_MOUSEOVER = 0;int const CLIP_MOUSEOUT = 1;int const CLIP_MOUSEDOWN = 2;int const CLIP_MOUSEUP = 3;//the surfacesSDL_Surface* buttonSheet = NULL;SDL_Surface* screen = NULL;//the sdl event structureSDL_Event event;//the clip regions of the spriteSDL_Rect clips[4];//the load image functionSDL_Surface *load_image(std::string filename){ SDL_Surface *loadedImage = NULL; SDL_Surface *optimizedImage = NULL; //loading the image loadedImage = IMG_Load(filename.c_str()); if(loadedImage != NULL) { optimizedImage = SDL_DisplayFormat(loadedImage); SDL_FreeSurface(loadedImage); //if the surface was optimized if(optimizedImage != NULL) { //color key surface SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY,SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF ) ); } } return optimizedImage;}//the apply surface functionvoid apply_surface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = NULL){ SDL_Rect offset; offset.x = x; offset.y = y; SDL_BlitSurface(source,clip,destination, &offset);}//the function the sets the clips of the source surfacevoid set_clips(){ clips[CLIP_MOUSEOVER].x = 0; clips[CLIP_MOUSEOVER].y = 0; clips[CLIP_MOUSEOVER].w = 320; clips[CLIP_MOUSEOVER].h = 240; clips[CLIP_MOUSEOUT].x = 320; clips[CLIP_MOUSEOUT].y = 0; clips[CLIP_MOUSEOUT].w = 320; clips[CLIP_MOUSEOUT].h = 240; clips[CLIP_MOUSEDOWN].x = 0; clips[CLIP_MOUSEDOWN].y = 240; clips[CLIP_MOUSEDOWN].w = 320; clips[CLIP_MOUSEDOWN].h = 240; clips[CLIP_MOUSEUP].x = 320; clips[CLIP_MOUSEUP].y = 240; clips[CLIP_MOUSEUP].w = 320; clips[CLIP_MOUSEUP].h = 240;}[/source]

this is my button.cpp
[source lang="cpp"]#include "SDL.h"#include "SDL_image.h"#include "SDL_ttf.h"#include <string>#include "Button.h"Button::Button(int x, int y, int w, int h){ //set the buttons attributes box.x = x; box.y = y; box.w = w; box.h = h; //set the default sprite clip = &clips[ CLIP_MOUSEOUT ];}void Button::handle_events(){}[/source]

this is my button.h
[source lang="cpp"]#pragma once#include "SDL.h"#include "SDL_image.h"#include "SDL_ttf.h"class Button{public: //the constructor that initializes the variables Button(int x, int y, int w, int h); //handles events and sets the buttons sprite region void handle_events(); //shows the button on the screen void show();private: //the attributes of the button SDL_Rect box; // the part of the button sprite sheet that will be shown SDL_Rect *clip;};[/source]

#4 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 31 October 2012 - 03:44 PM

the problem occurs in button.cpp

clip = &clips[ CLIP_MOUSEOUT ];

it says &clips is undefined. What gives? its in the main file as a global. What to do?

#5 oler1s   Members   -  Reputation: 589

Like
0Likes
Like

Posted 31 October 2012 - 06:04 PM

In button.cpp, where do you declare clips?

> its in the main file as a global.

Yes. But the issue is in button.cpp, right? Where did you declare clips in button.cpp?

#6 Álvaro   Crossbones+   -  Reputation: 10828

Like
0Likes
Like

Posted 31 October 2012 - 06:14 PM

What part of my answer is not clear to you? Follow my advice and you'll be fine. If you have a global variable defined in main.cpp, you should probably have a main.hpp with the corresponding "extern" declaration, and button.cpp should include it.

#7 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 31 October 2012 - 06:23 PM

I thought if a variable is global, any part of the program could read it. After searching around apparently thats not the case.
How would I go about making this main.hpp file? Would it be okay if i just make externs in the button.h file?

#8 oler1s   Members   -  Reputation: 589

Like
0Likes
Like

Posted 31 October 2012 - 06:51 PM

> I thought if a variable is global, any part of the program could read it.

C++ source files are compiled independently. That's why you need to declare something that was not defined earlier within the source file, that you are compiling.

> How would I go about making this main.hpp file?

How do you make any file?

> Would it be okay if i just make externs in the button.h file?

So declarations for globals in the main.cpp file are declared in button.h file. Do you find this to be logical code organization?

#9 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 31 October 2012 - 06:57 PM

> I thought if a variable is global, any part of the program could read it.

C++ source files are compiled independently. That's why you need to declare something that was not defined earlier within the source file, that you are compiling.

> How would I go about making this main.hpp file?

How do you make any file?

> Would it be okay if i just make externs in the button.h file?

So declarations for globals in the main.cpp file are declared in button.h file. Do you find this to be logical code organization?


i know how to make a .cpp file and .h file. What would I choose in visual c++ for an .hpp file.
Also can you give me a code example(preferebly from my main.cpp) showing how its done?

#10 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 01 November 2012 - 04:51 PM

check out my code so far

main.h:
[source lang="cpp"]//The headers#include "SDL.h"#include "SDL_image.h"#include "SDL_ttf.h"#include <string>//global variables from main are inserted hereextern int const CLIP_MOUSEOVER;extern int const CLIP_MOUSEOUT; extern int const CLIP_MOUSEDOWN; extern int const CLIP_MOUSEUP; extern SDL_Event event;extern SDL_Rect clips[4];extern SDL_Surface* buttonSheet;extern SDL_Surface* screen;//global functions are inserted hereextern SDL_Surface *load_image(std::string filename);extern void apply_surface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = NULL);extern void set_clips();[/source]

main.cpp:
[source lang="cpp"]//The headers#include "SDL.h"#include "SDL_image.h"#include "SDL_ttf.h"#include <string>#include "Button.h"#include "main.h"//the screen attributesconst int SCREEN_WIDTH = 640;const int SCREEN_HEIGHT = 480;const int SCREEN_BPP = 32;//the button states in the sprite sheetint const CLIP_MOUSEOVER = 0;int const CLIP_MOUSEOUT = 1;int const CLIP_MOUSEDOWN = 2;int const CLIP_MOUSEUP = 3;//the surfacesSDL_Surface* buttonSheet = NULL;SDL_Surface* screen = NULL;//the sdl event structureSDL_Event event;//the clip regions of the spriteSDL_Rect clips[4];//the load image functionSDL_Surface *load_image(std::string filename){ SDL_Surface *loadedImage = NULL; SDL_Surface *optimizedImage = NULL; //loading the image loadedImage = IMG_Load(filename.c_str()); if(loadedImage != NULL) { optimizedImage = SDL_DisplayFormat(loadedImage); SDL_FreeSurface(loadedImage); //if the surface was optimized if(optimizedImage != NULL) { //color key surface SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY,SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF ) ); } } return optimizedImage;}//the apply surface functionvoid apply_surface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = NULL){ SDL_Rect offset; offset.x = x; offset.y = y; SDL_BlitSurface(source,clip,destination, &offset);}//the function the sets the clips of the source surfacevoid set_clips(){ clips[CLIP_MOUSEOVER].x = 0; clips[CLIP_MOUSEOVER].y = 0; clips[CLIP_MOUSEOVER].w = 320; clips[CLIP_MOUSEOVER].h = 240; clips[CLIP_MOUSEOUT].x = 320; clips[CLIP_MOUSEOUT].y = 0; clips[CLIP_MOUSEOUT].w = 320; clips[CLIP_MOUSEOUT].h = 240; clips[CLIP_MOUSEDOWN].x = 0; clips[CLIP_MOUSEDOWN].y = 240; clips[CLIP_MOUSEDOWN].w = 320; clips[CLIP_MOUSEDOWN].h = 240; clips[CLIP_MOUSEUP].x = 320; clips[CLIP_MOUSEUP].y = 240; clips[CLIP_MOUSEUP].w = 320; clips[CLIP_MOUSEUP].h = 240;}int main(int argc, char* args[] ){ //set the quit flag bool quit = false; //initialize everything SDL_Init(SDL_INIT_EVERYTHING); screen = SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE); SDL_WM_SetCaption("Button Test", NULL); //loading the stuff buttonSheet = load_image("button.png"); //clip the sprite sheet set_clips(); //make a button object Button myButton(170,120,320,240); //while the user has not quit out yet while(quit == false) { //check to see if there are any event polls to handle if(SDL_PollEvent(&event)) { //handle button events myButton.handle_events(); //if the user has quit out of the window if(event.type == SDL_QUIT) { //quit the program quit = true; } } //Fill the screen white SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) ); //show the button myButton.show(); //update the screen SDL_Flip(screen); } //start cleaning up; SDL_FreeSurface(buttonSheet); SDL_Quit(); return 0;}[/source]

button.h
[source lang="cpp"]#pragma once#include "SDL.h"#include "SDL_image.h"#include "SDL_ttf.h"#include "main.h"class Button{public: //the constructor that initializes the variables Button(int x, int y, int w, int h); //handles events and sets the buttons sprite region void handle_events(); //shows the button on the screen void show();private: //the attributes of the button SDL_Rect box; // the part of the button sprite sheet that will be shown SDL_Rect *clip;};[/source]

button.cpp
[source lang="cpp"]#include "SDL.h"#include "SDL_image.h"#include "SDL_ttf.h"#include <string>#include "Button.h"Button::Button(int x, int y, int w, int h){ //set the buttons attributes box.x = x; box.y = y; box.w = w; box.h = h; //set the default sprite clip = &clips[CLIP_MOUSEOUT];}void Button::handle_events(){ //The mouse offsets int x = 0, y = 0; //If the mouse moved if( event.type == SDL_MOUSEMOTION ) { //Get the mouse offsets x = event.motion.x; y = event.motion.y; //If the mouse is over the button if( ( x > box.x ) && ( x < box.x + box.w ) && ( y > box.y ) && ( y < box.y + box.h ) ) { //Set the button sprite clip = &clips[CLIP_MOUSEOVER]; } //If not else { //Set the button sprite clip = &clips[CLIP_MOUSEOUT]; } } //if the mouse button is pressed if(event.type == SDL_MOUSEBUTTONDOWN) { //if the left button was pressed if(event.button.button == SDL_BUTTON_LEFT) { //get the mouse offsets x = event.motion.x; y = event.motion.y; //if the mouse is over the button if((x > box.x)&&(x < box.x+box.w)&&(y > box.y)&&(y < box.y+box.h)) { //set the button sprite clip = &clip[CLIP_MOUSEDOWN]; } } } //if a mouse button was released if(event.type == SDL_MOUSEBUTTONUP) { //if the left button was released if(event.button.button == SDL_BUTTON_LEFT) { //get the mouse offsets x = event.motion.x; y = event.motion.y; //if the mouse is over the button if((x > box.x)&&(x < box.x + box.w)&&(y > box.y)&&(y < box.y+box.h)) { //set the button sprite clip = &clip[CLIP_MOUSEUP]; } } }}void Button::show(){ //show the button apply_surface(box.x,box.y,buttonSheet,screen, clip);} [/source]


my problem is that im getting this eror now:
1>------ Build started: Project: sdl_test, Configuration: Debug Win32 ------
1> main.cpp
1>c:\users\aasim\desktop\sdl_test\sdl_test\main.h(20): error C2572: 'apply_surface' : redefinition of default parameter : parameter 5
1> c:\users\aasim\desktop\sdl_test\sdl_test\main.h(20) : see declaration of 'apply_surface'
1>c:\users\aasim\desktop\sdl_test\sdl_test\main.cpp(56): error C2572: 'apply_surface' : redefinition of default parameter : parameter 5
1> c:\users\aasim\desktop\sdl_test\sdl_test\main.h(20) : see declaration of 'apply_surface'
1> Button.cpp
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

#11 SiCrane   Moderators   -  Reputation: 9158

Like
0Likes
Like

Posted 01 November 2012 - 04:53 PM

Why doesn't main.h have include guards or pragma once?

#12 rip-off   Moderators   -  Reputation: 6916

Like
0Likes
Like

Posted 01 November 2012 - 05:18 PM

Default parameters should be specified once, most sensibly in the declaration (otherwise other files don't know about the default). Specifying them multiple times could result in them not matching one another, with confusing results.

Functions are implicitly "extern", so you don't need to use that keyword in your function declarations. As an exception to the rules alvaro listed, const values are implicitly "static" or file local, so you can actually define them in a header file.

We can reduce the usage of global variables by using parameters. For example, instead of having a global event that must be populated before calling Button::handle_events() (a hidden dependency), we can change the function to void Button::handle_event(SDL_Event event).

Likewise, Button::show() could become Button::show(SDL_Surface *screen, SDL_Surface *buttonSheet), though we can also use SDL's function SDL_GetVideoSurface() and avoid keeping track of the "screen" ourselves.

Applying these techniques, we can remove all the global variables (note: global constants are generally fine).

#13 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 01 November 2012 - 05:55 PM

okay after including #pragma onnce i get one error now

1>------ Build started: Project: sdl_test, Configuration: Debug Win32 ------
1> main.cpp
1>c:\users\aasim\desktop\sdl_test\sdl_test\main.cpp(56): error C2572: 'apply_surface' : redefinition of default parameter : parameter 5
1> c:\users\aasim\desktop\sdl_test\sdl_test\main.h(21) : see declaration of 'apply_surface'
1> Generating Code...
1> Compiling...
1> Button.cpp
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

#14 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 01 November 2012 - 05:57 PM

Default parameters should be specified once, most sensibly in the declaration (otherwise other files don't know about the default). Specifying them multiple times could result in them not matching one another, with confusing results.

Functions are implicitly "extern", so you don't need to use that keyword in your function declarations. As an exception to the rules alvaro listed, const values are implicitly "static" or file local, so you can actually define them in a header file.

We can reduce the usage of global variables by using parameters. For example, instead of having a global event that must be populated before calling Button::handle_events() (a hidden dependency), we can change the function to void Button::handle_event(SDL_Event event).

Likewise, Button::show() could become Button::show(SDL_Surface *screen, SDL_Surface *buttonSheet), though we can also use SDL's function SDL_GetVideoSurface() and avoid keeping track of the "screen" ourselves.

Applying these techniques, we can remove all the global variables (note: global constants are generally fine).


not sure what your trying to say. Where should i define then? the main.h or main.cpp? I already defined appl_surface in main.cpp

#15 rip-off   Moderators   -  Reputation: 6916

Like
0Likes
Like

Posted 02 November 2012 - 03:32 AM

The default value for the "clip" parameter should be in the declaration in main.h:
void apply_surface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = NULL)

It should not appear in the definition in main.cpp:
void apply_surface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip)
{
    // ...
}


#16 ISDCaptain01   Members   -  Reputation: 1152

Like
0Likes
Like

Posted 02 November 2012 - 04:57 PM

Thanks a bunch! It worked! Now im gonna add this project as reference in my personal folder. Just incase i need to mess around with externs again.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS