Window Changes Color Over Time In SDL2 - c++

I've created a window in SDL2 that opens in the color red. I need the window to change color after a few seconds and continue to do so as long as the window is open. So the window may open red, stay for five seconds then become green for five seconds then become blue for five seconds then loop back to red and begin the whole process again.
int WindowOpen() {
bool quit = false;
SDL_Window *window; // Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"My SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Event* MainEvent = new SDL_Event();
SDL_RenderClear(renderer);
// Up until now everything was drawn behind the scenes.
// This will show the new, red contents of the window.
SDL_RenderPresent(renderer);
// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);//red. Was testing to see if window would open red and change to green then blue but this doesn't work.
//SDL_Delay(3000);
//SDL_SetRenderDrawColor(renderer, 300, 150, 0, 155);//green
//SDL_Delay(3000);
//SDL_SetRenderDrawColor(renderer, 129, 150, 500, 105);//blue
while (quit == false && MainEvent->type != SDL_QUIT) { //While quit is false, run window and renderer.
SDL_PollEvent(MainEvent);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
// The window is open: could enter program loop here (see SDL_PollEvent())
//SDL_Delay(3000); // Pause execution for 3000 milliseconds, for example
// Close and destroy the window
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
delete MainEvent;
// Clean up
SDL_Quit();
}

SDL_SetRenderDrawColor is just setting the colour the renderer would paint, if you asked it to. To fill the back buffer with that colour you should follow it up with SDL_RenderClear. With the back buffer filled, to then draw it on the screen you need to call SDL_RenderPresent.
while (quit == false && MainEvent->type != SDL_QUIT) { //While quit is false, run window and renderer.
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);//red. Was testing to see if window would open red and change to green then blue but this doesn't work.
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
SDL_SetRenderDrawColor(renderer, 300, 150, 0, 155);//green
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
SDL_SetRenderDrawColor(renderer, 129, 150, 500, 105);//blue
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
SDL_PollEvent(MainEvent);
}
Changing your main loop to something like that will do similar to what you want, but the delay is three seconds. Also, this way your main loop will take 9 seconds to execute, which means event handling for quit could take up to 9 seconds. This isn't very good, but fixing it is left as an exercise for the reader.

Related

Rectangle in sdl2 sets colour for entire screen

I know there are already questions like this on SO but I am new to SDL2 and I have had a look at some tutorials to draw a rectangle and I have had a look at some questions here as well. With the current code below I cannot draw a rectanlge onto the window as it doesn't appear I have also tried to clear the window after the rectangle is meant to be drawn this just sets the entire window to that colour.
#include <iostream>
#include <SDL2\SDL.h>
int main(int argc, char** argv){
SDL_Window* window;
window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer* render;
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
bool close = false;
SDL_Event event;
while (close == false){
while (SDL_PollEvent(&event)){
if (event.type == SDL_QUIT){
close = true;
}
}
//set colour
SDL_SetRenderDrawColor(render, 255, 0, 0, 255);
SDL_RenderClear(render);
SDL_Rect rect;
rect.x, rect.y, rect.h, rect.w = 50, 50, 50, 50;
SDL_SetRenderDrawColor(render, 0, 0, 255, 255);
SDL_RenderFillRect(render, &rect);
//SDL_RenderClear(render); <-- If this is uncommented it clears the screen to blue.
SDL_RenderPresent(render);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(render);
SDL_Quit();
}
This is mean't to draw a blue rectangle onto a red window but I only get the red window and clearing the renderer only set's the window blue. Why does this rectangle not draw? If it is drawing then how come the colour of it ahsnt changed so it doesn't blend in with the background.
I have used these questions to help me get this far:
How to draw a rectangle in SDL 2 and what exactly is a renderer
SDL2 Wont draw Rectangles Correctly
https://dev.to/noah11012/using-sdl2-drawing-rectangles-3hc2
Your issue seems to be with the rect.x, rect.y, rect.h, rect.w = 50, 50, 50, 50;
When I changed it to
rect.x = 50;
rect.y = 50;
rect.h = 50;
rect.w = 50;
The program worked

SDL layered rendering system

I would like help with building a layered rendering system in SDL2.
I have a first layer containing a map of Paris with its roads.
I need to draw a line between two points on this map - the problem occurs when the before state of this line does not disappear.
I need to draw this line over the map and keep this.
How do I make s a system to save the map state whithout any overlaid lines drawn, and such that frame by frame I can show the map with the new state of the line overlaid on top of this?
Solved, below an example !! Thank you all
SDL_Window *window;
SDL_Renderer *render;
SDL_Texture *map; //map texture (my layer)
window = SDL_CreateWindow("Test window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
map = SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 640, 480); //Creating a texture
/*Map is a red background stored in map texture*/
SDL_SetRenderDrawColor(render, 255, 0, 0, 255);
SDL_SetRenderTarget(render, map);
SDL_RenderClear(render);
SDL_SetRenderTarget(render, NULL);
/*Seting the line color*/
SDL_SetRenderDrawColor(render, 0, 255, 0, 255);
/*Coping the map texture to the render and drawing a green line on top of this*/
SDL_RenderCopy(render, map, NULL, NULL);
SDL_RenderDrawLine(render, 0, 0, 640, 480);
SDL_RenderPresent(render);
SDL_Delay(2000);
/*Another line*/
SDL_RenderCopy(render, map, NULL, NULL);
SDL_RenderDrawLine(render, 0, 480, 640, 0);
SDL_RenderPresent(render);
SDL_Delay(2000);
SDL_DestroyWindow(window);
SDL_DestroyRenderer(render);
SDL_Quit();

Showing a video using two textures SDL2

I need to build an interface where on the left side of the screen shows part of one streaming video and the right side the other part. Something like this https://www.youtube.com/watch?v=fSPXpdVzamo
The video streaming is saved on a memory buffer that is being loaded on a texture. My question is how to render just the half of the texture, I've bee trying using SDL_Rect but nothing happens.
This is the relevant part of my code:
SDL_UpdateTexture(texture, NULL, buffer_start, fmt.fmt.pix.width * 2);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
If I try something like this, it doesn't work:
SDL_UpdateTexture(texture, NULL, buffer_start, fmt.fmt.pix.width * 2);
SDL_Rect someRect;
someRect.x = 0;
someRect.y = 0;
someRect.w = 1500;
someRect.h = 3000;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, &someRect);
SDL_RenderPresent(renderer);
Any advice would be great!
Without you posting a MCVE is hard to know where you went wrong. My guess is your x position is wrong. Here is an example where I show how to draw 2 images in the fashion of your video.
Green image: https://i.imgur.com/yaOG8Ng.png
Red image: https://i.imgur.com/faKKShU.png
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#define HEIGHT 600
#define WIDTH 800
using namespace std;
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Red Green", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
bool quit = false;
SDL_Event event;
SDL_Texture *green_part = IMG_LoadTexture(renderer, "Green400x600.png");
SDL_Texture *red_part = IMG_LoadTexture(renderer, "Red400x600.png");
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
SDL_RenderClear(renderer);
SDL_Rect copy_rect{0, 0, 400, 600};
SDL_RenderCopy(renderer, green_part, nullptr, &copy_rect);
// We now draw from half the screen onward x position = WIDTH / 2.
copy_rect.x = 400;
SDL_RenderCopy(renderer, red_part, nullptr, &copy_rect);
SDL_RenderPresent(renderer);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}

Change background of SDL2 window?

I can create a SDL2 window but I don't know how to change background color of this window.
My code:
#include "SDL.h"
SDL_Window *window;
void main()
{
window = SDL_CreateWindow("TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Delay(3000);
}
How can I change background color of this window to black?
You should set drawing colour with SDL_SetRenderDrawColor and then use SDL_RenderClear:
(code comes directly from SDL wiki)
int main(int argc, char* argv[])
{
SDL_Window* window;
SDL_Renderer* renderer;
// Initialize SDL.
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return 1;
// Create the window where we will draw.
window = SDL_CreateWindow("SDL_RenderClear",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
512, 512,
0);
// We must call SDL_CreateRenderer in order for draw calls to affect this window.
renderer = SDL_CreateRenderer(window, -1, 0);
// Select the color for drawing. It is set to red here.
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
// Clear the entire screen to our selected color.
SDL_RenderClear(renderer);
// Up until now everything was drawn behind the scenes.
// This will show the new, red contents of the window.
SDL_RenderPresent(renderer);
// Give us time to see the window.
SDL_Delay(5000);
// Always be sure to clean up
SDL_Quit();
return 0;
}
If you do not use SDL2 renderer you can do this:
Just call:
SDL_GL_SwapWindow(window);
After :
SDL_GL_MakeCurrent(window, context);
That's all! Now you have a black screen.
#include <SDL2/SDL.h>
#include <iostream>
using namespace std;
int main(){
int width=512, height=512;
SDL_Window *window=SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE);
if(window==NULL)
cout << "There was an error while initializing the window" << endl << SDL_GetError << endl;
SDL_Event event;
bool running=true;
while(running){
while(SDL_PollEvent(&event)){
if(event.type==SDL_QUIT){
running=false;
break;
}
}
SDL_GetWindowSize(window, &width, &height);
SDL_Surface *surface=SDL_GetWindowSurface(window);
Uint32 skyblue=SDL_MapRGB(surface->format, 65,193,193);
SDL_FillRect(surface, NULL, skyblue);
SDL_UpdateWindowSurface(window);
}
SDL_DestroyWindow(window);
SDL_Quit();
}
Note, none of these solutions work properly with OpenGL. The question was how to init the window with predefined color, not how to paint the first frame. There's still a blink of white color before the first frame is painted.
Try this one :
SDL_Window *wind;
SDL_Surface *windSurface = NULL
void main()
{
wind = SDL_CreateWindow("TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
windSurface = SDL_GetWindowSurface(wind);
SDL_FillRect(windSurface, NULL, SDL_MapRGB(windSurface->format, 240, 200, 112));
SDL_UpdateWindowSurface(wind);
SDL_Delay(3000);
}

SDL: Fullscreen translucent background

I'm trying to write a program that has a translucent background covering the whole screen. After some research it appeared that SDL would be the way to go.
I've written the code to create a full screen window with a background whose alpha is equal to 100 (out of 255), but for some reason it just draws the solid colour. What have I done wrong?
// Initialise SDL
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
this->throwSDLError("SDL_Init Error");
}
// Create the window and renderer
if (SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &(this->window), &(this->renderer)) != 0) {
this->throwSDLError("Could not create the window and renderer");
}
// Set the blend mode to specify how the alpha channel is used
if (SDL_SetRenderDrawBlendMode(this->renderer, SDL_BLENDMODE_BLEND) != 0) {
this->throwSDLError("Could not set render draw blend mode");
}
// Set the colour to draw
if (SDL_SetRenderDrawColor(this->renderer, 200, 200, 200, 100) != 0) {
this->throwSDLError("Could not set the drawing colour");
}
// Clear the screen using the colour
if (SDL_RenderClear(this->renderer) != 0) {
this->throwSDLError("Could not render the screen");
}
// Present the rendered screen
SDL_RenderPresent(this->renderer);
On Windows, you can create a transparent window by using SetLayeredWindowAttributes to chroma-key the background color from a borderless SDL window.
Code:
// SDL window with transparent background v1.2
#include <SDL.h>
#include <SDL_syswm.h>
#include <Windows.h>
// Makes a window transparent by setting a transparency color.
bool MakeWindowTransparent(SDL_Window* window, COLORREF colorKey) {
// Get window handle (https://stackoverflow.com/a/24118145/3357935)
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version); // Initialize wmInfo
SDL_GetWindowWMInfo(window, &wmInfo);
HWND hWnd = wmInfo.info.win.window;
// Change window type to layered (https://stackoverflow.com/a/3970218/3357935)
SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
// Set transparency color
return SetLayeredWindowAttributes(hWnd, colorKey, 0, LWA_COLORKEY);
}
int main(int argc, char** argv) {
// Get resolution of primary monitor
int desktopWidth = GetSystemMetrics(SM_CXSCREEN);
int desktopHeight = GetSystemMetrics(SM_CYSCREEN);
SDL_Window* window = SDL_CreateWindow("SDL Transparent Window",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
desktopWidth, desktopHeight, SDL_WINDOW_BORDERLESS);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// Set background color to magenta and clear screen
SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
SDL_RenderClear(renderer);
// Draw blue square in top-left corner
SDL_Rect rect1 = {0, 0, 100, 100};
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderFillRect(renderer, &rect1);
// Draw red square in center of the screen
SDL_Rect rect2 = {(desktopWidth-100)/2, (desktopHeight-100)/2, 100, 100};
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, &rect2);
// Add window transparency (Magenta will be see-through)
MakeWindowTransparent(window, RGB(255, 0, 255));
// Render the square to the screen
SDL_RenderPresent(renderer);
// Loop until user quits
bool quit = false;
SDL_Event event;
while (!quit) {
while (SDL_PollEvent(&event) != 0) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Result:
Explanation:
First, create a borderless window with that covers the entire desktop. Choose a solid masking color and use it as your background. (In my case, I used magenta). You can then key-out your masking color with the Win32 API function SetLayeredWindowAttributes.
Any part of the window with this color will be completely see-through. Other windows behind your program can be interacted with as normal. By default, other applications can be moved on top of your borderless window.
If you want your SDL window to always be on top of other windows, you can set the SDL_WINDOW_ALWAYS_ON_TOP flag when creating your window.
See Also
Stack Overflow: Creating a transparent window in C++ Win32
Stack Overflow: How detect current screen resolution?
Microsoft: Layered Windows