This SDL program works fine (displays a windows and a draws a bitmap onto it), however, if I declare any variables in my program (such as int, long, etc), the windows freezes and is white instead of black and nothing draws. What could possibly cause this?
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
int main(int argc, char* argv[]) {
// line below will cause SDL crash
// int blabla = 640;
SDL_Window *window;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(
"A rather exceptional SDL window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_OPENGL
);
if (window == NULL) {
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
SDL_Renderer *renderer;
SDL_Texture *texture;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface *brush;
brush = IMG_Load("brush2.png");
texture = SDL_CreateTextureFromSurface(renderer, brush);
SDL_RenderClear(renderer);
SDL_Rect *sRect, *dRect;
sRect->w = 10;
sRect->h = 4;
sRect->x = 0;
sRect->y = 0;
dRect->w = 10;
dRect->h = 4;
dRect->x = 10;
dRect->y = 10;
SDL_RenderCopy(renderer, texture, sRect, dRect);
SDL_RenderPresent(renderer);
SDL_Delay(1000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
You are writing unallocated memory.
SDL_Rect *sRect, *dRect;
sRect->w = 10; /* w doesn't exist. Writing is undefined behaviour. */
sRect and dRect are only pointers. They need to point to valid memory before struct members are accessed.
You could declare them in stack instead:
SDL_Rect sRect, dRect;
sRect.w = 10;
sRect.h = 4;
...
SDL_RenderCopy(renderer, texture, &sRect, &dRect);
You should also check return values of SDL_-functions. If those fail, and you continue execution regardless, you may experience weird behaviour or crashes.
Related
My program is about drawing the Mandelbrot set. I discovered that when I click another window in the operating system (eg. Chrome, or text editor ...) my program clears the screen to black but continues drawing where it finished. It is during drawing. If the drawing is finished and I click another window then nothing clearing happens.
Is there a solution to fix this (eg. switching something on or off in SDL) without tracking all the pixels onto the screen and print the entire pixel matrix all the times?
Minimal code:
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
enum {WIDTH = 1700, HEIGHT = 950};
int main(){
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Minimal", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Event event;
bool exit_ = false;
while (! exit_){
for (int i = 1; i < WIDTH; i++){
for (int j = 1; j < HEIGHT; j++){
SDL_RenderDrawPoint(renderer, i, j);
}
SDL_RenderPresent(renderer);
}
while (SDL_PollEvent(&event)){
if (event.type == SDL_QUIT) exit_ = true;
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
(Note: I haven't got any window event handling in the program.)
I think you need to put SDL_RenderClear(Renderer) at the top of the while loop.
If you do like that, window will be never cleared after rendering.
For example if you don't clear the window, a moving dot will leave his traces..
I work woth SDL too, and i always do this
So I've recently started to learn SDL2, and I am trying run a simple program, but I don't know what I'm doing wrong. My IDE (Code Blocks) says that the line of code SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); has some kind of error and won't run. What am I missing or doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
static const int width = 800;
static const int height = 600;
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); // <-Supposed Error
SDL_Window *window = SDL_CreateWindow("Hey\n", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRendererDrawColor(renderer, 255, 0, 0, 255);
bool running = true;
SDL_Event event;
while(running)
{
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
}
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
The linker error that I get is:
undefined reference to `SDL_SetRendererDrawColor'
Because this function doesn't exist in SDL2, you must use SDL_SetRenderDrawColor().
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
I'm using the SDL2 library, in C.
I made a test program to open a white window, but I get a segmentation fault with the function SDL_FillRect even though there are no errors or warnings when I build it.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
static const int window_width = 1000;
static const int window_height = 1000;
int main(int argc, char* argv[])
{
//Window
SDL_Window *window = NULL;
//Window Surface where things will be shown
SDL_Surface *surface = NULL;
//Inicializar SDL
if(SDL_Init(SDL_INIT_VIDEO) == -1)
{
printf("Failed to initialize SDL2. SDL Error: %s", SDL_GetError());
}
else
{
window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_SHOWN );
if(window == NULL)
printf("Failed to create SDL2 window. SDL Error: %s", SDL_GetError());
else
{
//Fill window with white color
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0xFF, 0xFF, 0xFF));
//Update surface with new changes
SDL_UpdateWindowSurface(window);
//Wait before closing (parameter in miliseconds)
SDL_Delay(4000);
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
You get Segmentation fault because surface is still NULL
This example code taken directly from the SDL wiki (https://wiki.libsdl.org/SDL_FillRect) shows how to create a SDL_Surface before calling SDL_FillRect()
/* Declaring the surface. */
SDL_Surface *s;
/* Creating the surface. */
s = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
/* Filling the surface with red color. */
SDL_FillRect(s, NULL, SDL_MapRGB(s->format, 255, 0, 0));
I just started with SDL and made a small square moving around on a window.
I used DL_GetKeyboardState, and got it moving kind of smoothly. However, just when I start moving it one direction by holding down one key, it moves a bit, stops, then move like I want. This messes up the smoothness. My best guess is that it waits for a doubleclick from the mouse, but im not sure. Any suggestions?
The code:
#include <stdio.h>
#include <SDL.h>
int main(int argc, char * argv[])
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Yelda!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1600, 1200, 0);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
const Uint8 *state;
int run = 1;
int xpos=300;
int ypos=300;
int projectileYPos;
int projectileXPos;
int loop;
int lanceLength = 10;
while(run)
{
while(SDL_PollEvent(&event))
{
state=SDL_GetKeyboardState(NULL);
if(state[SDL_SCANCODE_ESCAPE])
run=0;
if(state[SDL_SCANCODE_W])
ypos-=10;
if(state[SDL_SCANCODE_S])
ypos+=10;
if(state[SDL_SCANCODE_A])
xpos-=10;
if(state[SDL_SCANCODE_D])
xpos+=10;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255 ,255);
SDL_Rect rect = {xpos, ypos, 20, 20 };
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
SDL_Delay(20);
}
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
The SDL wiki says that you should use SDL_PumpEvents() to update the keyboard state array.
And indeed, if we
remove the while(SDL_PollEvent(&event)) loop (not its contents) as it's unneeded,
move state=SDL_GetKeyboardState(NULL); before the while(run) loop (the address of the array "will be valid for the whole lifetime of the application", so it always returns the same pointer), and
only call SDL_PumpEvents() inside the loop,
then the movement is smooth.
I just started using SDL2 and I already have a problem.
I want to create a window and paint it in red.
But it remains white, and I don't understand why.
Here is the code :
int main (int argc, char** argv) {
SDL_Window* pWindow = NULL;
pWindow = SDL_CreateWindow("Jeu de la vie", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_SHOWN);
SDL_Surface* pSurface = NULL;
pSurface = SDL_GetWindowSurface(pWindow);
SDL_FillRect(pSurface, NULL, SDL_MapRGB(pSurface->format, 255, 0, 0));
while(1);
SDL_FreeSurface(pSurface);
SDL_DestroyWindow(pWindow);
SDL_Quit();
return EXIT_SUCCESS;
}
There are several issues with your code, I'll try to address most of them.
Initialize SDL
SDL and SDL2 needs to be initialized before you can use it. The way to initialize SDL is the following function.
int SDL_Init(Uint32 flags)
Where flags can be a different value for different subsystems. Use SDL_INIT_EVERYTHING, to initialize everything.
int SDL_Init(SDL_INIT_EVERYTHING)
Read more about it here..
Initialize SDL_Window and SDL_Renderer
SDL_Renderer and SDL_Window needs to be set up before you can use them. You already create your window properly, so I won't cover that. Here's how to set up an SDL_Renderer
SDL_Renderer* SDL_CreateRenderer(SDL_Window* window,
int index,
Uint32 flags)
index defines what driver to use. Set it to -1 to use the first driver that supports the other arguments.
flags are used to make the rendering optimized, software rendiring, prevent vsync, etc.. Set it to SDL_RENDERER_ACCELERATED.
Read more about SDL_CreateRenderer here.
Mixing SDL and SDL2
SDL_Surface is primarily something used in SDL, not SDL2. SDL2_image, SDL2_ttf etc still used SDL_Surface, but they are converted into an SDL_Texture before they can be used.
SDL_FillRect(...); is also mostly a SDL thing. But as stated above, the SDL_Surface can be used, but you need to convert it to an SDL_Texture first :
SDL_Texture* SDL_CreateTextureFromSurface(SDL_Renderer* renderer,
SDL_Surface* surface)
Read more here.
And use
int SDL_RenderCopy(SDL_Renderer* renderer,
SDL_Texture* texture,
const SDL_Rect* srcrect,
const SDL_Rect* dstrect)
To render it, read more here.
Infinite loop ( while(1); )
You REALLY shouldn't do this, it'll just loop forever. Use SDL_Delay( 5000 ); to pause for 5000msec or 5 seconds.
A simpler way
You can use
int SDL_RenderDrawRect(SDL_Renderer* renderer,
const SDL_Rect* rect)
To draw a rect.
You should use
int SDL_SetRenderDrawColor(SDL_Renderer* renderer,
Uint8 r,
Uint8 g,
Uint8 b,
Uint8 a)
To set the color of what you are drawing, use
int SDL_RenderClear(SDL_Renderer* renderer)
After which you call your SDL_RenderDrawRect()
Up until this point, everything has been drawn "behind the scenes." To render it to the screen, use
void SDL_RenderPresent(SDL_Renderer* renderer)
Example
#include <SDL2/SDL.h>
int main (int argc, char** argv)
{
SDL_Window* window = NULL;
window = SDL_CreateWindow
(
"Jeu de la vie", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_SHOWN
);
// Setup renderer
SDL_Renderer* renderer = NULL;
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED);
// Set render color to red ( background will be rendered in this color )
SDL_SetRenderDrawColor( renderer, 255, 0, 0, 255 );
// Clear winow
SDL_RenderClear( renderer );
// Creat a rect at pos ( 50, 50 ) that's 50 pixels wide and 50 pixels high.
SDL_Rect r;
r.x = 50;
r.y = 50;
r.w = 50;
r.h = 50;
// Set render color to blue ( rect will be rendered in this color )
SDL_SetRenderDrawColor( renderer, 0, 0, 255, 255 );
// Render rect
SDL_RenderFillRect( renderer, &r );
// Render the rect to the screen
SDL_RenderPresent(renderer);
// Wait for 5 sec
SDL_Delay( 5000 );
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
Result
You can read more about SDL2 on my blog.