Can't open a window with SDL/C++ - c++

i stuck in a big bug with my code which i can't open the first window of my game after running it! it just open blank for a few secondes and then it closes automatically. I doon't know what wrong with my code beacause i'm following series of tutorials and my code seems like the code in the tutorials. here's my code:
#include "stdafx.h"
#include "FirstClass.h"
FirstClass::FirstClass(void){
bool quit = false;
window = NULL;
window = SDL_CreateWindow("Snaykie v1.0",350, 150, 800, 500, SDL_WINDOW_SHOWN);
if (window == NULL){
std::cout << "Can not open the game!" << std::endl;
}
renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
evt = new SDL_Event();
//background image
txt = NULL;
txt = IMG_LoadTexture(renderer, "mainview.bmp");
rct.x = 0 ;
rct.y = 0;
rct.h = 500;
rct.w = 800;
//button start
sbutt = NULL;
sbutt = IMG_LoadTexture(renderer, "startbutton.bmp");
startrct.x = 0 ;
startrct.y = 0;
startrct.h = 100;
startrct.w = 100;
}
FirstClass::~FirstClass(void)
{
SDL_DestroyTexture(txt);
SDL_DestroyTexture(sbutt);
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
delete evt;
}
//the code below is the loops that let the window stucks forever to keep opened
void FirstClass :: GameStart(void){
while (!quit && evt->type != SDL_QUIT){
SDL_PollEvent(evt);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, txt, NULL, &rct);
SDL_RenderCopy(renderer, sbutt, NULL, &startrct);
SDL_RenderPresent(renderer);
}
}
Please help me and thanks i'm really in a big problem.

You are handling the evt variable in a bad way. It is allocated but not initialized, and you compare the uninitialized value to SDL_QUIT. You should reorder the code inside FirstClass::GameStart and preferably use a local variable (since there is no actual need to use a dynamically allocated one) and remove the allocation and deletion of the existing evt from constructor and destructor. Here is a better version of FirstClass::GameStart:
void FirstClass::GameStart(void){
SDL_Event evt;
while (SDL_PollEvent(&evt)){
if (evt.type == SDL_QUIT) {
// a user requested termination has been received, exit the loop
break;
}
else {
// filter the event?
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, txt, NULL, &rct);
SDL_RenderCopy(renderer, sbutt, NULL, &startrct);
SDL_RenderPresent(renderer);
}
}
}
Also ensure that you are actually invoking the FirstClass::GameStart funcion from main, maybe you are simply not running the event loop at all.

Related

SDL2 program eats a lot of memory when minimized

I'm just trying to create a simple SDL2 window with a simple renderer. When I debug it, it runs normally, the memory still normal. But when I minimize it, press the minimize button then suddenly the memory just keep going up and only when i reopened that window then the memory goes back normal.
Memory spike
The code:
#include <SDL.h>
#include <SDL_image.h>
int main(int argc, char* args[]) {
SDL_Window* gWindow;
SDL_Renderer* gRenderer;
SDL_Texture* gTexture;
SDL_Surface* temp;
//Init
SDL_Init(SDL_INIT_VIDEO);
gWindow = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1366, 768, SDL_WINDOW_SHOWN);
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
IMG_Init(IMG_INIT_PNG);
//loading medias
temp = IMG_Load("assets/sprites/700.png");
gTexture = SDL_CreateTextureFromSurface(gRenderer, temp);
SDL_FreeSurface(temp);
//The main loop
bool quit = false;
SDL_Event e;
while (!quit)
{
while (SDL_PollEvent(&e) != 0)
{
if (e.type == SDL_QUIT)
{
quit = true;
}
}
SDL_RenderClear(gRenderer);
SDL_RenderCopy(gRenderer, gTexture, NULL, NULL);
SDL_RenderPresent(gRenderer);
}
//Destroy things
SDL_DestroyTexture(gTexture);
gTexture = NULL;
SDL_DestroyRenderer(gRenderer);
SDL_DestroyWindow(gWindow);
gWindow = NULL;
gRenderer = NULL;
IMG_Quit();
SDL_Quit();
return 0;
}
switch (m_event.window.event)
{
case SDL_WINDOWEVENT_MINIMIZED:
while (SDL_WaitEvent(&m_event))
{
if (m_event.window.event == SDL_WINDOWEVENT_RESTORED)
{
break;
}
}
break;
...
So when you minimize the Window, SDL keeps waiting for events. No further code could memory leak, since it stays in the lazy polling loop until the window is restored.
I traced the leak back to SDL_RenderClear, which shouldn't be supposed to run while minimized.
I just ran your code and compiled it. Seems fine. However you did mention when you minimize the program your ram meter increases, how long are you able to perform this repetition before it crashes? and does it even crash? It could be normal behavior. If your program crashes, its a memory leak which could indicate forgetting to de-allocate some other pointer to a memory object/variable.

How can I handle input in SDL?

My SDL program wont work. It was supposed to change the image when I pressed Up. However, it changes the image only when I click on the x in the Window
#include "SDL.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
int main(int argc, char* argv[])
{
enum KeyPressSurfaces {
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_TOTAL
};
SDL_Init(SDL_INIT_VIDEO);
SDL_Event e;
SDL_Window* window = SDL_CreateWindow("antena1", // window's title
10, 25, // coordinates on the screen, in pixels, of the window's upper left corner
640, 420, // window's length and height in pixels
SDL_WINDOW_OPENGL);
SDL_Surface* key_press_surface[KEY_PRESS_SURFACE_TOTAL];
SDL_Surface* gImage = NULL;
SDL_Surface* gScreenSurface = NULL;
bool quit = false;
key_press_surface[KEY_PRESS_SURFACE_UP] = SDL_LoadBMP("hello_world.bmp");
gScreenSurface = SDL_GetWindowSurface(window);
gImage = SDL_LoadBMP("nick.bmp");
if (gImage == NULL) {
printf("Erro", SDL_GetError);
}
SDL_BlitSurface(gImage, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface(window);
gScreenSurface = SDL_GetWindowSurface(window);
while (!quit) {
while (SDL_PollEvent(&e) == 0) {
if (e.type == SDL_QUIT) {
quit = true;
//SDL_DestroyWindow(window);#
}
else if (e.type == SDL_KEYDOWN) {
switch (e.key.keysym.sym) {
case SDLK_LEFT:
gImage = key_press_surface[KEY_PRESS_SURFACE_UP];
break;
default:
gScreenSurface = NULL;
break;
}
}
}
};
SDL_BlitSurface(gImage, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(30000);
return 0;
}
https://wiki.libsdl.org/SDL_PollEvent
SDL_PollEvent returns 0 if there are no events available. So per the example in the above article, in order to get into the while statement for SDL_PollEvent, there must be events in the queue. However, your code only goes into the loop if there are NO events in the queue. So anything that happens once you get there is undefined.
IOW, just remove the "== 0".

Drawing SDL_Surface from another class

So I have three classes Application, DrawMgr and Cube. In Application.cpp is my main loop in which I call DrawMgr::DrawCube in which I call Cube::Draw.
Application.cpp
while (!quit)
{
//Draw Background
gDrawMgr.DrawBackground();
gDrawMgr.DrawCube();
//UpdateScreen
gDrawMgr.UpdateScreen();
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT || e.key.keysym.sym == SDLK_ESCAPE)
{
quit = true;
}
}
}
DrawMgr.cpp
SDL_Surface* screenSurface;
void DrawMgr::DrawCube()
{
gCube.Draw(screenSurface);
}
Cube.cpp
void Cube::Draw( SDL_Surface* destination )
{
SDL_Rect offset;
offset.x = 100;
offset.y = 100;
SDL_FillRect(cube, NULL, SDL_MapRGB( cube->format, 0, 0, 0 ) );
SDL_BlitSurface( cube, NULL, destination, &offset);
}
When I run the program, the cube doesn't appear, what am I doing wrong?
Are you sure you're using SDL2.0 ? because things have changed, you need a SDL_Renderer and a SDL_Texture. Seems like you're trying to do it in the SDL 1 way.
In SDL2, to update the screen, we use those calls
SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent(sdlRenderer);
RenderClear to wipe the screen content.
RenderCopy to draw some texture on it.
RenderPresent to draw the final result on the screen.
Go see the migration guide for more details on the new flow.
https://wiki.libsdl.org/MigrationGuide

SDL_Delay() while getting events (kinda nooby)

C++, SDL 2
Im making a disco simulator thats just loops through pictures and plays music.
(Epilepsy warning) http://imgur.com/9ePOIAw
Basically I want to run this code
while (isPartying){
currentImage = image1;
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_Delay(25);
SDL_UpdateWindowSurface(window);
currentImage = image2;
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(25);
currentImage = image3;
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(25);
//image 3, 4, 5 and so on
}
while getting events all the time.
while (SDL_PollEvent(&ev) != 0){
if (ev.type == SDL_QUIT){
isPartying = false;
}
}
I want it to get events while Im in the middle of the isPartying loop. Now it only checks for events at the beginning (or the end, depends on where I put the event loop of course). Anyone know a better way to wait for the next picture then SDL_Delay()? Or maybe even have another solution
Ano
Basically, what you want to do is to achieve two things at a time.
You have two options:
Using SDL_Thread, but I prefere to not use threads when another solution is possible (because you may have to deal with semaphores or mutexes)
Using SDL_TimerCallback (some would say that too much timers kill the flow of the code, but it's what we gonna use)
Here is a code sample (NB: you must pass SDL_INIT_TIMER to SDL_Init()).
void IsPartying() {
SDL_Event ev;
while (SDL_PollEvent(&ev)){
if (ev.type == SDL_QUIT){
return false;
}
}
return true
}
uint32_t ChangeImage(uint32_t interval, void* param) {
int *imageNb = param;
(*imageNb)++
return interval
}
void Processing() {
// Store your images in SDL_Surface **imageArray
int imageNb = 0;
SDL_TimerID t = SDL_AddTimer(25, ChangeImage, &imageNb);
while (IsPartying()) {
SDL_BlitSurface(imageArray[imageNb], NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(1); // Release proc charge
}
SDL_RemoveTimer(SDL_TimerID);
}
Of course you still need to check if you iterated over all the images, else you'll got a nice segfault while trying to access an unallocated cell of the array.

SDL text rendering access violation

I'm using SDL 2.0 with C++ for 2D graphics, compressed image format loading, sound playback and so on. Consider the following code:
int main(int argc, char *args[])
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
SDL_Window *pWindow = SDL_CreateWindow("Access Violation", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1920, 1080, SDL_WINDOW_FULLSCREEN);
SDL_Renderer *pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED);
Mix_Init(0);
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);
Mix_Music *pMusic = Mix_LoadMUS("music.wav");
TTF_Init();
TTF_Font *pFont = TTF_OpenFont("font.ttf", 28);
bool quit = false;
SDL_Event ev;
while(!quit)
{
while(SDL_PollEvent(&ev) != 0)
{
switch(ev.type)
{
case SDL_QUIT:
quit = true;
break;
}
}
SDL_SetRenderDrawColor(pRenderer, 255, 255, 255, 255);
SDL_RenderClear(pRenderer);
for(int i = 0; i < 864; i++)
{
SDL_Color clr = { 0, 0, 0 };
SDL_Surface *pSurface = TTF_RenderText_Solid(pFont, "Hey!", clr);
SDL_Texture *pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
SDL_Rect dstrect = { (int)(i/27) * 60, (i%27)*40, pSurface->w, pSurface->h };
SDL_RenderCopy(pRenderer, pTexture, 0, &dstrect);
SDL_DestroyTexture(pTexture);
SDL_FreeSurface(pSurface);
}
SDL_RenderPresent(pRenderer);
}
TTF_CloseFont(pFont);
Mix_FreeMusic(pMusic);
SDL_DestroyRenderer(pRenderer);
SDL_DestroyWindow(pWindow);
Mix_CloseAudio();
Mix_Quit();
IMG_Quit();
TTF_Quit();
SDL_Quit();
return 0;
}
What this basically does is that it just initializes SDL, loads a music, loads a font, and fills continuously the whole screen with text. Fine.
But!
If I add this line
...
SDL_Event ev;
Mix_PlayMusic(pMusic, 0);
while(!quit)
...
right here, text redrawing in the cycle
for(int i = 0; i < 864; i++)
{
...
}
starts to behave unpredictably. One of the SDL's function will shoot an access violation, after some time - between 1 and 30 seconds after start. On the other hand, would I omit text redrawing, music is playing fine.
Any ideas? Of course, all return values are checked. I've omitted checks because of the clarity of the code.
EDIT: Typos.