Stack Trace :
So, I'm trying to create a 2D game and right now I'm trying to display and move a image, however when I Debug the game/run it, visual studio and the game freezes and can't quit, not even when using the task manager to kill it.
The only way to unfreeze it is by logging off or restarting the pc which forces both of them to close.
I also get some weird error :
Unhandled exception at 0x71002A95 (SDL2_ttf.dll) in SDLGame.exe: 0xC0000005: Access violation reading location 0x00000000.
I have no idea what it means and how to fix it, but I'm guessing it has something to do with my code that I need to change.
Here's my code :
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
// Macros
#define pause system("PAUSE"); // Works on windows only, removed in alpha / beta versions.
// Pre "init" of functions
void QuitGame();
int InitGame();
void processInput();
void InitRects();
// Variables
int FramesPassed = 0;
int FramesPerSecond = 0; // Not used yet
SDL_Renderer* renderer = nullptr;
SDL_Window* window = nullptr;
SDL_Event evnt;
SDL_Rect sprite1_Rect;
SDL_Rect FPS_Text_Rect;
TTF_Font* Sans = TTF_OpenFont("Fonts/Aaargh.ttf", 40);
SDL_Color Color_White = { 255, 255, 255 };
SDL_Surface* FPS_Text_Surface = nullptr;
SDL_Texture* FPS_Text = nullptr;
SDL_Texture* testImg = nullptr;
static bool isRunning = true;
int SDL_main(int argc, char* argv[])
{
InitGame();
InitRects();
std::cout << "Displaying text on screen using SDL TTF doesn't work" << std::endl;
std::cout << "This happens when the TTF Surface is being rendered on screen" << std::endl;
std::cout << "check line : 123 and 124." << std::endl;
while (isRunning)
{
FramesPassed++;
processInput();
SDL_RenderClear(renderer); // Clears the last/current frame?
// Render testImage on screen. (needs to be between render present and clear.)
SDL_RenderCopy(renderer, testImg, NULL, &sprite1_Rect);
SDL_RenderCopy(renderer, FPS_Text, NULL, &FPS_Text_Rect);
SDL_RenderPresent(renderer); // Pretty much draws everything again.
}
return 0;
QuitGame();
}
int InitGame()
{
std::cout << "Game Initializing..." << std::endl;
std::cout << "TTF SDL Initializing..." << std::endl;
if (TTF_Init() < 0)
{
std::cout << "SDL TTF Failed To Initialize : " << TTF_GetError() << std::endl;
pause
QuitGame();
}
else
{
std::cout << "SDL TTF Initialized Successfully" << std::endl;
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
std::cout << "SDL Initialization Failed : " << SDL_GetError() << std::endl;
pause
QuitGame();
}
else
{
std::cout << "SDL Initializing" << std::endl;
window = SDL_CreateWindow("Game Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1024, 720, SDL_WINDOW_SHOWN);
if (window == NULL)
{
std::cout << "Window Creation Failed : " << SDL_GetError() << std::endl;
pause
QuitGame();
}
else
{
std::cout << "SDL Initialized Successfully" << std::endl;
std::cout << "Renderer Initializing..." << std::endl;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL)
{
std::cout << "Renderer Creation Failed : " << SDL_GetError() << std::endl;
pause
QuitGame();
}
else
{
std::cout << "Renderer Initialized Successfully" << std::endl;
// This line (under) crashes game, and crashes visual studio...
FPS_Text_Surface = TTF_RenderText_Solid(Sans, "Frames Passed : " + FramesPassed, Color_White);
testImg = IMG_LoadTexture(renderer, "images/test.bmp");
FPS_Text = SDL_CreateTextureFromSurface(renderer, FPS_Text_Surface);
}
}
}
}
std::cout << "Game Has Successfully Initialized!" << std::endl;
return 0;
}
void InitRects()
{
sprite1_Rect.h = 32;
sprite1_Rect.w = 32;
sprite1_Rect.x = 10;
sprite1_Rect.y = 10;
FPS_Text_Rect.h = 100;
FPS_Text_Rect.w = 50;
FPS_Text_Rect.x = 2;
FPS_Text_Rect.y = 2;
}
void processInput()
{
if (SDL_PollEvent(&evnt)) {
switch (evnt.type) {
case SDL_QUIT:
QuitGame();
break;
case SDL_KEYDOWN:
switch (evnt.key.keysym.sym) {
case SDLK_a:
sprite1_Rect.x -= 1;
break;
case SDLK_d:
sprite1_Rect.x += 1;
break;
case SDLK_w:
sprite1_Rect.y-= 1;
break;
case SDLK_s:
sprite1_Rect.y += 1;
break;
}
break;
}
}
}
void QuitGame()
{
isRunning = false;
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
The problem is that you have the font as a global variable and load it straight away!
You need to call TTF_Init() first and load the font after!
By using a global vairable your loading it before initializing SDL_TTF, and this way TTF_OpenFont() will return a nullptr and if you try to read a nullptr gives an Access violation reading location 0x00000000 error!
Just call TTF_OpenFont() in a function and after TTF_Init() and it will work!
Just a tip you should check that Sans isn't a nullptr before using it!
Related
Game Engine Creation course work, questions about SDL, currently learning C++ SDL.
Met a question about SDL_Image, Couldn't open image.
When I run the code it closed instantly
bool InitSDL()
{
//Setup SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
cout << "SDL did not initialise. Error: " << SDL_GetError();
return false;
}
else
{
gWindow = SDL_CreateWindow(
"GEC_SDL",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN
);
if (gWindow == NULL)
{
cout << "Window was not created. Error: " << SDL_GetError();
return false;
}
}
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
if (gRenderer != NULL)
{
cout << "Renderer initialised." << endl;
//Initialise PNG loading.
int imageFlags = IMG_INIT_PNG;
if (!(IMG_Init(imageFlags) & imageFlags))
{
cout << "SDL_Image could not initialise. Error: " << IMG_GetError;
return false;
}
else {
cout << "SDL_Image initialised." << endl;
}
}
else
{
cout << "Renderer could not initialise. Error: " << SDL_GetError;
return false;
}
gTexture = LoadTextureFromFile("D:/_a'Programs/School/GEC_SDL/GEC_SDL/Images/text.bmp");
if (gTexture == NULL)
{
return false;
}
return true;
}
Error Messgae
Tried full path: D:_a'Programs\School\GEC_SDL\GEC_SDL\Images
Error Messgae
Load texture from file function
SDL_Texture* LoadTextureFromFile(string path)
{
FreeTexture();
SDL_Texture* pTexture = NULL;
//Load the image.
SDL_Surface* pSurface = IMG_Load( path.c_str() );
if (pSurface != NULL)
{
//Create the texture from the pixels on the surface.
pTexture = SDL_CreateTextureFromSurface(gRenderer, pSurface);
if (pTexture == NULL)
{
cout << "Unable to create texture from surface. Error: " << SDL_GetError() << endl;
}
SDL_FreeSurface(pSurface);
}
else
{
cout << "Unable to create texture from surface. Error: " << IMG_GetError() << endl;
}
return pTexture;
}
I searched similar question in the forum and tried their ways, none of them works, please help.
OMG, yes it's ''s problem, I rename the folder, now it works...
PS: stupid character sets
This is my .cpp file:
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
bool runningOnEmpty = false;
const char* title;
int xpos, ypos, width, height;
bool fullscreen = false;
SDL_Window *window;
SDL_Renderer *renderer;
void init(){
int flags = 0;
if(fullscreen){
flags = SDL_WINDOW_FULLSCREEN;
}
if(!SDL_Init(SDL_INIT_EVERYTHING)){
std::cout << "Sdl initialised!!\n";
window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if(window){
std::cout << "window created!!\n";
}
renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer){
std::cout << "renderer created!!\n";
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
}
runningOnEmpty = true;
} else {
runningOnEmpty = false;
}
if(TTF_Init()==-1) {
std::cout << "cannot init TTF: " << TTF_GetError() << "\n";
} else {
std::cout << "TTF initialized!" << "\n";
}
}
void render(){
SDL_RenderClear(renderer);
TTF_Font* rFont = TTF_OpenFont("./fonts/roboto.ttf", 20);
if(!rFont){
std::cout << "Cannot open font: " << TTF_GetError() << "\n";
}
SDL_Color White = {0, 0, 0};
SDL_Surface* surfaceMessage = TTF_RenderText_Solid(rFont, "Score: ", White);
if(surfaceMessage == NULL)
std::cout << "Cannot make surface!" << SDL_GetError() << "\n";
SDL_Texture* Message = SDL_CreateTextureFromSurface(renderer, surfaceMessage);
SDL_Rect mr;
mr.x = 50, mr.y = 50, mr.w = 100, mr.h = 100;
if(Message = NULL)
std::cout << "Cannot make texture!" << SDL_GetError() << "\n";
if(SDL_RenderCopy(renderer, Message, NULL, &mr))
std::cout << "Cannot render text!" << SDL_GetError() << "\n";
SDL_FreeSurface(surfaceMessage);
SDL_RenderPresent(renderer);
}
void clean(){
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
std::cout << "Game cleaned!\n";
}
void handleEvents(){
SDL_Event event;
SDL_PollEvent(&event);
switch(event.type){
case SDL_QUIT:
runningOnEmpty = false;
break;
default:
break;
}
}
int main(){
title = "Test";
xpos = SDL_WINDOWPOS_CENTERED;
ypos = SDL_WINDOWPOS_CENTERED;
width = 800, height = 900;
fullscreen = false;
init();
render();
while(runningOnEmpty){
handleEvents();
}
clean();
return 0;
}
It compiles without error, and when I run the executable it renders a white window, with no text on it(even if it should have some text).
The error comes when I try to use SDL_RenderCopy, and as I acknowledged using SDL_Error(), apparently the texture is invalid, even if I check it before using it.
This is the exact thing that I get in the console when running the code:
Sdl initialised!!
window created!!
renderer created!!
TTF initialized!
Cannot render text!Invalid texture
Game cleaned!
if(Message = NULL) is an assignment, not comparison, so your previous value of Message is lost and it is NULL after that, and that result is used as logic value (NULL == 0 == false, for that matter). Enabling compiler warnings should produce a message pinpointhing this specific problem, e.g. -Wall for gcc gives
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if(Message = NULL)
To compare values, use == operator.
Also your texture goes out of scope without DestroyTexture, which is clearly a resource leak.
I'm developing in VS2013 on a Windows 8.1 machine. The window flashes briefly on the screen (despite having a 2 second delay in the code).
Here is all the code:
#include <SDL.h>
#include <iostream>
int main(int argc, char **argv)
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 4;
}
//open a window
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;
return 3;
}
//renderer
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr){
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
return 2;
}
//load bitmap
SDL_Surface *bmp = SDL_LoadBMP("helloworld.jpg");
if (bmp == nullptr){
std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
return 6;
}
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
SDL_FreeSurface(bmp);
if (tex == nullptr){
std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
return 5;
}
SDL_RenderClear(ren);
SDL_RenderCopy(ren, tex, NULL, NULL);
SDL_RenderPresent(ren);
SDL_Delay(2000);
return 0;
}
It exits with a code 6. I was thinking it couldn't find the helloworld.jpg file. But, its there. I moved it from location to location hoping I was just an idiot. No luck. Its currently in the same directory as the .exe file.
SDL_LoadBMP will only load BMP formatted pictures, and guessing by the extension you have chosen you look to be using a JPEG formatted image, and your program is refusing to load it.
see SDL_Image for one possible solution.
My current code is as follows:
#include <iostream>
#include "SDL.h"
#include "SDL_image.h"
int main(int argc, char **argv) {
if (SDL_Init(SDL_INIT_EVERYTHING != 0)) {
std::cout << "SDL_Init() Error: " << SDL_GetError() << std::endl;
std::cin.get();
return 1;
}
SDL_Window *win = SDL_CreateWindow("RandomSDL2", 100, 100, 1280, 720, SDL_WINDOW_SHOWN);
if (win = nullptr) {
std::cout << "SDL_CreateWindow() Error: " << SDL_GetError() << std::endl;
std::cin.get();
return 1;
}
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr) {
std::cout << "SDL_CreateRenderer() Error: " << SDL_GetError() << std::endl;
std::cin.get();
return 1;
}
SDL_Surface *img = IMG_Load("res/test.png");
if (img == nullptr) {
std::cout << "IMG_Load() Error: " << IMG_GetError() << std::endl;
std::cin.get();
return 1;
}
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, img);
SDL_FreeSurface(img);
if (tex == nullptr) {
std::cout << "SDL_CreateTextureFromSurface() Error: " << SDL_GetError << std::endl;
std::cin.get();
}
SDL_RenderClear(ren);
SDL_RenderCopy(ren, tex, NULL, NULL);
SDL_RenderPresent(ren);
SDL_Delay(2000);
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
It seems that the CreateRenderer function throws the error Invalid Window, I'm unsure as to why, I'm currently following this tutorial, I've copied the code down to a T besides the resolution and the use of SDL_image, SDL_image shouldn't really effect the creation of the renderer at this stage, I've also tried the resolution specified in the tutorial and it seems to still throw the same error.
Does anyone have any insight on this issue?
if (win = nullptr) {
^ assignment, probably wanted ==
Don't set win to nullptr and it probably won't be nullptr.
Every time I run this program I got a this error:
Segmentation fault
testing.cpp
#include <iostream>
#include <cstdint>
#include <SDL.h>
#include <SDL_image.h>
#include "Surface.h"
#include "Point2D.h"
int main() {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
std::cerr << "Can not init SDL" << std::endl;
return -1;
}
SDL_Surface *scr = SDL_SetVideoMode(800, 600, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);
if ( scr == NULL ) {
std::cerr << "Can not open window" << std::endl;
return -1;
}
SDL_WM_SetCaption("Test Surface class", NULL);
Surface screen;
Surface image;
screen.set(SDL_GetVideoSurface());
if (image.load("./data/images/logo.png") == false) {
std::cerr << "Can not open file" << std::endl;
return -1;
}
bool run = true;
uint32_t sticks = SDL_GetTicks();
while(run) {
if (screen.draw(image, Rectangle(0, 0, image.getWidth(), image.getHeight()), Point2D(0, 0)) == false) {
std::cerr << "Can not draw to window" << std::endl;
return -1;
}
if ((SDL_GetTicks() - sticks)/1000 > 5) {
std::cerr << "End of time" << std::endl;
run = false;
}
SDL_Flip(screen.sdlSurface());
}
std::cerr << "Done" << std::endl;
SDL_Quit();
return 0;
}
There is the source code of class Surface
#include "Surface.h"
#include "Color.h"
Surface::Surface() {
this->surface = NULL;
}
Surface::~Surface() {
SDL_FreeSurface(this->surface);
this->surface = NULL;
}
bool Surface::draw(Surface source, Rectangle source_area, Point2D position) {
SDL_Rect sr = source_area.sdlRect();
SDL_Rect tr = {position.getX(), position.getY(), 0, 0};
std::cout << sr.x << "," << sr.y << "," << sr.w << "," << sr.h << std::endl;
std::cout << tr.x << "," << tr.y << "," << tr.w << "," << tr.h << std::endl;
std::cout << source.sdlSurface() << std::endl;
std::cout << this->surface << std::endl;
// TR and SR are currently unused. Just for case of testing
if (SDL_BlitSurface(source.sdlSurface(), NULL, this->surface, NULL) != 0) {
return false;
}
return true;
}
bool Surface::fill(Color color, Rectangle area) {
SDL_Rect tr = area.sdlRect();
std::cout << tr.x << "," << tr.y << "," << tr.w << "," << tr.h << std::endl;
std::cout << (int)color.sdlColor() << std::endl;
if ( SDL_FillRect(this->surface, &tr, color.sdlColor()) != 0) {
return false;
}
return true;
}
Rectangle Surface::getSize() {
return Rectangle(0, 0, this->getWidth(), this->getHeight());
}
bool Surface::load(std::string file) {
SDL_Surface *src = IMG_Load(file.c_str());
if (src == NULL) {
std::cout << "cyh" << std::endl;
std::cout << IMG_GetError() << std::endl;
return false;
}
this->surface = SDL_DisplayFormatAlpha(src);
if (this->surface == NULL) {
std::cout << "cyh1" << std::endl;
std::cout << SDL_GetError() << std::endl;
return false;
}
SDL_FreeSurface(src);
src = NULL;
return true;
}
void Surface::set(SDL_Surface *surface) {
this->surface = surface;
}
void Surface::set(Surface surface) {
this->surface = surface.sdlSurface();
}
The problem is probably in the draw function. If I change this line:
if (SDL_BlitSurface(source.sdlSurface(), NULL, this->surface, NULL) != 0) {
to:
if (SDL_BlitSurface(IMG_Load("./data/images/logo.png"), NULL, this->surface, NULL) != 0) {
everything seems to be ok. Could you give me a suggestion where should be the problem?
You're violating The Rule of 3.
You need to define a copy constructor and a copy assignment operator for this to work properly.
When you're passing the Surface in to the draw method, you're making a copy of it. Since you're managing a resource inside the Surface class (the SDL_Surface*), you'll have multiple instances of the class pointing at the same surface, so when the destructors are called, you'd be freeing the same SDL_Surface* more than once.
Edit: I would recommend passing your arguments by const reference. You don't need to make copies of the Surface objects when you want to draw them.
This:
bool Surface::draw(Surface source, Rectangle source_area, Point2D position);
Would become this:
bool Surface::draw(const Surface &source, const Rectangle &source_area, const Point2D &position);
And this can be applied to your other functions too.