When i can access to SDL_Rendrerer after maximizing window? - c

I try to redraw window only when is need, but when window is resize in a hop (for example maximize), SDL_Renderer is not usable in new size some time after action.
Here is my simple example code:
#include <SDL2/SDL.h>
bool redraw = true;
void draw(SDL_Renderer* renderer, SDL_Rect& rect)
{
SDL_SetRenderDrawColor(renderer, 0, 0, 50, 0xFF);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 90, 90, 90, 0xFF);
SDL_RenderDrawLine(renderer, 0, 0, rect.w, rect.h);
SDL_RenderPresent(renderer);
redraw = false;
}
SDL_Rect resize(const SDL_Event& event)
{
int win_w = (int) event.window.data1;
int win_h = (int) event.window.data2;
SDL_Rect rect = {0, 0, win_w, win_h};
redraw = true;
return rect;
}
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Maximize test",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800, 450, 0);
SDL_SetWindowResizable(window, SDL_TRUE);
SDL_Renderer* renderer = SDL_CreateRenderer(
window, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
bool running = true;
SDL_Event event;
SDL_Rect rect = {0, 0, 800, 450};
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_RESIZED:
rect = resize(event);
break;
}
break;
}
if (redraw) {
draw(renderer, rect);
}
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
return 0;
}
At first, I try to get new renderer size SDL_GetRendererOutputSize in same result like getting size from event.
When I try to resize window with typical mouse motion actions, it works fine. But maximize or window manager resizing to one screen side does not work.
I try to use different event like SDL_WINDOWEVENT_SIZE_CHANGED, but with same result.
And yes, normally, I checks all SDL calls, with SDL_RenderDrawLine but without any errors.

Related

Cannot get SDL_SetTextureColorMod to work

I am trying to change the color of the image displayed. The image contains characters in black and I want to display them in red. So I am trying to use SDL_SetTextureColorMod but it seems I am doing it wrong since the image rendered is still black. Does someone see the problem with my code?
#include "SDL.h"
#include <stdio.h>
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window;
SDL_Renderer *renderer;
SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer);
SDL_Surface *surface = SDL_LoadBMP("font.bmp");
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
int keep_going = 1;
while (keep_going) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
keep_going = 0;
}
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
int ret = SDL_SetTextureColorMod(texture, 255, 0, 0);
if(ret != 0){
printf("%s",SDL_GetError());
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_Quit();
return 0;
}
The image I'm using:

SDL2: Why a figure "blinks"?

I'm trying to move a square in a rectangle in SDL, but when i launch it, the rectangle and the square "blinks" until I move the square with up, left, right or down. When the square moves, the rectangle stop blinking and only the square keeps blinking. How can i move it without the blink?
Edit: The problem was that i put SDL_RenderPresent twice after the main loop. Thanks for your help.
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <SDL2/SDL_image.h>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 500;
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
bool out = false;
SDL_Event event;
SDL_Rect grid;
grid.x = 25;
grid.y = 25;
grid.w = 300;
grid.h = 450;
SDL_Rect square;
square.x = 175;
square.y = 25;
square.w = 25;
square.h = 25;
//Main loop
while (out==false){
while (SDL_PollEvent(&event)){
if (event.type==SDL_QUIT){out=true;}
else if (event.type==SDL_KEYDOWN){
// Keys
switch (event.key.keysym.sym){
case SDLK_m:
out=true;
break;
case SDLK_LEFT:
square.x-=25;
SDL_RenderPresent(renderer);
break;
case SDLK_RIGHT:
square.x+=25;
SDL_RenderPresent(renderer);
break;
default:
break;
}
}
}
SDL_SetRenderDrawColor(renderer,0,255,0,0);
SDL_RenderFillRect(renderer, &grid);
SDL_RenderPresent(renderer);
SDL_SetRenderDrawColor(renderer,255,0,0,255);
SDL_RenderFillRect(renderer,&square);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
As #HolyBlackCat pointed out, you should only call SDL_RenderPresent() once per frame, not once per shape or keypress:
#include <SDL.h>
#include <SDL_image.h>
#include <stdbool.h>
int main()
{
SDL_Init( SDL_INIT_VIDEO );
SDL_Window* window = SDL_CreateWindow(
"",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
500,
SDL_WINDOW_OPENGL );
SDL_Renderer* renderer = SDL_CreateRenderer(
window,
-1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
bool out = false;
SDL_Event event;
SDL_Rect grid;
grid.x = 25;
grid.y = 25;
grid.w = 300;
grid.h = 450;
SDL_Rect square;
square.x = 175;
square.y = 25;
square.w = 25;
square.h = 25;
//Main loop
while( out == false )
{
while( SDL_PollEvent( &event ) )
{
if( event.type == SDL_QUIT )
{
out = true;
}
else if( event.type == SDL_KEYDOWN )
{
// Keys
switch( event.key.keysym.sym )
{
case SDLK_m:
out = true;
break;
case SDLK_LEFT:
square.x -= 25;
break;
case SDLK_RIGHT:
square.x += 25;
break;
default:
break;
}
}
}
SDL_SetRenderDrawColor( renderer, 0, 255, 0, 0 );
SDL_RenderFillRect( renderer, &grid );
SDL_SetRenderDrawColor( renderer, 255, 0, 0, 255 );
SDL_RenderFillRect( renderer, &square );
SDL_RenderPresent( renderer );
}
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
SDL_Quit();
return 0;
}

Why am I getting a spurious white pixel when I render a texture in SDL?

I'm using SDL2 to draw some stuff on screen. Here is some code:
#include <SDL.h>
void main()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 500, 500, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Texture *texture;
{
SDL_Surface *window_surface = SDL_GetWindowSurface(window);
Uint32 pixel_format = window_surface->format->format;
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, 48, 48, 8, pixel_format);
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
SDL_FreeSurface(window_surface);
}
SDL_Rect target_rectangle;
target_rectangle.x = 100;
target_rectangle.y = 100;
target_rectangle.w = 48;
target_rectangle.h = 48;
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDrawLine(renderer, 0, 50, 50, 0);
SDL_RenderCopy(renderer, texture, 0, &target_rectangle);
SDL_RenderPresent(renderer);
SDL_Event event;
while(1)
{
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
return;
break;
}
}
SDL_Delay(10);
}
}
The code creates some dummy blank texture texture. I get the same behavior with a texture loaded from a bitmap file. These lines are the important ones:
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDrawLine(renderer, 0, 50, 50, 0);
SDL_RenderCopy(renderer, texture, 0, &target_rectangle);
SDL_RenderPresent(renderer);
So draw a line somewhere in white pixels, and then copy the dummy texture to the screen, and display it all. When I do this, I get a white pixel at the bottom right of the texture.
As I said, I also get this when the texture comes from a bitmap using code like this:
SDL_Surface *bitmap_surface = SDL_LoadBMP("test.bmp");
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, bitmap_surface);
SDL_FreeSurface(bitmap_surface);

C SDL VS Code image is not displaying

I have recently started learning game programming in C. I am using a virtual studio code on linux Ubuntu, and image star.png is not displaying on the screen, there are no errors or problems reported by vs code. I have tried reinstalling sdl2-dev and sdl2-image-dev libraries. Maybe it is a problem with SDL, or maybe with my code (it was written in 2013).
The code should draw a white ractangl, which i can move around, on a blue screen and place a star in upper left corner of a window. It does everything except placing a star.
The code: (doesn't show "Cannot dinf star.png!" so I guess it is not that)
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
typedef struct
{
int x, y;
short life;
char *name;
}Man;
typedef struct
{
//players
Man man;
//image
SDL_Texture *star;
} GameState;
/////////////////////////////////////////////////////////////////////processEvents
int processEvents(SDL_Window *window , GameState *game)
{
SDL_Event event;
int done = 0;
//Check for events
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_WINDOWEVENT_CLOSE:
{
if (window)
{
SDL_DestroyWindow(window);
window = NULL;
done = 1;
}
}
break;
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
done = 1;
break;
}
}
break;
case SDL_QUIT:
done = 1;
break;
}
}
const Uint8 *state = SDL_GetKeyboardState(NULL);
if(state[SDL_SCANCODE_LEFT])
{
game->man.x -= 1;
}
if(state[SDL_SCANCODE_RIGHT])
{
game->man.x += 1;
}
if(state[SDL_SCANCODE_UP])
{
game->man.y -= 1;
}
if(state[SDL_SCANCODE_DOWN])
{
game->man.y += 1;
}
SDL_Delay(10);
return done;
}
/////////////////////////////////////////////////////////////////////////////////////doRender
void doRedner(SDL_Renderer *renderer, GameState *game)
{
SDL_SetRenderDrawColor(renderer , 0, 0, 255, 255); //blue
//screen clean up into blue
SDL_RenderClear(renderer);
//set color
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Rect rect = {game->man.x, game->man.y, 80, 80};
SDL_RenderFillRect(renderer, &rect);
//draw a star
SDL_Rect starRect = { 50, 50, 64, 64 };
SDL_RenderCopy(renderer, game->star, NULL, &starRect);
SDL_RenderPresent(renderer);
}
/////////////////////////////////////////////////////////////////////////////////////main funkction
int main(int argc, char *argv[])
{
GameState gameState;
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Surface *starSurface = NULL;
SDL_Init(SDL_INIT_VIDEO);
gameState.man.x = 340-40;
gameState.man.y = 240-40;
window = SDL_CreateWindow("Game Widnow",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
0
);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
//load image
starSurface = IMG_Load("star.png");
if(starSurface = NULL)
{
printf("Cannot find star.png!\n\n");
SDL_Quit();
return 1;
}
gameState.star = SDL_CreateTextureFromSurface(renderer, starSurface);
SDL_FreeSurface(starSurface);
int done = 0;
while(!done)
{
//check events
done = processEvents(window, &gameState);
//render
doRedner(renderer, &gameState);
}
SDL_Delay(1000);
//exit game and free memory
SDL_DestroyTexture(gameState.star);
//destroy and close window
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
TL;DR: Your intention is to perform a comparison, but you are using the assignment operator (i.e., =) instead of the comparison operator ==.
The conditional expression in your if statement:
if(starSurface = NULL)
{
...
}
does not check whether starSurface is NULL. The expression starSurface = NULL assigns NULL to starSurface and evaluates to NULL. Therefore, the condition evaluates to false and no error message is displayed.
Instead, you should write (note the double = below):
if (starSurface == NULL)
or just:
if (!starSurface)

SDL and C keyboard or touch event

I'm programming in c4droid but I can't get the touch event to work.
Tried switch or if statement but nothing works im sure rendering is ok because if I delete the switch then its renders normally
Here I the code:
#include <SDL2/SDL.h>
int main()
{
SDL_Window *window = NULL;
window = SDL_CreateWindow("Shooter", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
// Setup renderer
SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED);
// Set render color to red ( background will be rendered in this color )
SDL_SetRenderDrawColor(renderer, 0, 255, 25, 255);
// Clear winow
SDL_RenderClear(renderer);
// Creat a rect at pos ( 50, 50 ) that's 50 pixels wide and 50 pixels
// high.
SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
SDL_Rect r;
r.x = 500;
r.y = 500;
r.w = 50;
r.h = 50;
SDL_Rect e;
e.x = 5;
e.y = 5;
e.w = 50;
e.h = 50;
SDL_Event event;
while(SDL_PollEvent(&event) != 0) {
switch (event.type) {
case SDL_FINGERDOWN :
e.x = e.x + 10;
SDL_RenderFillRect(renderer, &r);
SDL_RenderFillRect(renderer, &e);
SDL_RenderPresent(renderer);
break;
}
}
// Wait for 5 sec
SDL_Delay(50000);
SDL_DestroyWindow(window);
SDL_Quit();
}
You need to make sure to poll the event.
while(true) {
while(SDL_PollEvent(&event) != 0) {
switch (event.type) {
case SDL_FINGERDOWN :
e.x = e.x + 10;
SDL_RenderFillRect(renderer, &r);
SDL_RenderFillRect(renderer, &e);
SDL_RenderPresent(renderer);
break;
// Render rect
}
}
}
Provided event is not NULL, SDL_PollEvent will take the next event from the queue and store it in the SDL_Event that event is pointing at.
Edit: Don't remove the while(true) loop, put this one inside it. Sorry, I probably should have been a bit more clear in the beginning.

Resources