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
}
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".
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);
}
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);
}
My image cant load can someone tell me why please?
I'm trying to change the offset when I press WASD, it will work in Code::Blocks but not the .exe file.
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include <SDL/SDL.h>
int WIDTH = 800;
int HEIGHT = 600;
int main (int argc, char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Surface *screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_SWSURFACE|SDL_DOUBLEBUF);
if (!screen){
printf("Unable to set 800x600 video: %s\n", SDL_GetError());
return 1;
}
SDL_WM_SetCaption("The Killer Of The Night Pre-Release 0.0.1", NULL);
SDL_Surface *player = SDL_LoadBMP("lol.bmp");
if (!player){
printf("Unable to load the image here's the error: %s\n", SDL_GetError());
}
SDL_Rect offset;
offset.x = 100;
offset.y = 200;
bool done = false;
while (!done)
{
SDL_Event event;
SDL_PollEvent(&event);
if (event.type == SDL_QUIT)
{
done = true;
}
if (event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_ESCAPE:
done = true;
break;
case SDLK_w:
offset.y -= 1;
break;
case SDLK_a:
offset.x -= 1;
break;
case SDLK_s:
offset.y += 1;
break;
case SDLK_d:
offset.x += 1;
break;
}
}
SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 25,25,255));
SDL_BlitSurface(player, 0, screen, &offset);
SDL_Flip(screen);
}
return 0;
}
It's working fine in Code::Blocks but when I run the .exe file it's not working!?!
You need to put lol.bmp in the directory with your exe.
When you run an executable in CodeBlocks, the working directory is the directory of the Code Block project file (.cbp), which is where your lol.bmp is located. You need to put that file in the bin/Debug/ folder or bin/Release/ folder depending on your build target.
More info would be nice since "it's not working" doesn't really say what's failing. For example is it a dll error, or like previously stated is lol.bmp not in the proper folder. Also I believe SDL_Rect needs a height and width as well.