So, I'm making a simple 2D game for mobile, and obviously it's controlled by touchscreen. However, I ran into a problem: when I move my fingers around the screen, SDL_FINGERMOTION event keeps registering for a while even after I put my finger up, and you're basically stuck for a couple of seconds unable to press anything. I have no idea what can cause this, and neither I have an idea how to fix it. Here's my code for a brief idea:
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
using namespace std;
const int SCREEN_WIDTH = 1080;
const int SCREEN_HEIGHT = 1080;
int main()
{
SDL_Window *win = SDL_CreateWindow("something", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_Texture *touchUpTex = IMG_LoadTexture(ren, "tU.png");
SDL_Texture *touchDownTex = IMG_LoadTexture(ren, "tD.png");
SDL_Texture *touchMotionTex = IMG_LoadTexture(ren, "tM.png");
SDL_Event e;
e.type = SDL_FINGERUP;
SDL_Rect rect;
rect.x = 0, rect.y = 0, rect.w = 1080, rect.h = 1080;
while(true)
{
SDL_PollEvent(&e);
if (e.type == SDL_FINGERUP)
SDL_RenderCopy(ren, touchUpTex, NULL, &rect);
else if (e.type == SDL_FINGERDOWN)
SDL_RenderCopy(ren, touchDownTex, NULL, &rect);
else if (e.type == SDL_FINGERMOTION)
SDL_RenderCopy(ren, touchMotionTex, NULL, &rect);
SDL_RenderPresent(ren);
}
return 0;
}
I tried to make an event called e2, so when the first ("e") event registers a finger motion, e2 gets registered instead. It got somewhat better, but I still had an awkward input lag for a split second when I moved my finger on accident.
Related
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, ©_rect);
// We now draw from half the screen onward x position = WIDTH / 2.
copy_rect.x = 400;
SDL_RenderCopy(renderer, red_part, nullptr, ©_rect);
SDL_RenderPresent(renderer);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
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);
}
I am using SDL2 in windowed mode on Windows 7 64bit to create a small game.
I get tearing at the same height of the window despite having VSYNC active. The weird thing is that the movement in itself is fluid, but there is this line, about 50px from the bottom, where tearing is noticeable. It always stays there, without moving or anything.
The weird thing is that if I crate a smaller window, I get tearing at exactly the same height from the bottom.
I tried taking screens of it but it doesn't show the tearing.
I have no idea if this is a problem of SDL2, a problem with Windows, a problem with my pc or a problem in my source file. I have tried looking online for a solution but I could not find anything like this problem.
It is a first for me since I have been playing with a lot of SDL games in the past in windowed mode and none had this problem.
Here is a snippet of the source I have been using:
#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>
const int SCREEN_WIDTH = 400;
const int SCREEN_HEIGHT = 300;
bool init( SDL_Window** window, SDL_Renderer** renderer ) {
SDL_Init(SDL_INIT_VIDEO);
*window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
*renderer = SDL_CreateRenderer(*window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
int flags = IMG_INIT_PNG;
IMG_Init(flags);
return true;
}
void close( SDL_Texture** image, SDL_Window** window ) {
SDL_DestroyTexture( *image );
*image = NULL;
SDL_DestroyWindow( *window );
*window = NULL;
SDL_Quit();
}
int main(int argc, char* argv[]) {
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Texture* image = NULL;
const SDL_Rect rect = { 0, 0, SCREEN_WIDTH, 200 };
SDL_Rect rectImage, rectImageOriginal;
int w, h;
SDL_QueryTexture(image, NULL, NULL, &w, &h);
rectImage = { 0, 0, w, h };
rectImageOriginal = rectImage;
init( window, renderer );
image = IMG_LoadTexture( renderer, path );
while (running) {
[... here I move rectImage ...]
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 200, 0, 0, 255);
SDL_RenderFillRect(renderer, NULL);
SDL_RenderCopy(renderer, image, &rectImageOriginal, &rectImage);
SDL_RenderPresent(renderer);
}
close(&image, &window);
}
Okay, so I've been working on this little bouncing DVD logo thingy and I'm running to it slowly taking up more and more memory. Eventually it ends up taking a whopping 1.4 GB then slows down and crashes. Here is the code, what is wrong with it that causes it to do this?
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2_ttf/SDL_ttf.h>
#include <SDL2_image/SDL_image.h>
// This sets ups the display.
SDL_Window* window = SDL_CreateWindow("DVD Thingy", 100, 100,
800, 600, SDL_WINDOW_SHOWN
| SDL_RENDERER_ACCELERATED
| SDL_RENDERER_PRESENTVSYNC);
SDL_Renderer* screen = SDL_CreateRenderer(window, -1, 0);
void drawText(char text[], int origX, int origY, SDL_Renderer* ren, TTF_Font* font, SDL_Color color) {
SDL_Surface* surfaceMessage = TTF_RenderText_Blended(font, text, color);
SDL_Texture* Message = SDL_CreateTextureFromSurface(ren, surfaceMessage);
int w = surfaceMessage->w;
int h = surfaceMessage->h;
SDL_Rect messageRect = {origX, origY, w, h};
SDL_RenderCopy(ren, Message, NULL, &messageRect);
SDL_DestroyTexture(Message);
}
int main() {
// This initializes the font class.
srand(time(NULL));
TTF_Init();
int skyboxColor = 240;
bool done = false;
int dirX = 1, dirY = 1;
TTF_Font* font = TTF_OpenFont("./Impact.ttf", 18);
TTF_SetFontOutline(font, 1);
int dvdX = rand() % 800, dvdY = rand() % 600-20;
SDL_Color white = {255, 255, 255};
SDL_Event event;
while (!done) {
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
SDL_Quit();
return 0;
default:
break;
}
}
dvdX += dirX;
dvdY += dirY;
if (dvdX > 770) {
dirX = -1;
}
if (dvdX < 0) {
dirX = 1;
}
if (dvdY < -3) {
dirY = 1;
}
if (dvdY > 580) {
dirY = -1;
}
SDL_SetRenderDrawColor( screen, 0, 0, 0, 255);
SDL_RenderClear(screen);
drawText("DVD", dvdX, dvdY, screen, font, white);
SDL_RenderPresent(screen);
SDL_Delay (1/1000 * 60);
}
return 0;
}
It would appear that in the drawText() function you are creating a new SDL_Surface by means of a call to TTF_RenderText_Blended().
You must ensure to free this surface when you are finished with it, which would appear to be at the end of the function it is created in. You already destroy the texture which you create from the surface so all you need to add is one line after that:
SDL_DestroyTexture(Message);
SDL_FreeSurface(surfaceMessage); <- Free the surface
As drawText() was being called constantly in the main while loop, it was bloating memory with SDL_Surfaces.
Just one other point, as you don't seem to be changing the text from "DVD" you could create the texture once and then just draw it where ever you need to. This would be much more efficient than creating, drawing and then destroying every single drame.
I recently started programming with SDL and I've been following some tutorials on gamedevgeek and lazyfoo. I got to show images on the screen, but when I tried to move them I realized the screen was not updating correctly, making the sprite leave a trace, like in this image:
As you can see, the sprite started out in the top left corner, and it left a trace throughout its path to the bottom right.
Some info that can help:
I'm using a raspberry pi with raspbian.
I'm using SDL 1.2.
What have I tried:
I tried changing the last parameter of SDL_SetVideoMode to SDL_HWSURFACE, SDL_SWSURFACE, SDL_DOUBLEBUF, SDL_FULLSCREEN
I tried to switch between SDL_Flip(screen) and SDL_UpdateRect(screen, 0, 0, 0, 0); when I changed the parameter of SDL_SetVideoMode.
Here is my code.
#include "SDL.h"
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
int main ( int argc, char *argv[] )
{
SDL_Surface *screen, *temp, *sprite;
SDL_Rect rcSprite;
SDL_Event event;
Uint8 *keystate;
int colorkey, gameover;
SDL_Init(SDL_INIT_VIDEO);
// screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SDL_DOUBLEBUF | SDL_FULLSCREEN);
// screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SDL_HWSURFACE);
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SDL_SWSURFACE);
temp = SDL_LoadBMP("sprite.bmp");
sprite = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);
colorkey = SDL_MapRGB(screen->format, 255, 0, 255);
SDL_SetColorKey(sprite, SDL_SRCCOLORKEY | SDL_RLEACCEL, colorkey);
rcSprite.x = 0;
rcSprite.y = 0;
gameover = 0;
while (!gameover)
{
if (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
gameover = 1;
break;
}
break;
}
}
keystate = SDL_GetKeyState(NULL);
if (keystate[SDLK_LEFT] )
rcSprite.x -= 2;
if (keystate[SDLK_RIGHT] )
rcSprite.x += 2;
if (keystate[SDLK_UP] )
rcSprite.y -= 2;
if (keystate[SDLK_DOWN] )
rcSprite.y += 2;
SDL_BlitSurface(sprite, NULL, screen, &rcSprite);
// SDL_Flip(screen);
SDL_UpdateRect(screen, 0, 0, 0, 0);
}
SDL_FreeSurface(sprite);
SDL_FreeSurface(grass);
SDL_Quit();
return 0;
}
What am I doing wrong? Needless to say that I'm very new to the linux world, as well as the raspberry pi's, as well as SDL's :)
You call to SDL_SetVideoMode() is incorrect, your code should not compile, enable your compiler warnings.
The function takes four arguments:
SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);
so it should be something like:
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32 , SDL_SWSURFACE);
if( !screen )
//print your warning and exit.
Also your screen surface is never cleared and the sprite remains. Either redraw the entire screen with sprites or clear the surface
SDL_FillRect( screen , NULL , 0x0 ) ; //fills the entire surface with 0x0 .