Jump to content

  • Log In with Google      Sign In   
  • Create Account

SDL2 Not Loading/Showing Images?


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
17 replies to this topic

#1 Jamie_Edwards   Members   -  Reputation: 105

Like
0Likes
Like

Posted 05 June 2014 - 09:58 AM

Hi guys,

 

so I've decided to start trying to making a simple game using SDL2. I'd found a ( what seems to be good ) Tutorial by Lazy Foo... Problem is....

Either I'm a complete noob, or something just isn't working (note: I've not used C++ in about a year, and came over from Java).

 

This is what I have (also, this is my OOP approach to his tutorials, and I'll pick out the "problem" code):

 

Gui.h:

Spoiler

 

Gui.cpp:

Spoiler

 

Input.h:

Spoiler

 

Event.cpp:

Spoiler

 

In my Initialize.cpp I've got the initGui function just before my event loop.

 

Oh and my dev tree is as follows:

Spoiler

 

I don't understand what's going wrong, or I'm completely overlooking something, but that being said, when it's built and run, there are no error, except that one warning, and the surface goes black, so it's certainly doing something.

 

Any help would be much appreciated.

 

Thanks!

 

Jamie.


Edited by Jamie_Edwards, 05 June 2014 - 10:15 AM.


Sponsor:

#2 yellowsputnik   Members   -  Reputation: 661

Like
0Likes
Like

Posted 05 June 2014 - 11:10 AM

Do you call SDL_Init anywhere?



#3 Jamie_Edwards   Members   -  Reputation: 105

Like
0Likes
Like

Posted 05 June 2014 - 11:36 AM

Do you call SDL_Init anywhere?

 

Yes, in Initialize.cpp, I have an if else statement that says:

if ( SDL_Init ( SDL_INIT_VIDEO ) < 0 ) {
    printf ( "SDL could not initialize! SDL_ERROR: %s\n", SDL_GetError() );
    return -1;
}
else {
    // initiate the game here
}


#4 exOfde   Members   -  Reputation: 809

Like
0Likes
Like

Posted 05 June 2014 - 11:51 AM


class Gui {
private:
    ...
SDL_Window* window;
    SDL_Surface* screenSurface;
public:
    SDL_Surface* keyPressSurfaces[];

 

in your GUI class. you declare a pointer to an array, or a pointer to a pointer. but you never initilize it. so from where take you your surfaces?

of course you load it with GUI::loadMedia but even there you just access the first pointer to the array which you has never initilized yet and try to assign a new value to it

 

perhaps i am wrong but that what i see ...

 


bool Gui::loadMedia() {
    Input input;
 
   
bool success = true;
 
   
// Load default surface
    keyPressSurfaces[input.KEY_PRESS_SURFACE_DEFAULT] = loadSurface ( "assets/surfaces/press.jpg" );

Edited by exOfde, 05 June 2014 - 11:56 AM.


#5 Jamie_Edwards   Members   -  Reputation: 105

Like
0Likes
Like

Posted 05 June 2014 - 12:21 PM


in your GUI class. you declare a pointer to an array, or a pointer to a pointer. but you never initilize it. so from where take you your surfaces?
of course you load it with GUI::loadMedia but even there you just access the first pointer to the array which you has never initilized yet and try to assign a new value to it
 
perhaps i am wrong but that what i see ...

 

I do initialize them. If you look in the Gui.cpp spoiler, at the "Gui::Gui()" method, I initialize them there.



#6 dejaime   Crossbones+   -  Reputation: 4027

Like
0Likes
Like

Posted 05 June 2014 - 01:43 PM

keyPressSurface[Input::KEY_PRESS_SURFACE_TOTAL]; // There is a compiler warning here saying "statement has no effect"????
This means your code isn't doing anything. The above line is the same as the example below:
int myVar; // Creates the variable
myVar; // This isn't doing anything at all, you're referencing something but not doing anything to/with it.
In this code (from Gui.h):
public:
    SDL_Surface* keyPressSurfaces[];
This pointer isn't being initialized anywhere. You need to allocate some memory for it before using, adding the below to your Gui::Gui() may fix your problem
// Define the total number of surfaces desired somehow ...
#define TOTAL_SURFACES 20
// and allocate this number times the size of a surface.
keyPressSurface = (SDL_Surface**)malloc( TOTAL_SURFACES * Sizeof(SDL_Surface) );

//OR declare it like this if you know beforehand how many surfaces you want:
public:
    SDL_Surface* keyPressSurfaces[TOTAL_SURFACES];
//One or the other, the first uses dynamic memory and the second static.
But remember to clean up in your Gui::~Gui()
//CleanUp
if (keyPressSurface)
    free(keyPressSurface);
@edit
    enum Key_Press_Surfaces {
        KEY_PRESS_SURFACE_DEFAULT,
        ...
        KEY_PRESS_SURFACE_RIGHT,
        KEY_PRESS_SURFACE_TOTAL
    };
As I can see, you're relying on enum to result in integer values, so you can use them as indexes for the array. You shouldn't do that though, enum isn't guaranteed to result in an ordered set of integers.
 
You could give it explicit values though, as in here:
    enum Key_Press_Surfaces {
        KEY_PRESS_SURFACE_DEFAULT = 0,
        ... //incrementing by 1
        KEY_PRESS_SURFACE_RIGHT = 9,
        KEY_PRESS_SURFACE_TOTAL = 10
    };
Of course there is the possibility of creating a custom safe enum for your projects using templates, but that is a bit too complex and I personally don't think I could do it to exemplify here without spending some hours with it.

Edited by dejaime, 05 June 2014 - 04:30 PM.


#7 exOfde   Members   -  Reputation: 809

Like
0Likes
Like

Posted 05 June 2014 - 01:53 PM

what dejaime wrote was what i actually meant



#8 Jamie_Edwards   Members   -  Reputation: 105

Like
0Likes
Like

Posted 05 June 2014 - 02:52 PM

OK, the errors and warnings have gone! BUT...

 

When I tried to do the following:


keyPressSurface = (SDL_Surface**)malloc( TOTAL_SURFACES * Sizeof(SDL_Surface) );

it didn't like "SDL_Surface**" but when I replaced that with "SDL_Surface*" it compiled fine. so my code now looks like this:

 

Gui.h:

Spoiler

 

Gui.cpp:

Spoiler

 

As said, the above are no longer kicking out any errors or warnings. Thing is, when the game is built and run, I still get a black window and no reaction to ANY input given by the keyboard.

 

Could it be that I've got my images in the wrong place because at the moment I have my assets folder in the root of the project?

 

oh and also, I've done the edit you suggested:

Input.h:

Spoiler


#9 yellowsputnik   Members   -  Reputation: 661

Like
1Likes
Like

Posted 05 June 2014 - 03:15 PM

Why do you declare a Gui variable in Initialize::event()?

 

Is that the actual Gui object that you use in the rest of the program? My guess is that you're not working with the Gui object that you think you're using.



#10 yellowsputnik   Members   -  Reputation: 661

Like
0Likes
Like

Posted 05 June 2014 - 03:18 PM

Btw, you can also use Input::KEY_PRESS_SURFACE_UP instead of defining a local Input object and using input.KEY_PRESS_SURFACE_UP.



#11 Jamie_Edwards   Members   -  Reputation: 105

Like
0Likes
Like

Posted 05 June 2014 - 03:28 PM


Why do you declare a Gui variable in Initialize::event()?

 

I declared it because I thought it would be easier to write "gui.keyPressSurfaces[]" rather than "Gui::keyPressSurfaces" as I have at least 5 points in my code where I have to write that. And same goes for Input too in the Event class ( if that makes sense ).

 

But changing the event calls to "Gui::" instead just makes the compiler vomit the following error:

error: invalid use of non-static data member 'Gui::keyPressSurfaces'

changing the "Gui::" back to "gui." and then changing "input." to "Input::" causes no errors.

 

Edit:

 

I changed everything to read:

 

Event.cpp ( with changes to KEY_PRESS_SURFACE_... to match what I wanted it to look like ):

Gui::currentSurface = Gui::keyPressSurfaces[Input::KEY_PRESS_SURFACE_DEFAULT];

 

Gui.h:

SDL_Surface* keyPressSurfaces[];
SDL_Surface* currentScreen;
 
// To:
static SDL_Surface* keyPressSurfaces[];
static SDL_Surface* currentScreen;

 

the compiler then gives:

undefined reference to 'Gui::currentSurface'

Edited by Jamie_Edwards, 05 June 2014 - 03:40 PM.


#12 yellowsputnik   Members   -  Reputation: 661

Like
0Likes
Like

Posted 05 June 2014 - 03:33 PM

You'll have to use the same Gui variable that you called initGui() on. Otherwise you're not using the window and surfaces that you created during initialization.



#13 Jamie_Edwards   Members   -  Reputation: 105

Like
0Likes
Like

Posted 05 June 2014 - 04:09 PM

How do I go about doing that?



#14 dejaime   Crossbones+   -  Reputation: 4027

Like
1Likes
Like

Posted 05 June 2014 - 04:24 PM

You are using a non-initialized Gui object on Event.cpp.

Every time you call the event( SDL_Event* ) function, you create a new Gui and use it without loading anything.

In the end of the function call, it is deleted.

So, as Yellowsputnik pointed out, you're not using the Gui object you think you are.

 

You could pass on the Gui object to the event function as in here:

void Initialize::event ( const Gui &gui, SDL_Event* event )

or even use a global variable for it.

 

What exactly is the Initialize class responsible for?


Edited by dejaime, 05 June 2014 - 04:26 PM.


#15 Jamie_Edwards   Members   -  Reputation: 105

Like
0Likes
Like

Posted 05 June 2014 - 05:23 PM


You are using a non-initialized Gui object on Event.cpp.
Every time you call the event( SDL_Event* ) function, you create a new Gui and use it without loading anything.
In the end of the function call, it is deleted.
So, as Yellowsputnik pointed out, you're not using the Gui object you think you are.

 

Right ok.

 


You could pass on the Gui object to the event function as in here:
void Initialize::event ( const Gui &gui, SDL_Event* event )
or even use a global variable for it.

 

I tried doing as you said and I think I did it wrong as it threw errors at me. Could you show me how it should be implemented?

 


What exactly is the Initialize class responsible for?

 

It's responsible for pretty much everything, it initializes the event loop, gui, render and finally the cleanup when the app is closed.



#16 dejaime   Crossbones+   -  Reputation: 4027

Like
2Likes
Like

Posted 05 June 2014 - 05:48 PM

Could you show me how it should be implemented?

 
Take a look at the following code snippet:
#include <iostream>

class MyClass {
	std::string myName;
	
public:
	MyClass(std::string name): myName(name){
            //myName = name;
        }

	void PrintMyName() {
		std::cout << myName << std::endl;
	}
};

void CallPrintMyName (MyClass& correct_object) {
	correct_object.PrintMyName();
}

int main (){
        // Creates two objects with their names.
        MyClass Dejaime("Dejaime Neto"), JohnSmith("John Smith");

        //Call the function passing the first object
	CallPrintMyName (Dejaime);
        //Call again with the second one
	CallPrintMyName (JohnSmith);
}
You see, I pass on the object I want to use inside the CallPrintMyName function.
It outputs the following:
>> Dejaime Neto
>> John Smith

If you want some advice, it just seems you are biting a bit more than you can chew at the moment. I'd advise you to take a step back and study a bit more variable scopes, functions and object orientation in general, be it with Java or C++. Give it a week or so and then get back to this problem, it can only do good!

Edited by dejaime, 05 June 2014 - 06:25 PM.


#17 Jamie_Edwards   Members   -  Reputation: 105

Like
0Likes
Like

Posted 06 June 2014 - 09:08 AM

OK, I've decided to follow the tutorial a little closer to get the gist of how to make SDL work, but it's still not working properly. It builds and runs fine, but when I ask it to load a ".bmp" image, it just shows a white surface.

 

I've tried putting the image in with the "Initialize.cpp", "main.cpp", "Gui.cpp" and in the root directory, and even in the bin/debug folder and it still comes up with a just a white screen.



#18 yellowsputnik   Members   -  Reputation: 661

Like
0Likes
Like

Posted 06 June 2014 - 09:14 AM

Make sure to check return values of functions to see if they actually did what you think they should do.

 

When debugging, I always like to use breakpoints and step through the code to know exactly what's going on. You can try that here as well.






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