SDL image only shows occasionally - c++

The code below is meant to show a picture of a rider in the top left corner of the SDL window. With this code the image occasionally does appear as intended, but most of the time when I run the program I just get a black window. Any idea why?
#include "Game.h"
#include <iostream>
bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullScreen)
{
int flags = 0;
if (fullScreen)
{
flags = SDL_WINDOW_FULLSCREEN;
}
//attempt to initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING)==0) {
std::cout << "SDL init success \n";
//init the window
m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if (m_pWindow !=0) // window init successful
{
std::cout << "Window creation successful\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer !=0) // renderer init success
{
std::cout << "renderer creation successful\n";
SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);
}
else
{
std::cout << "renderer init failed!\n";
return false; // render init failed
}
}
else
{
std::cout << "Window init failed!\n";
return false; //window init failed
}
}
else
{
std::cout << "SDL init failed!\n";
return false; // SDL init failed
}
std::cout << "Init success\n";
m_bRunning = true; // everything init-d successfully, main game loop running
SDL_Surface* pTempSurface = SDL_LoadBMP("rider.bmp");
if(!pTempSurface)
{
std::cout << "Error, tempsurface is null";
}
m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
SDL_FreeSurface(pTempSurface);
SDL_QueryTexture(m_pTexture, NULL, NULL, &m_sourceRectangle.w, &m_sourceRectangle.h);
m_destinationRectangle.x = m_sourceRectangle.x = 0;
m_destinationRectangle.x = m_sourceRectangle.x = 0;
m_destinationRectangle.h = m_sourceRectangle.h;
m_destinationRectangle.w = m_sourceRectangle.w;
return true;
}
void Game::render()
{
SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
SDL_RenderCopy(m_pRenderer, m_pTexture, &m_sourceRectangle, &m_destinationRectangle);
SDL_RenderPresent(m_pRenderer);
}
void Game::handleEvents()
{
SDL_Event event;
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
m_bRunning = false;
break;
default:
break;
}
}
}
void Game::clean()
{
std::cout << "cleaning app\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}

Related

Error to pixel manipulation SDL2 c++

i'm trying to create a manual color key with pixel manipulation in SDL2, but when i execute the program, the color key doesn't work, these pixels become white, but not transparent.
I tried to Lock the surface and set the surface blendmode, but doesn't work too.
Code:
// IO includes
#include <iostream>
// String includes
#include <string>
// SDL includes
#include <SDL.h>
#include <SDL_image.h>
// Screen constants
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
using namespace std;
// Window variables
SDL_Window *window = NULL;
SDL_Surface *windowSurface = NULL;
// Image surfaces
SDL_Surface *background = NULL;
SDL_Surface *image = NULL;
// Functions
bool initializeSDL();
SDL_Surface *loadSurfaceFromFile(string path);
void SetColorKey(SDL_Surface *surface, Uint32 color);
bool LoadFiles();
void FreeMemory();
// SDL_main
int main(int argc, char* argv[]){
// Try to initialize and load files
if(initializeSDL() == false){
FreeMemory();
return -1;
}
if(LoadFiles() == false){
FreeMemory();
return -1;
}
// Blit images
SDL_BlitSurface(background, NULL, windowSurface, NULL);
SDL_BlitSurface(image, NULL, windowSurface, new SDL_Rect(70, 277, image->w, image->h));
// Update screen
SDL_UpdateWindowSurface(window);
// Loop
SDL_Event ev;
while(true){
if(SDL_PollEvent(&ev) && ev.type == SDL_QUIT) break;
}
return 0;
}
bool initializeSDL(){
// Try to initialize the video
if( SDL_Init(SDL_INIT_VIDEO) < 0 ){
// Print error
cout << "Error to initialize the video: " << SDL_GetError() << endl;
return false;
}
// Try to create the window
window = SDL_CreateWindow("Surface", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if(window == NULL){
// Print error
cout << "Error to create the window: " << SDL_GetError() << endl;
return false;
}
// Try to initialize PNG format
int imgFlags = IMG_INIT_PNG;
if(! (IMG_Init(imgFlags) &imgFlags) ) return false;
// Get the window surface
windowSurface = SDL_GetWindowSurface(window);
// If everything is fine, return true
return true;
}
SDL_Surface* loadSurfaceFromFile(string path){
// Create a temporary surface
SDL_Surface *tmpSurface = NULL;
// Create an optimized surface
SDL_Surface *optimizedSurface = NULL;
// Try to load the tmpSurface
tmpSurface = IMG_Load(path.c_str());
if(tmpSurface == NULL){
// Print error
cout << "Error to load the image: " << SDL_GetError() << endl;
return NULL;
}
// Try to optimize the surface
optimizedSurface = SDL_ConvertSurface(tmpSurface, windowSurface->format, NULL);
SDL_FreeSurface(tmpSurface); // Free tmpSurface memory
delete tmpSurface; // Delete the tmpSurface
if(optimizedSurface == NULL){
// Print error
cout << "Error to optimize the image: " << SDL_GetError() << endl;
}
return optimizedSurface;
}
void SetColorKey(SDL_Surface *surface, Uint32 color){
Uint32 *pixels = (Uint32*)surface->pixels;
int pixelCount = (surface->pitch/4) * surface->h;
Uint32 transparent = SDL_MapRGBA(image->format, 255, 255, 255, 0);
for(int i=0;i<pixelCount;i++){
if(pixels[i] == color){
pixels[i] = transparent;
}
}
}
bool LoadFiles(){
// Try to load the background
background = loadSurfaceFromFile("background.bmp");
if(background == NULL) return false;
// Try to load the image
image = loadSurfaceFromFile("image.png");
if(image == NULL) return false;
// Set manual color key to image
SetColorKey(image, SDL_MapRGB(image->format, 0, 255, 255));
return true;
}
void FreeMemory(){
SDL_FreeSurface(background);
SDL_FreeSurface(image);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}

SDL not responding after running for a few seconds on linux

I was following the SDL Game development book and I cant even get the first file to work right. Upon the application starting it renders the window and then after a few seconds Linux says the game is not responding and ask me to force quit. This repeats every few seconds if I click wait. One thing I have noticed is that SDL_PollEvent never returns true.I am not sure why things are not working. Here is my code.
Main.cpp
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include "Game.h"
// our Game object
Game* g_game = 0;
int main(int argc, char* argv[]) {
g_game = new Game();
g_game->init("Chapter 1", 100, 100, 640, 480, 0);
while(g_game->running()) {
g_game->handleEvents();
//g_game->update();
g_game->render();
}
g_game->clean();
return 0;
}
Game.h
#ifndef __Game__
#define __Game__
#if !WINDOWS
#include <SDL2/SDL.h>
#else
#include <SDL.h>
#endif
class Game {
public:
Game() {}
~Game() {}
// simply set the running variable to true
bool init(const char* title, int xpos, int ypos, int width, int
height, bool fullscreen);
void render();
void update();
void handleEvents();
void clean();
// a function to access the private running variable
bool running() {
return m_bRunning;
}
private:
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
bool m_bRunning;
};
#endif /* defined(__Game__) */
Game.cpp
#include "Game.h"
#include <iostream>
bool Game::init(const char* title, int xpos, int ypos, int width,
int height, bool fullscreen) {
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "SDL init success\n";
// init the window
int flags = 0;
if(fullscreen) {
flags = SDL_WINDOW_FULLSCREEN;
}
m_pWindow = SDL_CreateWindow(title, xpos, ypos,
width, height, flags);
if(m_pWindow != 0) { // window init success
std::cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0) { // renderer init success
std::cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer,
255,0,255,255);
} else {
std::cout << "renderer init fail\n";
return false; // renderer init fail
}
} else {
std::cout << "window init fail\n";
return false; // window init fail
}
} else {
std::cout << "SDL init fail\n";
return false; // SDL init fail
}
std::cout << "init success\n";
m_bRunning = true; // everything inited successfully, start the main loop
return true;
}
void Game::render() {
SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
SDL_RenderPresent(m_pRenderer); // draw to the screen
}
void Game::clean() {
std::cout << "cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
void Game::handleEvents() {
SDL_Event event;
while(SDL_PollEvent(&event)) {
std::cout << "Checking Events";
switch(event.type) {
case SDL_QUIT:
std::cout << "Quiting";
m_bRunning = false;
break;
default:
break;
}
}
}
Edit:
so I made a minamal version of the code and now i get a new error. The error says "Segmentation Fault (core dumped)". Based on running it to a specific line in debug the error seems to appear at the line that says "SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);" I am not sure what the error is though
Here is the minial code:
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, char** argv) {
if(SDL_Init(SDL_INIT_EVERYTHING) != 0) {
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if(win == NULL) {
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(ren == NULL) {
SDL_DestroyWindow(win);
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
std::string imagePath = "cb.bmp";
SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str());
if(bmp == NULL) {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
if(tex == NULL) {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_FreeSurface(bmp);
SDL_Event e;
bool quit = false;
while(!quit) {
while(SDL_PollEvent(&e)) {
//If user closes the window
if(e.type == SDL_QUIT) {
quit = true;
}
//If user presses any key
if(e.type == SDL_KEYDOWN) {
quit = true;
}
//If user clicks the mouse
if(e.type == SDL_MOUSEBUTTONDOWN) {
quit = true;
}
}
SDL_RenderClear(ren);
SDL_RenderPresent(ren);
}
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
I have compiled and run your minimal code successfully under Linux with SDL 2.0.4. I used a simple image as "cb.bmp".
Try the following :
compile like this : g++ -Wall -ggdb $(sdl2-config --cflags) -o program main.cpp -lSDL2
gdb ./program, then type 'run'
when it crashes, type 'bt' (for backtrace)
copy the output here
My guess is : either the "bmp" file format is not supported or the rendering driver is not supported. try to use :
SDL_CreateRenderer(win, -1, 0);

What Causes SDL_Renderer to be invalid?

I'm trying to make a 2D game where the background is a hockey rink. The error handler said the Render-er didn't initialize thus making the texture not initialize. I know the BMP loads because I don't get an error for that. Don't worry about the camera stuff. The background is supposed to scroll. I just need the background to render. The code may not be the best, but corrections are always appreciated.
#include <SDL/SDL.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int fps = 60;
SDL_Window *window;
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
int x = 0, y = 0;
SDL_Surface *screen;
SDL_Surface *background = SDL_LoadBMP("hockeyrink.bmp");
if(background == NULL)
{
SDL_ShowSimpleMessageBox(0, "Background init error", SDL_GetError(), window);
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
SDL_ShowSimpleMessageBox(0, "Renderer init error", SDL_GetError(), window);
}
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,background);
if(texture == NULL)
{
SDL_ShowSimpleMessageBox(0, "Texture init error", SDL_GetError(), window);
}
const int speed = 5;
SDL_Rect camera;
camera.x = 0;
camera.y = 0;
camera.w = 800;
camera.h = 600;
bool b[2] = {0,0};
Uint32 start;
window = SDL_CreateWindow("", 300, 100, 1024, 800, SDL_WINDOW_OPENGL);
if (window == NULL)
{
cout << ("could not create window: %s/n", SDL_GetError());
return 1;
}
bool running = true;
while (running)
{
start = SDL_GetTicks();
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
running = false;
SDL_DestroyTexture(texture);
SDL_FreeSurface(background);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0]=1;
break;
case SDLK_LEFT:
b[1]=1;
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0]=0;
break;
case SDLK_LEFT:
b[1]=0;
break;
}
break;
}
}
if(b[0])
{
x+=speed;
camera.y+=speed;
if (camera.y > 3000-800)
{
camera.y=0;
}
}
else if(b[1])
{
x-=speed;
camera.y-=speed;
if (camera.y <= 0)
{
camera.y = 2000-800;
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
if(1000/fps>SDL_GetTicks()-start)
{
SDL_Delay(1000/fps-(SDL_GetTicks() - start));
}
}
return 0;
}
When you create renderer, the window pointer does not point to anything(i.e. it is uninitialized).
You must create the window before creating the renderer.
So put the lines:
window = SDL_CreateWindow("", 300, 100, 1024, 800, SDL_WINDOW_OPENGL);
if (window == NULL)
{
cout << ("could not create window: %s/n", SDL_GetError());
return 1;
}
before the line: SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);

Unable to open Image in C++ SDL

So im trying to render an image. This code worked fine before I refactored into seperate classes but i cannot see the problem. The file path for the image also worked before the refactoring however i have not moved the image so it should still be in the same place.
The error i am getting is "Unable to create texture from surface. Error: Couldn't open Images/text.bmp" so im fairly certain its the line of code below that is messing up.
if (!(gTexture->LoadFromFile("Images/text.bmp")))
{
return false;
}
Here is the LoadFromFile function code
bool Texture2D::LoadFromFile(string path)
{
Free();
SDL_Texture* pTexture = NULL;
SDL_Surface* pSurface = IMG_Load(path.c_str());
if (pSurface != NULL)
{
//SDL_SetColorKey(pSurface, SDL_TRUE, SDL_MapRGB(pSurface->format, 0, 0xFF, 0xFF));
pTexture = SDL_CreateTextureFromSurface(mRenderer, pSurface);
if (pTexture == NULL)
{
cout << "Unable to create texture from surface. Error: " << SDL_GetError() << endl;
}
mWidth = pSurface->w;
mHeight = pSurface->h;
SDL_FreeSurface(pSurface);
}
else
{
cout << "Unable to create texture from surface. Error: " << IMG_GetError() << endl;
}
mTexture = pTexture;
return pTexture != NULL;
}
Below is the Source.cpp file:
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include "Constants.h"
#include "Texture2D.h"
#include "Commons.h"
#include <iostream>
#include <string>
using namespace std;
//Globals
SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;
Texture2D* gTexture = NULL;
//prototypes
bool InitSDL();
void CloseSDL();
bool Update();
void Render();
int main(int argc, char* args[])
{
if(InitSDL())
{
bool quit = false;
while(!quit)
{
//gTexture->Render(Vector2D(), SDL_FLIP_NONE, 0);
Render();
quit = Update();
}
}
CloseSDL();
return 0;
}
bool InitSDL()
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
cout << "SDL did not initialise. Error: " << SDL_GetError();
return false;
}
else
{
//ITS ALL GOOD BRO
gWindow = SDL_CreateWindow("Games Engine Creation",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
//DID IT GO?
if (gWindow == NULL)
{
//NUH UH
cout << "Window was not created. Error: " << SDL_GetError();
return false;
}
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
if (gRenderer != NULL)
{
//INITIALISE THAT PNG BBY
int imageFlags = IMG_INIT_PNG;
if (!(IMG_Init(imageFlags) & imageFlags))
{
cout << "SDL_Image could not initialise. Error: " << IMG_GetError();
return false;
}
}
else
{
cout << "Renderer could not be initialised. Error: " << SDL_GetError();
return false;
}
gTexture = new Texture2D(gRenderer);
if (!(gTexture->LoadFromFile("Images/text.bmp")))
{
return false;
}
return true;
}
}
void CloseSDL()
{
SDL_DestroyWindow(gWindow);
gWindow = NULL;
delete gTexture;
gTexture = NULL;
SDL_DestroyRenderer(gRenderer);
gRenderer = NULL;
IMG_Quit();
SDL_Quit();
}
bool Update()
{
SDL_Event e;
SDL_PollEvent(&e);
switch(e.type)
{
case SDL_QUIT:
return true;
break;
case SDL_KEYUP:
switch(e.key.keysym.sym)
{
case SDLK_q:
return true;
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
return true;
break;
}
return false;
}
void Render()
{
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(gRenderer);
gTexture->Render(Vector2D(), SDL_FLIP_NONE, 0);
//SDL_Rect renderLocation = { 0, 0, mWidth, mHeight };
//SDL_RenderCopyEx(mRenderer, mTexture, NULL, &renderLocation, 0, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(gRenderer);
}
A simple way to start debugging is to place the image in the same folder with the executable and show the path as ./image.bmp to see if something is wrong with the path.

Why the game window closes after specific time?

Why the window that created by SDL Game Library are automatically closed after specific time.
I know the reason is SDL_Delay() function, but if not used that function, the game will appear runtime error.
How can I create a window that continuously work without appear in specific period time ?
My code(Simplest code):
SDL_Window *window;
SDL_Renderer *render;
int main(int argc, char* args[]){
if(SDL_Init(SDL_INIT_EVERYTHING) >= 0){
window = SDL_CreateWindow("Simple game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
if(window != 0){
render = SDL_CreateRenderer(window, -1, 0);
}
}else{
return 1;
}
SDL_SetRenderDrawColor(render, 0, 0, 0, 255);
SDL_RenderClear(render);
SDL_RenderPresent(render);
SDL_Delay(3000);
SDL_Quit();
return 0
}
You need to loop forever and call SDL update screen functions. Read LazyFoo tutorials found here: http://lazyfoo.net/SDL_tutorials
Or here a short code to get you started:
#include <iostream>
#include "SDL/SDL.h" // basic SDL
#include <string>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BBP = 32; // bits per-pixel
SDL_Surface* screen = NULL; // display screen
SDL_Event event; // grab events
using namespace std;
bool init() {
// initialize SDL
if(SDL_Init( SDL_INIT_EVERYTHING ) == -1)
return false;
//the screen image
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT,
SCREEN_BBP, SDL_SWSURFACE );
if(!screen) {
cout << "error creating screen" << endl;
return false;
}
//Set the window caption
SDL_WM_SetCaption("Event Test", NULL );
return true;
}
int main(int argc, char* argv[])
{
try
{
// make sure the program waits for a quit
bool quit = false;
cout << "Starting SDL..." << endl;
// Start SDL
if(!init()) {
cout << "initialize error" << endl;
return false;
}
// main loop
while( quit == false )
{
if (SDL_PollEvent(&event))
{
// The x button click
if(event.type == SDL_QUIT)
{
//quit the program
quit = true;
}
}
// Fill the screen white
SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB(
screen->format, 0xFF, 0xFF, 0xFF ) );
//Update screen
if(SDL_Flip(screen) == -1)
return -1;
}
}
catch (exception& e)
{
cerr << "exception caught: " << e.what() << endl;
return -1;
}
return 0;
}