I've been trying to improve my C++ skills and explore different ways of programming in it by using libraries like SDL.
This particular program is a Particle system and i've followed a guide on youtube that can be found here: http://www.youtube.com/watch?v=6Z5FI5180oo&list=UU6A2B9G_y-fzAXEu2hHPlMg.
The problem is that this guide is using SDL 1.2 and i've been trying to translate the depricated functions used in here to SDL 2.0.
Basically it works fine apart from some functions where i try to retrieve the width/height/pixels/pitch from the Windowsurface. SDL 1.2 uses the function GetVideoSurface() whereas i do believe SDL2.0 should use GetWindowSurface().
I'm having problems with accessing this function outside of my main function and i'm not sure what the problem really is.
For example in my particle::show() function i have this code:
void particle::show()
{
Uint8* pixels=(Uint8*)SDL_GetWindowSurface(window)->pixels;
Uint8* pixel=pixels+(int)y*SDL_GetWindowSurface(window)->pitch+(int)x;
*pixel=color;
}
Here i can't access these functions, i get no error message. Even if i try to use SDL_GetError(). The program crashes with a segmentation fault and no other errors (that i can see.)
This is my main function:
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow("My Particles",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480, SDL_WINDOW_OPENGL);
bool running = true;
const int FPS = 30;
Uint32 start;
srand(time(0));
particleEngine ps (100, SDL_GetWindowSurface(window)->w/2, SDL_GetWindowSurface(window)->h/2);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
while(running)
{
start = SDL_GetTicks();
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
running = false;
break;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
ps.refresh();
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_Quit();
return 0;
}
I've defined my SDL_Window *window outside of every function as a global variable.
I'm running SDL 2.0 and Mac OS X 10.10 Yosemite Beta 2
Any ideas how i should solve this?
SDL_Window *window is a local variable in the int main(int argc, char** argv) function. It will not be visible outside of main unless you either make it a global variable (not nice) or make it a member of a class which you create an instance of.
Alternatively you could pass the pointer to the SDL_Window to the functions which you need it in.
I noticed you said you have declared it as a global variable and in that case that is why it compiles but doesn't work. The variable used in the particle::show() will be using the global variable which will points to nothing (globals are always zero-initialized by default). As you declare SDL_Window again in main() that is what gets assigned the created window.
Related
I'm trying to set up an SDL project with Visual Studio 2019 using this article:
https://www.wikihow.com/Set-Up-SDL-with-Visual-Studio
but the compiler is throwing me the errors 'one or more multiply defined symbols found' and
'_main already defined in main.obj'.
main.obj is a file in the debug folder of my project but when I try deleting it or the entire debug folder, VS recreates it when I run the project.
I've read that c++ can't have more than one main function but I can't open the main.obj file and I don't really want to delete the one in main.cpp
Here's the code I'm running and thanks for your help!
#include "SDL.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow
("An SDL2 window", // window's title
10, 25, // coordinates on the screen, in pixels, of the window's upper left corner
640, 480, // window's length and height in pixels
SDL_WINDOW_OPENGL);
SDL_Delay(3000); // window lasts 3 seconds
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Glad to know it works now. Maybe you had a messy file structure with your previous SDL installation. Anyways, I think it might be interesting to show how the SDL dependency can be removed from your main.cpp file, to avoid such problems in the future.
First, let's consider the example in your question. The example is not very useful in practice, but I'll show a better version after.
The main idea is hiding everything that has to do with SDL from your main.cpp and headers.
1. Simple Example
// MySDL.h - NO SDL STUFF
class MySDL
{
public:
MySDL() = default; // or whatever you need
void runtest() const; // here we'll run the 3sec window
};
Now, we can put all our SDL stuff in the cpp file:
// MySDL.cpp
#include "MySDL.h"
#include "SDL.h" // HERE WE INCLUDE SDL
void MySDL::runtest()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("yee haw", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 400, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
}
No SDL included in main.cpp, we just include our SDL interface MySDL.h.
// Now you can use your SDL interface like this
int main(int, char* [])
{
MySDL sdl;
sdl.runtest();
return 0;
}
2. Better Version
However, you would typically want something more sofisticated than a window which disappears in 3 seconds. Therefore, you might want to store class members which depends on SDL. But then, you would have to #include "SDL.h" in your MySDL.h header file, which would give you the same problems as described in your question and comments. To remove this dependency, we can use the pimpl idiom.
The header file now includes a pointer to our SDL implementation. This SDL implementation will be defined in the cpp file in order to remove the SDL dependency.
// MySDL.h
class MySDL
{
public:
MySDL() = default; // or whatever you need
~MySDL();
void doSmthWithYourWindow(/*args*/);
private:
// pointer to our SDLImplementation (defined in cpp file)
class SDLImplementation;
std::unique_ptr<SDLImplementation> _sdl;
};
In our cpp file, we define the SDLImplementation, and MySDL has access to that implementation through the _sdl pointer.
// MySDL.cpp
#include "MySDL.h"
#include "SDL.h"
// here we can store class members which depend on SDL
struct MySDL::SDLImplementation
{
SDLImplementation()
{
SDL_Init(SDL_INIT_EVERYTHING);
_window = SDL_CreateWindow("yee haw", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 400, SDL_WINDOW_SHOWN);
_renderer = SDL_CreateRenderer(_window, -1, 0);
SDL_SetRenderDrawColor(_renderer, 0, 255, 0, 255);
SDL_RenderClear(_renderer);
SDL_RenderPresent(_renderer);
}
// functionality of your SDL implementation
void turnWindowUpsideDown() { /* _window->turnUpsideDown(); */ }
// members depending on SDL
SDL_Window* _window;
SDL_Renderer* _renderer;
};
MySDL::~MySDL() = default;
void MySDL::doSmthWithYourWindow(/*args*/)
{
// here we have access to our SDL implementation
_sdl->turnWindowUpsideDown();
}
Just like before, we only include our MySDL.h interface in the main.cpp file.
int main(int, char* [])
{
MySDL sdl;
sdl.doSmthWithYourWindow();
return 0;
}
So I ended up deleting SDL and completely restarting with a different tutorial linked here:
https://www.youtube.com/watch?v=QQzAHcojEKg
Not really sure what the difference was but it worked. Anyways, thanks for your help and I'll put the new code here.
#include "SDL.h"
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("yee haw", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 400, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
return 0;
}
I'm doing Lazy Foo's tutorial on SDL (I'm using SDL2-2.0.9), and at the texture rendering part I encountered the following problem: the program compiles and runs as expected, no issue here, but when I close the window, the console doesn't close and the process continues running, so I have to close the console separately.
When I tried to debug it, I found out that the program indeed leaves the main cycle and reaches the "return 0" line in the main function successfully, but then it just hangs like that until I close the console.
The issue is only present when I use the SDL renderer with any option other than SDL_RENDERER_SOFTWARE. If I use SDL_RENDERER_SOFTWARE - the program closes as expected. With other options it stays at "return 0" running other threads (crypt32.dll, ntdll.dll and nvd3dum, in this order in the thread view, meaning that the process is stuck in crypt32).
I'm aware that my main function is not the "real main" as it has been hijacked by SDL, so exit(0) works fine as an ad-hoc solution. But I want to know, why exactly does that happen and is there any other way to fix this, so that I don't have to use exit(0) ?
Here is an example (simplified) code, which demonstrates this issue for me:
#include "SDL.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
SDL_Window *win = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *bitmapTex = NULL;
SDL_Surface *bitmapSurface = NULL;
int width = 640, height = 480;
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("Could not initialize SDL");
return 1;
}
win = SDL_CreateWindow("Hello World", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, 0);
renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
bitmapSurface = SDL_LoadBMP("res/x.bmp");
bitmapTex = SDL_CreateTextureFromSurface(renderer, bitmapSurface);
SDL_FreeSurface(bitmapSurface);
bool quit = false;
while (!quit) {
SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) {
quit = true;
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, bitmapTex, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(bitmapTex);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
printf("REACHED RETURN 0");
return 0;
}
Works as intended, but after closing the window I see "REACHED RETURN 0" printed in console and that's it, the console stays there. The code can be simplified further, the issue will be present as long as there is an instance of SDL_Renderer created.
UPD: The callstack during the hanging:
> ntdll.dll!_NtWaitForMultipleObjects#20()
KernelBase.dll!_WaitForMultipleObjectsEx#20()
crypt32.dll!ILS_WaitForThreadProc()
kernel32.dll!#BaseThreadInitThunk#12()
ntdll.dll!__RtlUserThreadStart()
ntdll.dll!__RtlUserThreadStart#8()
UPD2: The problem is not with the loop at all, I created the simplest application where I just create a window and a renderer and then return 0, it still gives me a hanging console. Like this:
#include <SDL.h>
int main(int argc, char* args[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) return 1;
SDL_Window* window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
return 0;
}
Same thing when I destroy them properly. The problem is in the renderer.
UPD3: Here is the Parallel Stack window during the "hanging". There is no "main" thread since I close it successfully, these are the threads which stop the program from closing properly. Other than that, it doesn't give me any understanding of the problem.
This test program should create a blank window that stays open until you x-it-out. I copied it from SDL's documentation to make sure it is correct. It can be found here.
// Example program:
// Using SDL2 to create an application window
#include "SDL.h"
#include <stdio.h>
int main(int argc, char* argv[]) {
SDL_Window *window; // Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"An SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
//game loop, quitGame to quit
bool quitGame = false;
//var for checking events
SDL_Event event;
while(!quitGame) {
//Update particles
//Draw particles
//Check for events
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT)
quitGame = true;
}
}
// Close and destroy the window
SDL_DestroyWindow(window);
// Clean up
SDL_Quit();
return 0;
}
It doesn't create a window and terminates immediately, but gives no errors.
I'm using Eclipse, mingw32, and the latest stable release of SDL2. SDL2's libraries and headers are within a file in my C drive. I am using a 64 bit system. I include the entire folder of SDL2's header files. The only library folder I have linked is the one within the 64 bit part of the SDL2 folder. The libraries I have linked are the ones suggested by HolyBlackCat, (in this order) mingw32, SDL2main, and SDL2. Any help is greatly appreciated. Thanks!
I have been working on a simple game engine (i know, i know, i've heard "Write games not engines" before, this is just to understand the concepts). I have been using SDL2, since it works well with OpenGL. However for some reason, the program closes once the initializing function is completed.
Screen.cpp:
Screen::Screen(int width, int height, const std::string& title)
{
//Initialize SDL
SDL_Init(SDL_INIT_EVERYTHING);
//Setting OpenGL Attributes
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//Create the Window
m_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
l.writeToDebugLog("Created SDL_Window!");
//Create OpenGL context from within SDL
m_glContext = SDL_GL_CreateContext(m_window);
l.writeToDebugLog("Created SDL GL Context!");
//Initializing GLEW
GLenum status = glewInit();
l.writeToDebugLog( "Initializing GLEW");
if (status != GLEW_OK)
{
l.writeToGLEWELog(" Glew Failed to Initialize!");
}
//setting the windowSurface to the m_window's surface
windowSurface = SDL_GetWindowSurface(m_window);
m_isClosed = false;
}
This is where i create the screen object and initialize all of the SDL functions and OpenGL functions
Engine.cpp:
void Engine::initialize(){
//Console Detecting platform
c.initialize();
//Printing Operating System to screen
std::cout << "Loaded on : " << platformToString(c.os) << " OS " << std::endl;
//Constructing a new Screen to be referenced too
graphics::Screen temp(800,600,"ClimLib 0.0.05");
//setting all the variables
m_window = &temp;
m_EntityManager = nullptr;
m_isRunning = temp.isClosed();
m_renderer = SDL_GetRenderer(m_window->getWindow());
}
void Engine::update(){
do{
//Check whether entities have been created and placed in the manager
if (m_EntityManager != nullptr){
for each(core::Entity *e in *m_EntityManager){
for each(core::Component *c in e->getComponentList()){
c->Update();
}
}
}
//Update Logic Here
m_window->Update();
if (m_window->isClosed()){
m_isRunning = false;
return;
}
}while (isRunning());
}
This initialize function is the last function my window executes before it deletes itself, maybe i need to call it from the main function of the program?
main.cpp:
int main(int argc, char *argv[]){
clim::system::Engine game;
game.initialize();
while (game.isRunning()){
game.update();
}
return 0;
}
That is how i have my main set up at the moment.
EDIT: I believe the reason was because i am creating a variable and storing it as a reference, when the function returns the temp variable is thrown away?
You are creating your screen as a temporary value and then assigning the address of that value to a pointer whose lifetime actually exceeds the lifetime of the value it's pointing to that is very likely a stack value as well. Short of your immediate issue with the window dying, this will cause one or both of the following when used later:
Crashes (illegal memory access)
Undefined behavior (from reading random values on the stack that are sitting at this address later in execution)
While perhaps not applicable now, this is a real good way to cause headaches for yourself in pretty much everything.
You should just assign like this:
m_window = new graphics::Screen(800,600,"ClimLib 0.0.05");
The way you initialized it means that it will destroy itself when the function exits as it was declared and initialized in the function.
Using new will guarantee it exists until you delete it because it will sit somewhere on the heap unmolested unless your code does.
Just make sure you call delete m_window in the destructor of the class containing it to properly clean up the window when you're done using it when using new to create it. You can also declare m_window to be a graphics::Screen instead of a graphics::Screen* and just assign m_window like:
m_window = graphics::Screen(800,600,"ClimLib 0.0.05");
This way you don't have to worry about deleting it yourself later as it will delete itself when the containing class is deleted.
I've recently decided to dive into writing a C++ game using SDL as one of my libraries. During the course of my program writing and learning about SDL, I stumbled across a peculiar bug in my program, and decided to replicate it in an SSCCE to make sure that I wasn't crazy.
The problem appears to be that when I pass SDL_RENDERER_PRESENTVSYNC as a flag to SDL_CreateRenderer, I get inconsistent rendering. To compare, I ran the program 50 times with, and 50 times without the flag, and made that the only change to my program in each case. Without the flag, the display worked 100% of the time. With the flag on, it only rendered successfully 13 out of the 50 times.
Here's the program:
#include <SDL2/SDL.h>
#include <iostream>
int main(int argc, char** argv)
{
if(SDL_Init(SDL_INIT_VIDEO) != 0)
{
std::cerr << "Unable to initialize SDL: " << SDL_GetError() << std::endl;
return -1;
}
SDL_Window* win = SDL_CreateWindow("Testing",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(win, -1,
SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
for(int x = 0; x < 640; x+=32)
{
for(int y = 0; y < 480; y+=32)
{
SDL_Rect rect = {x+1, y+1, 31, 31};
SDL_RenderFillRect(renderer, &rect);
}
}
SDL_RenderPresent(renderer);
SDL_Delay(500);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
If it makes a difference, I'm compiling and testing the program on Ubuntu 15.04, GCC/G++ 4.9.2, Compiled and linked against SDL 2.0.2.
Being so new to SDL, and still relatively new to both C++ and C (I come from a Java background), I think it's very likely that I've made a simple error that I'm not catching, but I can't think of what I might have done.
For those seeing this question in the future, the problem appears to have resolved itself a little over a year later, as I can no longer replicate my own SSCCE. It may be a change of environment, as I am not using the same system and am now using an Nvidia Graphics Card. The problem, though I can no longer verify this, was almost certainly in the environment or the hardware. That same laptop ended up failing (motherboard issues) a mere month or two later, so take from that what you will. Consider checking your hardware health and attempting a completely clean environment if you are experiencing this same issue.