I'm learning to programming with SDL2. Currently, I'm making a basic exercise. My program load a background image, and a complete sprite sheet on the background. But I'm having problems while executing the program. When I execute the binary, the program window closes immediately by itself; I cant see anything. I think it is a problem with the main loop, but it looks right for me. This is my code
#include "SDL.h"
void main () {
int gameover = 0;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* TheWindow;
SDL_Renderer* RenderEngine;
SDL_Surface* LoadedSurface;
SDL_Surface* LoadedImage;
SDL_Texture* CharacterImg;
SDL_Texture* BackgroundImg;
TheWindow = SDL_CreateWindow("Character Test",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 580, SDL_WINDOW_RESIZABLE);
RenderEngine = SDL_CreateRenderer( TheWindow, -1, SDL_RENDERER_ACCELERATED);
LoadedSurface= SDL_LoadBMP("./maptest.bmp");
BackgroundImg = SDL_CreateTextureFromSurface( RenderEngine, LoadedSurface);
SDL_FreeSurface(LoadedSurface);
LoadedImage = SDL_LoadBMP("./sprite.bmp");
CharacterImg = SDL_CreateTextureFromSurface( RenderEngine, LoadedImage);
SDL_FreeSurface(LoadedImage);
SDL_Event event;
while (!gameover)
{
if (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
gameover = 1;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
gameover = 1;
break;
}
}
break;
}
SDL_RenderClear(RenderEngine);
SDL_RenderCopy(RenderEngine, BackgroundImg, NULL, NULL);
SDL_RenderCopy(RenderEngine, CharacterImg, 120, 80);
SDL_RenderPresent(RenderEngine);
}
SDL_Quit();
}
Your code will quit the while-loop if any SDL_PollEvent happens:
while (!gameover)
{
if (SDL_PollEvent(&event)) //Any SDL_PollEvent that gets into if...
{
switch (event.type)
{
case SDL_QUIT:
gameover = 1;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
case SDLK_q:
gameover = 1;
break;
}
}
break; //...will eventually hit this break if it didn't break before
}
SDL_RenderClear(RenderEngine);
SDL_RenderCopy(RenderEngine, BackgroundImg, NULL, NULL);
SDL_RenderCopy(RenderEngine, CharacterImg, 120, 80);
SDL_RenderPresent(RenderEngine);
}
Related
I wrote these following lines of codes:
#include <sdl.h>
#include <iostream>
#include <stdio.h>
#include <string>
bool running = true;
enum KeyPressSurfaces {
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
//de deallocate surface
KEY_PRESS_SURFACE_TOTAL
};
int main(int argc, char** argv) {
//standard stuffs
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("vibin' with smug pika", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 300, 300, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface* loadSurface(std::string path);
SDL_Surface* surface = SDL_GetWindowSurface(window);
SDL_Surface* keypress [KEY_PRESS_SURFACE_TOTAL];
//anh hien tai dang duoc load, de BlitSurface len surface
//SDL_BlitSurface(current --> surface)
SDL_Surface* current = NULL;
//set windows icon
SDL_Surface* icon = SDL_LoadBMP("../pikachu/keypress_bmp/icon.bmp");
SDL_SetWindowIcon(window, icon);
SDL_Event event;
//load each image into the keypress array
keypress[KEY_PRESS_SURFACE_DEFAULT] = SDL_LoadBMP("../pikachu/keypress_bmp/default.bmp");
keypress[KEY_PRESS_SURFACE_UP] = SDL_LoadBMP("../pikachu/keypress_bmp/up.bmp");
keypress[KEY_PRESS_SURFACE_DOWN] = SDL_LoadBMP("../pikachu/keypress_bmp/down.bmp");
keypress[KEY_PRESS_SURFACE_LEFT] = SDL_LoadBMP("../pikachu/keypress_bmp/left.bmp");
keypress[KEY_PRESS_SURFACE_RIGHT] = SDL_LoadBMP("../pikachu/keypress_bmp/right.bmp");
while (running) {
while (SDL_PollEvent(&event)){
switch (event.type) {
//user click x
case SDL_QUIT:
running = false;
break;
//where all the user inputs are handled
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_UP:
current = keypress[KEY_PRESS_SURFACE_UP];
break;
case SDLK_DOWN:
current = keypress[KEY_PRESS_SURFACE_DOWN];
break;
case SDLK_LEFT:
current = keypress[KEY_PRESS_SURFACE_LEFT];
break;
case SDLK_RIGHT:
current = keypress[KEY_PRESS_SURFACE_RIGHT];
break;
case SDLK_SPACE:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
break;
default:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
}
}
}
SDL_BlitSurface(current, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
}
//deallocating surfaces
for(int i=0; i<KEY_PRESS_SURFACE_TOTAL; ++i) {
SDL_FreeSurface(keypress[i]);
keypress[i] = NULL;
}
//destroy everythangggg
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
However, this bit:
default:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
does not run at all, no matter where I put it. The program should have shown the default image at the beginning, but there's only black when I compiled. Everything else runs fine and I cannot determine what mistake I make.
I'm using CodeBlock version 20.03 and the latest version of SDL2.
I created a solution for you, and I have some notes to check from your end,
Check if the file path is correct
../pikachu/keypress_bmp/default.bmp.
When you want to trigger the default, you should press another key
e.i Enter, A, B, etc.
I have downloaded an SDL library I am not sure if you are using the
same, but mine is V2.
I have commented on your code, which I didn't use here in the image
path.
here is my code and result:
//#include <sdl.h>
#include <SDL.h>
#include <iostream>
#include <stdio.h>
#include <string>
bool running = true;
enum KeyPressSurfaces {
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
//de deallocate surface
KEY_PRESS_SURFACE_TOTAL
};
int main(int argc, char** argv) {
//standard stuffs
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("vibin' with smug pika", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 300, 300, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface* loadSurface(std::string path);
SDL_Surface* surface = SDL_GetWindowSurface(window);
SDL_Surface* keypress[KEY_PRESS_SURFACE_TOTAL];
//anh hien tai dang duoc load, de BlitSurface len surface
//SDL_BlitSurface(current --> surface)
SDL_Surface* current = NULL;
//set windows icon
//SDL_Surface* icon = SDL_LoadBMP("../pikachu/keypress_bmp/icon.bmp");
SDL_Surface* icon = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img1.bmp");
SDL_SetWindowIcon(window, icon);
SDL_Event event;
//load each image into the keypress array
/*
keypress[KEY_PRESS_SURFACE_DEFAULT] = SDL_LoadBMP("../pikachu/keypress_bmp/default.bmp");
keypress[KEY_PRESS_SURFACE_UP] = SDL_LoadBMP("../pikachu/keypress_bmp/up.bmp");
keypress[KEY_PRESS_SURFACE_DOWN] = SDL_LoadBMP("../pikachu/keypress_bmp/down.bmp");
keypress[KEY_PRESS_SURFACE_LEFT] = SDL_LoadBMP("../pikachu/keypress_bmp/left.bmp");
keypress[KEY_PRESS_SURFACE_RIGHT] = SDL_LoadBMP("../pikachu/keypress_bmp/right.bmp");
*/
keypress[KEY_PRESS_SURFACE_DEFAULT] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/imgD.bmp");
keypress[KEY_PRESS_SURFACE_UP] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img3.bmp");
keypress[KEY_PRESS_SURFACE_DOWN] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img4.bmp");
keypress[KEY_PRESS_SURFACE_LEFT] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img5.bmp");
keypress[KEY_PRESS_SURFACE_RIGHT] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img6.bmp");
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
//user click x
case SDL_QUIT:
running = false;
break;
//where all the user inputs are handled
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_UP:
current = keypress[KEY_PRESS_SURFACE_UP];
break;
case SDLK_DOWN:
current = keypress[KEY_PRESS_SURFACE_DOWN];
break;
case SDLK_LEFT:
current = keypress[KEY_PRESS_SURFACE_LEFT];
break;
case SDLK_RIGHT:
current = keypress[KEY_PRESS_SURFACE_RIGHT];
break;
case SDLK_SPACE:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
break;
default:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
}
}
}
SDL_BlitSurface(current, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
}
//deallocating surfaces
for (int i = 0; i < KEY_PRESS_SURFACE_TOTAL; ++i) {
SDL_FreeSurface(keypress[i]);
keypress[i] = NULL;
}
//destroy everythangggg
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
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".
So I've tried this on two machines running two different OS's and the same thing happens between them.
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, char *argv[])
{
bool running = true;
SDL_Init( SDL_INIT_EVERYTHING);
SDL_Window* win = SDL_CreateWindow("test", 100, 100, 800, 600,
SDL_WINDOW_SHOWN);
SDL_Renderer* ren = SDL_CreateRenderer(win, -1, 0);
int r = 0;
while(running)
{
SDL_Event event;
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_d:
r++;
break;
case SDLK_RIGHT:
r++;
break;
}
break;
}
SDL_SetRenderDrawColor(ren, r, 255, 255, 255);
SDL_RenderClear(ren);
SDL_RenderPresent(ren);
}
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
When holding down the right arrow key, it flickers, r is increasing much faster.
When holding down d, it slowly increases.
Why?
SDL_PollEvent returns 1 if there is a pending event or 0 if there are none available. You don't check return status and look into event anyway, even if you have no reason to. What you'll find here is pretty much undefined (most likely just old data - reading the same event over and over again, even if it didn't happen that often).
Correct event handling is done within a loop:
while(running) {
SDL_Event ev;
while(SDL_PollEvent(&ev)) {
// process event here
}
// draw here
}
I have problems deactivating fullscreen mode with my program. Entering fullscreen happens correctly, but trying to go back to windowed mode doesn't work, the only effect is that the cursor gets shown again.
Here's the MCVE/SSCCE that reproduces the issue for me:
void ToggleFullscreen(SDL_Window* Window) {
Uint32 FullscreenFlag = SDL_WINDOW_FULLSCREEN;
bool IsFullscreen = SDL_GetWindowFlags(Window) & FullscreenFlag;
SDL_SetWindowFullscreen(Window, IsFullscreen ? 0 : FullscreenFlag);
SDL_ShowCursor(IsFullscreen);
}
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* Window = SDL_CreateWindow("",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
bool Exit = false;
for (SDL_Event Event; !Exit;) {
SDL_WaitEvent(&Event);
if (Event.type == SDL_KEYDOWN) {
switch (Event.key.keysym.sym) {
case SDLK_f: ToggleFullscreen(Window); break;
case SDLK_q: Exit = true; break;
}
}
}
SDL_DestroyWindow(Window);
SDL_Quit();
}
SDL_SetWindowFullscreen returns 0, as if the operation was successful. What am I doing wrong? (I'm using SDL 2.0.3 on OS X 10.10.3.)
It looks like a known issue. Hopefully the SDL developers will fix it. I found the following bug report.
https://github.com/libsdl-org/SDL/issues/1428
Even now there still appears to be a problem with SDL_SetWindowFullscreen. I tried to add fullscreen functionality to my video player with this function. However, it would randomly crash when transitioning between fullscreen and windowed mode.
I found a temporary work around that appears to be working correctly for now.
SDL_DisplayMode dm;
if (SDL_GetDesktopDisplayMode(0, &dm))
{
printf("Error getting desktop display mode\n");
return -1;
}
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYUP:
switch (event.key.keysym.sym)
{
case SDLK_f:
SDL_RestoreWindow(screen); //Incase it's maximized...
SDL_SetWindowSize(screen, dm.w, dm.h + 10);
SDL_SetWindowPosition(screen, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}
break;
}
}
It's basically "fake" fullscreen. It resizes the window so the client area covers the whole screen and the minimize, maximize, exit buttons are off screen.
Hope this helps.
I know this may be 5 years after date, but I was facing the same problem, and I found your code way more complex then need be. So I just wanted to add for however comes here:
//somewhere outside the loop
bool isFullScreen = true;
void toggleFullScreen(SDL_Window* window, bool currentState)
{
isFullScreen = !currentState;
SDL_SetWindowFullscreen(window, !currentState);
SDL_ShowCursor(currentState);
}
just place the isFullscreen at the currenState and you have a good toggle with a keypress event.
This works fine for me in SDL2(pressing f toggles it on/off and q quits):
SDL_Window* window = SDL_CreateWindow("Fullscreen demo", 0, 0, 640, 480, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_Event event;
bool fullScreen = false;
SDL_bool running = SDL_TRUE;
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = SDL_FALSE;
break;
case SDL_KEYDOWN:
if(event.key.keysym.scancode == SDL_SCANCODE_F){
fullScreen = !fullScreen;
if(fullScreen){
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
}
else{
SDL_SetWindowFullscreen(window, 0);
}
}
if(event.key.keysym.scancode == SDL_SCANCODE_Q){
running = SDL_FALSE;
}
break;
default: break;
}
}
// drawing stuff here...
// swap and display buffer
SDL_RenderPresent(renderer);
}
[SOLVED]I'm following this tutorial (video) and I'm at this very moment. I had no problems with compiling, but when it comes to running the program it's just flashing for a second and turning off. So I've run the debugger and I found a segmentation fault from SDL_DisplayFormat in my load_image function, when I comment off lines where I load images it works ok, but I can't find the reason of the problem.
[SOLUTION] I haven't fill the .bmp files that is why the SDL_DisplayFormat didn't work. Once filed with drawning, everything started to work.
Here is my code:
#include "game.h"
/*TODO
*stworzyć plik z blokami "blocks.bmp"
*stworzyć plik z tlem "background.bmp"
*uzywac jako tla do obrazkow 000,255,255
*
*/
game::game()
{
//zaladowanie ekranu
SDL_Init(SDL_INIT_EVERYTHING);
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGTH, 32, SDL_SWSURFACE);
//ladowanei obrazkow
//ustawianie polozenia i rozmiaru kamery
camera.x = camera.y = 0;
camera.w = SCREEN_WIDTH;
camera.h = SCREEN_HEIGTH;
//inicjalizacja kierunku w kotrym sie poruszamy
direction[0] = direction[1] = 0;
running = true;
block = (load_image("blocks.bmp"));
background = (load_image("background.bmp"));
}
game::~game()
{
SDL_FreeSurface(block);
SDL_FreeSurface(background);
SDL_Quit();
}
SDL_Surface* game::load_image (const char* filename)
{
SDL_Surface* tmp = SDL_LoadBMP(filename);
SDL_Surface* tmp2 = SDL_DisplayFormat(tmp);
//do odkomentowania kolorkey na razie zeby sprawdzac kolizje
// SDL_SetColorKey(tmp2, SDL_SRCCOLORKEY, SDL_MapRGB(screen->format, 0x00, 0xff, 0xff)
SDL_FreeSurface(tmp);
return tmp2;
}
void game::handleEvents()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
running = false;
return;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_LEFT:
direction[0] = 1;
break;
case SDLK_RIGHT:
direction[1] = 1;
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_LEFT:
direction[0] = 0;
break;
case SDLK_RIGHT:
direction[1] = 0;
break;
}
break;
}
}
}
void game::start()
{
while(1)
{
handleEvents();
SDL_Flip(screen);
}
}
One advise up front: Provide complete, minimal code including compile instructions. Yours doesn't have a main() function and the class definition is missing too (game.h). After reconstructing this and running it in a debugger, I find that the first SDL_LoadBMP() returns NULL (maybe that's the same at yours, but here it's definitely the case that I don't have the according files), so I have no clue if you have the same problem or not.
Now, what you can try to fix this is to check returnvalues. In this case, try this:
SDL_Surface* tmp = SDL_LoadBMP(filename);
if(!tmp)
throw std::runtime_error("SDL_LoadBMP() failed");
Using a unique_ptr or some custom wrapper class is also a good advice in order to not leak resources.