I'm getting the same log every time I run my program.
There is a snippet from the main.cpp, where every variable is in local scope:
EDIT: you find at the bottom.
I made these functions for start the game, run the menu loop, and close the graphics, and give false value for gameNoError if something goes wrong. But the last function gives me the following log message:
"No present window or/and renderer to close! SDL possibly not started, closed already or wrong pointers used!"
(Note, that I wrote all log messages myself, because I want to use logging to.)
So, this means that I loose somewhere the value of pointers, but I can't find out why?
There is my close function too:
bool closeGraphics(FILE* logFile, SDL_Window* gameWindow, SDL_Renderer* gameRenderer)
{
bool success = false;
if (gameWindow == NULL or gameRenderer == NULL)
{
doLogging(logFile, "No present window or/and renderer to close! SDL possibly not started, closed already or wrong pointers used!");
success = false;
}
else
{
SDL_DestroyRenderer(gameRenderer);
gameRenderer = NULL;
SDL_DestroyWindow(gameWindow);
gameWindow = NULL;
doLogging(logFile, "Renderer and window destroyed successfully!");
}
TTF_Quit();
IMG_Quit();
SDL_Quit();
return success;
}
I only use the pointers for rendering in menu loop (if you need I will paste that too!) and the pointers are used in scope.
So what is the problem?
EDIT:
I found something: the menu loop looses the pointers too! But SDL starts and I made this not first. So I really don't know what is the problem.
Files from my project:
main.cpp:
#include <stdio.h>
#include <string>
#include <SDL.h>
#include "initialization/utility.hpp"
#include "initialization/init_closeGraphics.hpp"
#include "menuLoop.hpp"
int main(int argc, char* argv[])
{
bool gameNoError = true;
SDL_Renderer* gameRenderer = NULL;
SDL_Window* gameWindow = NULL;
FILE* logFile = fopen("errorLog.txt", "w");
doLogging(logFile, "Game started successfully!");
gameNoError = initGraphics(logFile, gameWindow, gameRenderer, "This is a title!", 800, 600);
if (gameNoError) gameNoError = doMenuLoop(logFile, gameWindow, gameRenderer, 800, 600);
if (gameNoError)
{
gameNoError = closeGraphics(logFile, gameWindow, gameRenderer);
}
else
{
closeGraphics(logFile, gameWindow, gameRenderer);
}
if (!gameNoError)
{
doLogging(logFile, "Game stopped with error/exception/problem!");
}
else
{
doLogging(logFile, "Game stopped successfully!");
}
return 0;
}
utility.hpp contains only the logging function
init_close.cpp: (it has it's header)
#include "init_closeGraphics.hpp"
bool initGraphics(FILE* logFile,
SDL_Window* gameWindow,
SDL_Renderer* gameRenderer,
const char* gameTitle,
int gameWindowWidth,
int gameWindowHeight)
{
bool success = true;
if (gameWindowWidth <= 0 or gameWindowHeight <= 0)
{
doLogging(logFile, "Get less then or equal with 0 window dimensions at SDL initialization!");
success = false;
}
else
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
doLogging(logFile, "Failed to initialize SDL!");
doLogging(logFile, SDL_GetError());
success = false;
}
else
{
gameWindow = SDL_CreateWindow(gameTitle,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
gameWindowWidth,
gameWindowHeight,
SDL_WINDOW_SHOWN);
if (gameWindow == NULL)
{
doLogging(logFile, "Failed to create window!");
doLogging(logFile, SDL_GetError());
success = false;
}
else
{
gameRenderer = SDL_CreateRenderer(gameWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (gameRenderer == NULL)
{
doLogging(logFile, "Failed to create renderer!");
doLogging(logFile, SDL_GetError());
success = false;
}
else
{
SDL_SetRenderDrawColor(gameRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
int IMG_FLAG = IMG_INIT_PNG;
if (!(IMG_Init(IMG_FLAG) & IMG_FLAG))
{
doLogging(logFile, "Failed to initialize SDL_image!");
doLogging(logFile, IMG_GetError());
success = false;
}
if (TTF_Init() == -1)
{
doLogging(logFile, "Failed to initialize SDL_ttf!");
doLogging(logFile, TTF_GetError());
success = false;
}
}
}
}
}
return success;
}
bool closeGraphics(FILE* logFile, SDL_Window* gameWindow, SDL_Renderer* gameRenderer)
{
bool success = false;
if (gameWindow == NULL or gameRenderer == NULL)
{
doLogging(logFile, "No present window or/and renderer to close! SDL possibly not started, closed already or wrong pointers used!");
success = false;
}
else
{
SDL_DestroyRenderer(gameRenderer);
gameRenderer = NULL;
SDL_DestroyWindow(gameWindow);
gameWindow = NULL;
doLogging(logFile, "Renderer and window destroyed successfully!");
}
TTF_Quit();
IMG_Quit();
SDL_Quit();
return success;
}
You are passing your pointer variables to initGraphics by value, so your call site will not see any changes to them.
If you want the variables in main to be updated when you call initGraphics, take them by reference:
bool initGraphics(FILE* logFile,
SDL_Window*& gameWindow,
// ^
SDL_Renderer*& gameRenderer,
// ^
const char* gameTitle,
int gameWindowWidth,
int gameWindowHeight)
Related
I'm trying to put an imagine on surface.
So it's showed a black screen when I'm load BMP and display bmp
here's my code:
#define SDL_MAIN_HANDLED
#include <iostream>
#include "SDL/include/SDL2/SDL.h"
const int screenWidth=640;
const int screenHeight=480;
SDL_Window* window=NULL;
SDL_Surface* screenSurface=NULL;
SDL_Surface* gHelloWorld = NULL;
bool init(){
bool good = true;
if(SDL_Init(SDL_INIT_VIDEO)<0){
std::cout<<"ERROR: Failed to initialize SDL " << SDL_GetError()<<"\n";
good = false;
}else{
//Create Window
window =SDL_CreateWindow("SDL Tutorial",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,screenWidth,screenHeight,SDL_WINDOW_SHOWN);
if (window ==NULL){
std::cout<<"ERROR: Failed to create "<<SDL_GetError() <<"\n";
good = false;
}else{
//Get window surface
screenSurface = SDL_GetWindowSurface( window );
}
}
return good;
}
void close(){
SDL_FreeSurface(gHelloWorld);
gHelloWorld = NULL;
SDL_DestroyWindow(window);
window=NULL;
SDL_Quit();
}
bool loadMedia(){
bool ok = true;
gHelloWorld=SDL_LoadBMP("hello_world.bmp");
if(gHelloWorld==NULL){
std::cout<<"ERROR: Failed to load "<<SDL_GetError()<<"\n";
ok = false;
}else{
std::cout<<"Loaded successfully "<<'\n';
}
return ok;
}
int main(){
SDL_Window* window=NULL;
SDL_Surface* screenSurface=NULL;
bool Init = init();
if(Init){
bool loadMed = loadMedia();
if(loadMed){
SDL_Rect area ={30,30,250,250};
SDL_BlitSurface(gHelloWorld,&area,screenSurface,&area);
SDL_UpdateWindowSurface(window); //
SDL_Event e; bool quit = false; while( quit == false ){ while( SDL_PollEvent( &e ) ){ if( e.type == SDL_QUIT ) quit = true; } }
}
}
close();
return 0;
}
And I'm using Cmake to link lib (dynamic linking)
I tried to write SDL_Rect , and its not work ;/
Your problem is that you are nulling your sufaces in the main function.
Here is a version of your code without that mistake:
#include <iostream>
#include "SDL/include/SDL2/SDL.h"
const int screenWidth=640;
const int screenHeight=480;
SDL_Window* window=NULL;
SDL_Surface* screenSurface=NULL;
SDL_Surface* gHelloWorld = NULL;
bool init(){
bool good = true;
if(SDL_Init(SDL_INIT_VIDEO)<0){
std::cout<<"ERROR: Failed to initialize SDL " << SDL_GetError()<<"\n";
good = false;
}else{
//Create Window
window =SDL_CreateWindow("SDL Tutorial",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,screenWidth,screenHeight,SDL_WINDOW_SHOWN);
if (window ==NULL){
std::cout<<"ERROR: Failed to create "<<SDL_GetError() <<"\n";
good = false;
}else{
//Get window surface
screenSurface = SDL_GetWindowSurface( window );
}
}
return good;
}
void close(){
SDL_FreeSurface(gHelloWorld);
gHelloWorld = NULL;
SDL_DestroyWindow(window);
window=NULL;
SDL_Quit();
}
bool loadMedia(){
bool ok = true;
gHelloWorld=SDL_LoadBMP("/tmp/image.bmp");
if(gHelloWorld==NULL){
std::cout<<"ERROR: Failed to load "<<SDL_GetError()<<"\n";
ok = false;
}else{
std::cout<<"Loaded successfully "<<'\n';
}
return ok;
}
int main(){
// your error was nulling your surfaces.
// SDL_Window* window=NULL;
// SDL_Surface* screenSurface=NULL;
bool Init = init();
if(Init){
bool loadMed = loadMedia();
if(loadMed){
SDL_Rect area ={30,30,250,250};
SDL_BlitSurface(gHelloWorld,&area,screenSurface,&area);
SDL_UpdateWindowSurface(window); //
SDL_Event e; bool quit = false; while( quit == false ){ while( SDL_PollEvent( &e ) ){ if( e.type == SDL_QUIT ) quit = true; } }
}
}
close();
return 0;
}
Also, I recommend that you make your surface updates inside your while loop because somethimes SDL don't render the first surface and you obta a false window.
Here is a good resource for learning SDL: https://lazyfoo.net/tutorials/SDL/
and on my GitHub I have a tool to give you an SDL example: https://github.com/Monsterduty/mktest.
Here's my header file:
#ifndef SOMETHING_H
#define SOMETHING_H
#include <SDL.h>
#include <stdio.h>
#include <string>
#pragma once
class Something {
public:
//Screen dimension constants
int SCREEN_WIDTHS;
int SCREEN_HEIGHTS;
//Starts up SDL and creates window
bool inits();
//Loads media
bool loadMediases();
//Frees media and shuts down SDL
void closes();
Something(int height);
int mains();
//Loads individual image
SDL_Surface* loadSurfaces(std::string path);
//The window we'll be rendering to
SDL_Window* gWindows;
//The surface contained by the window
SDL_Surface* gScreenSurfaces;
//The images that correspond to a keypress
SDL_Surface* gKeyPressSurfaceses[5];
//Current displayed image
SDL_Surface* gCurrentSurfaces;
};
#endif
Here's my cpp file:
//Using SDL, standard IO, and strings
#include <SDL.h>
#include <stdio.h>
#include <string>
#include "Something.h"
class Something {
public:
//Screen dimension constants
int SCREEN_WIDTHS = 640;
int SCREEN_HEIGHTS = 480;
//Key press surfaces constants
enum KeyPressSurfaceses
{
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
KEY_PRESS_SURFACE_TOTAL
};
//The window we'll be rendering to
SDL_Window* gWindows = NULL;
//The surface contained by the window
SDL_Surface* gScreenSurfaces = NULL;
//The images that correspond to a keypress
SDL_Surface* gKeyPressSurfaceses[KEY_PRESS_SURFACE_TOTAL];
//Current displayed image
SDL_Surface* gCurrentSurfaces = NULL;
Something(int height) {
SCREEN_HEIGHTS = height;
}
bool inits()
{
//Initialization flag
bool success = true;
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Create window
gWindows = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTHS, SCREEN_HEIGHTS, SDL_WINDOW_SHOWN);
if (gWindows == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Get window surface
gScreenSurfaces = SDL_GetWindowSurface(gWindows);
}
}
return success;
}
bool loadMedias()
{
//Loading success flag
bool success = true;
//Load default surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT] = loadSurfaces("resources/images/press.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT] == NULL)
{
printf("Failed to load default image!\n");
success = false;
}
//Load up surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP] = loadSurfaces("resources/images/up.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP] == NULL)
{
printf("Failed to load up image!\n");
success = false;
}
//Load down surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN] = loadSurfaces("resources/images/down.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN] == NULL)
{
printf("Failed to load down image!\n");
success = false;
}
//Load left surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT] = loadSurfaces("resources/images/left.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT] == NULL)
{
printf("Failed to load left image!\n");
success = false;
}
//Load right surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT] = loadSurfaces("resources/images/right.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT] == NULL)
{
printf("Failed to load right image!\n");
success = false;
}
return success;
}
void closes()
{
//Deallocate surfaces
for (int i = 0; i < KEY_PRESS_SURFACE_TOTAL; ++i)
{
SDL_FreeSurface(gKeyPressSurfaceses[i]);
gKeyPressSurfaceses[i] = NULL;
}
//Destroy window
SDL_DestroyWindow(gWindows);
gWindows = NULL;
//Quit SDL subsystems
SDL_Quit();
}
SDL_Surface* loadSurfaces(std::string path)
{
//Load image at specified path
SDL_Surface* loadedSurface = SDL_LoadBMP(path.c_str());
if (loadedSurface == NULL)
{
printf("Unable to load image %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
}
return loadedSurface;
}
int mains(int argc, char* args[])
{
//Start up SDL and create window
if (!inits())
{
printf("Failed to initialize!\n");
}
else
{
//Load media
if (!loadMedias())
{
printf("Failed to load media!\n");
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//Set default current surface
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT];
//While application is running
while (!quit)
{
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
//User presses a key
else if (e.type == SDL_KEYDOWN)
{
//Select surfaces based on key press
switch (e.key.keysym.sym)
{
case SDLK_UP:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP];
break;
case SDLK_DOWN:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN];
break;
case SDLK_LEFT:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT];
break;
case SDLK_RIGHT:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT];
break;
default:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT];
break;
}
}
}
//Apply the current image
SDL_BlitSurface(gCurrentSurfaces, NULL, gScreenSurfaces, NULL);
//Update the surface
SDL_UpdateWindowSurface(gWindows);
}
}
}
//Free resources and close SDL
closes();
return 0;
}
};
Why does it keep throwing a "Class" type redefinition error? How can I fix this? I've tried everything but I just run into more problems. I saw some posts relating the issue to defining the class twice, but getting rid of the class definition in the cpp and using classname::functionname just causes more errors.
I know this is a stupid problem to have, I'm a beginning C++ programmer using tutorials and Visual Studio.
In your .cpp file you have completely redeclared class Something. That's not how you do it if you want to just put the implementations of functions in the .cpp file.
The syntax in there should be like:
bool Something::inits()
{
// implementation ...
}
bool Something::loadMedias()
{
// implementation ...
}
And so on
In the following code:
#include <iostream>
#include "SDL.h"
using namespace std;
int main(int argc, char** argv)
{
SDL_Surface* screenSurface = nullptr;
SDL_Surface* image = nullptr;
SDL_Window* window = nullptr;
const Uint8* keystate;
SDL_Rect offset;
offset.x = 100;
offset.y = 200;
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
cout << "Window initialization error: " << SDL_GetError();
}
else
{
window = SDL_CreateWindow("game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
bool isRunning = true;
SDL_Event ev;
//game loop
while (isRunning)
{
while (SDL_PollEvent(&ev) != 0)
{
if (ev.type == SDL_QUIT)
isRunning = false;
}
keystate = SDL_GetKeyboardState(NULL);
if (keystate[SDL_SCANCODE_W])
{
offset.y -= 1;
}
else if (keystate[SDL_SCANCODE_A])
{
offset.x -= 1;
}
else if (keystate[SDL_SCANCODE_S])
{
offset.y += 1;
}
else if (keystate[SDL_SCANCODE_D])
{
offset.x += 1;
}
screenSurface = SDL_GetWindowSurface(window);
image = SDL_LoadBMP("world.bmp");
SDL_BlitSurface(image, NULL, screenSurface, &offset);
SDL_UpdateWindowSurface(window);
cout << SDL_GetError() << endl;
}
}
SDL_FreeSurface(image);
SDL_DestroyWindow(window);
image = nullptr;
window = nullptr;
SDL_Quit();
return 0;
}
I get an error, saying: "SDL_UpperBlit: passed a NULL surface error." But the error did not occur until I went from using a switch statement in the while loop for SDL_PollEvent, to just using if statements using SDL_SCANCODE_ in the isRunning while loop. So the error does not occur instantly, but after a short while, like 10 seconds or so. So I am able to move around the world.bmp with WASD for a short while, then I get the error "SDL_UpperBlit: passed a NULL surface error.".
What's the solution for this?
image = SDL_LoadBMP("world.bmp");
This loads world.bmp from the disk, creates a brand new surface and stores the image inside. You never destroy this surface, and you don't check for errors either.
As you're running this once per frame, SDL quickly runs out of resources, SDL_LoadBMP returns NULL to signal it, and you pass that NULL to SDL_BlitSurface.
Only load your resources once, and take care of destroying them at the right time. C++ has smart pointers and RAII to do that for you.
I have this simple code for SDL.
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
using namespace std;
int main(int argc, char * argv[]){
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
return 1;
}
SDL_Window * win = SDL_CreateWindow("Window", 0, 0, 1920, 1080, SDL_WINDOW_FULLSCREEN_DESKTOP);
if(win == nullptr){
return 1;
}
SDL_Quit();
return 0;
}
None of this shows a window, I have error checked everything. It was working previously, but now it just opens and closes. I'm running on Xcode, if that helps.
Like the others state, your program terminates immediately so the window should "flash" momentarily. You can have the window appear for a few seconds by using SDL_Delay:
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == nullptr){
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Delay(2000);
SDL_DestroyWindow(win);
SDL_Quit();
And remember to call SDL_DestroyWindow.
A while(true) {} loop will just cause your program to freeze. You probably want something like the following so that it listens for events, and you can close the window at your leisure.
SDL_Event e;
bool quit = false;
while (!quit){
while (SDL_PollEvent(&e)){
if (e.type == SDL_QUIT){
quit = true;
}
if (e.type == SDL_KEYDOWN){
quit = true;
}
if (e.type == SDL_MOUSEBUTTONDOWN){
quit = true;
}
}
}
I'm new to SDL, and I have a function bool init(). I've been learning SDL 2.0 from lazyfoot.net for a few days without a problem. I've been essentially copying their code, and today I tried to do my own. (EDIT: I know someone said I have an outdated header file. This is not the case, because I have been able to use SDL_WINDOWPOS_UNDEFINED and other 2.0 features ever since I installed the library) For whatever reason, this won't work.
I'm using Windows 7 Starter, with Code::Blocks (MinGW as my compiler)
When I (try to) build and run, there is a red flag next to line 17, which is this.
bool init() {
Here is the entire source code.
#include <iostream>
#include <SDL.h>
const int SCREEN_WIDTH = 500;
const int SCREEN_HEIGHT = 500;
bool init();
bool loadMedia();
void quit();
int time = 5000;
SDL_Window* window = NULL;
SDL_Surface* surface = NULL;
SDL_Surface* topImage = NULL;
bool init() {
bool success = true;
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << SDL_GetError() << std::endl;
success = false;
}
else{
SDL_CreateWindow("My Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if(window == NULL) {
std::cout << SDL_GetError() << std::endl;
success = false;
}
}
return success;
}
bool loadMedia() {
bool success = true;
surface = SDL_GetWindowSurface(window);
if(surface == NULL) {
std::cout << SDL_GetError() << std::endl;
success = false;
}
else {
topImage = SDL_LoadBMP("image.bmp");
if(topImage = NULL) {
std::cout << SDL_GetError() << std::endl;
success = false;
}
else {
SDL_BlitSurface(topImage, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(time);
}
}
return success;
}
void quit() {
SDL_FreeSurface(topImage);
topImage = NULL;
SDL_DestroyWindow(window);
window = NULL;
surface = NULL;
SDL_Quit();
}
int main(int argc, char* args[]) {
if(init() == true) {
init();
if(loadMedia() == true) {
loadMedia();
}
}
quit();
return 0;
}
You are getting this error:
error: 'SDL_WINDOWPOS_UNDEFINED' was not declared in this scope
which means that your including headers for an older version of SDL. but SDL_WINDOWPOS_UNDEFINED is defined in the SDL 2.0 version.
Just make sure to include the right headers which you can download them from the official library website: http://www.libsdl.org/download-2.0.php