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
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();
}
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);
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);
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 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;
}