I am trying to write a basic game using OpenGL and SDL2 but whenever I run the program the window immediately closes
Window.cpp
#include "Window.h"
#include <GL/glew.h>
Window::Window(const char* title)
{
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 900, 900, SDL_WINDOW_OPENGL);
context = SDL_GL_CreateContext(window);
GLenum status = glewInit();
}
Window::~Window()
{
SDL_DestroyWindow(window);
SDL_GL_DeleteContext(context);
SDL_Quit();
}
void Window::Input()
{
SDL_Event e;
while (true)
{
if (e.type = SDL_QUIT)
{
exit(0);
}
}
}
void Window::Update()
{
SDL_GL_SwapWindow(window);
Input();
}
Window.h
#pragma once
#include <SDL.h>
#include <GL/glew.h>
class Window
{
SDL_Window* window;
SDL_GLContext context;
public:
void Input();
void Update();
Window(const char* title);
~Window();
};
Main.cpp
#include <SDL.h>
#include <GL\glew.h>
#include "Window.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
Window window("Window");
while (true)
{
glClearColor(0, 1, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
window.Update();
}
return 0;
}
When I run the code I get a brief flash of a green window then it immediately crashes. when I remove Input(); from my update function it the window does not crash but it is unresponsive. I have tried to change SDL_PollEVent to SDL_WaitEvent and adding delays to the Input function but nothing works
First thing, you are using an assignment operator when you probably want to check for equivalence:
if (e.type = SDL_QUIT)
Should be:
if (e.type == SDL_QUIT)
Additionally, you have other issues. You declare the SDL_Event e; union just before you test it, but you don't initialise it to any value. Then you go on to loop over that variable waiting for it to be set to quit. Nothing can change the value of that variable, so how will your loop ever exit?
Related
I have a C++ project where I'm initially trying to display a PNG image to the screen.
This is my code.
RenderWindow.hpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
class RenderWindow
{
public:
RenderWindow(const char *p_title, int p_width, int p_height);
void render();
void cleanUp();
private:
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Surface *image = IMG_Load("~/SDL2_Game/images/Green_Tile.png");
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);
};
RenderWindow.cpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include "RenderWindow.hpp"
RenderWindow::RenderWindow(const char* p_title, int p_w, int p_h):window(NULL), renderer(NULL)
{
window = SDL_CreateWindow(p_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, p_w, p_h, SDL_WINDOW_SHOWN);
if (window == NULL) std::cout << "Window failed to init: " << SDL_GetError() << std::endl;
renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);
}
void RenderWindow::render(){
SDL_RenderClear(renderer);
//SDL_Rect dstrect = { 5, 5, 320, 240 };
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
void RenderWindow::cleanUp(){
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
}
main.cpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include "RenderWindow.hpp"
int main(int argc, char** argv){
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cout << "Problem with initialization. " << SDL_GetError() << std::endl;
}
else {
std::cout << "Initialization success!" <<std::endl;
}
if (!IMG_Init(IMG_INIT_PNG)){
std::cout << "Problem with Image initialization " <<SDL_GetError() << std::endl;
}
RenderWindow win("RPG_Game_v_1.0", 800, 600);
win.render();
bool gameRunning = true;
SDL_Event event;
while(gameRunning){
while(SDL_PollEvent(&event)){
if (event.type == SDL_QUIT) gameRunning = false;
}
}
win.cleanUp();
IMG_Quit();
SDL_Quit();
return 0;
}
I'm on a Linux machine.
I compile this with
g++ -g -o game ./*.cpp -lSDL2main -lSDL2 -lSDL2_image
Only a window is displaying. There is no image. I've tried refactoring my code with SDL_BlitSurface() and it does indeed display the PNG image. But why is this code not working? is it due to the fact that I'm using SDL_Texture* and my current system does not have a discrete graphics card?
I think that the call to SDL_CreateTextureFromSurface fails because it is called before SDL_CreateWindow and SDL_CreateRenderer, thereby initializing texture to NULL.
Please move the initizalization of texture (and image) to after window and renderer are initialized.
To further help with such issues, please check if the result of SDL functions != NULL and print SDL_GetError() to get more information about what went wrong.
I'm learning the basics of creating a window using SDL2 by following a tutorial. The code works just fine, and even compiles correctly, however on runtime it gives the error message 'Assertion failure at SDL_RenderClear_REAL'.
I've tried reinstalling SDL2, as well as moving it to the user library folder on my mac, but neither of these fixed the issue
main.cpp
#include "game.hpp"
Game *game = nullptr;
int main() {
game = new Game();
game->init("GUI", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, false);
while (game->running()) {
game->handleEvents();
game->update();
game->render();
}
game->clean();
return 0;
}
game.cpp
#include "game.hpp"
Game::Game(){}
Game::~Game(){}
void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) {
int flags = 0;
if (fullscreen == true) {
flags = SDL_WINDOW_FULLSCREEN;
}
if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "Sub-systems initialized\n";
window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if (window) {
std::cout << "Window created.\n";
}
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
std::cout << "Renderer created\n";
}
isRunning = true;
} else {
isRunning = false;
}
}
void Game::handleEvents() {
SDL_Event event;
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
isRunning = false;
break;
default:
break;
}
}
void Game::update() {
cnt++;
std::cout << cnt << "\n";
}
void Game::render() {
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
void Game::clean() {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
std::cout << "Game cleaned\n";
}
game.hpp
#ifndef game_hpp
#define game_hpp
#include "SDL2/SDL.h"
#include <iostream>
class Game {
public:
Game();
~Game();
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
void handleEvents();
void update();
void render();
void clean();
bool running() { return isRunning; }
private:
int cnt = 0;
bool isRunning;
SDL_Window *window;
SDL_Renderer *renderer;
};
#endif
After narrowing down the code, it seems that the issue is limited to SL_RenderClear. Here's the exact message it produces in the console:
2019-08-20 15:26:15.508900-0500 GUI[26436:7287503] WARN:
Assertion failure at SDL_RenderClear_REAL (/Users/valve/release/SDL/SDL2-2.0.10-source/src/render/SDL_render.c:2235), triggered 1 time:
'renderer && renderer->magic == &renderer_magic'
Program ended with exit code: 42
How can I fix this issue?
EDIT: Added full code to help identify the problem.
A basic "hello world" of creating a window and clearing the color on the screen for SDL requires a few boilerplate initialization steps
Initialize SDL
Create a SDL_Window
Create a SDL_Renderer
After which you can do
SDL_RenderClear and use SDL_RenderDrawColor to set a custom color to make it more obvious that it is properly clearing the Renderer.
Without error checking this would look something like:
SDL_Init(flags);
SDL_Window* window = SDL_CreateWindow("window title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, more_flags);
SDL_SetRenderDrawColor(renderer, red, green, blue, alpha);
SDL_RenderClear(renderer);
Also remember to call SDL_Delay(ms) if you want the program to not immediately close before you get a chance to see the window.
I am currently learning SDL2 and just managed to create a ping pong game. Some friends told me that I should start using classes for managing as an example player1 and player2. I know how to create a class but I do not understand how I would be able to pass SDL_Renderer between classes in order to render an object from within the class to the main.cpp file.
#include "SDL2/SDL.h"
#include "SDL2/SDL_render.h"
#include <iostream>
#include <windows.h>
#include <thread>
#include "player.h"
Player Player; //defining the class
const int WINDOW_WIDTH = 1280;
const int WINDOW_HEIGHT = 720;
int main(int argc, char *args[]) {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window;
SDL_Renderer *renderer;
window = SDL_CreateWindow ("Test",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH,
WINDOW_HEIGHT,
0
);
if (window == NULL) {
std::cout << "Window could not load" << SDL_GetError() << std::endl;
return 0;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
while (running) //running is a bool (true) {
Player.draw();
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
What do I have to do in my player.cpp draw function in order to draw an object on the screen?
Using C++ windows, compiling the code with g++ main.cpp player.cpp -o main.exe -IC:\MinGW\i686-w64-mingw32\include -LC:\MinGW\i686-w64-mingw32\lib -lmingw32 -lSDL2main -lSDL2
In main.cpp
Player.draw(renderer)
(presuming you are using the same code as above, just pass "renderer" to the Player.draw() function.)
In player.h
class Player {
public:
void draw(SDL_Renderer *renderer)
};
In player.cpp
void Player::draw(SDL_Renderer *renderer) {
SDL_Rect object;
object.x = 0;
object.y = 0;
object.h = 10;
object.w = 10;
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDrawRect(renderer, &object);
SDL_RenderFillRect(renderer, &object);
}
// will draw a white box with at position (0,0)
I believe this is a simple way to do it
I have recently started a game project in C++ using SDL2. I have created a class for the Game and included an init function which initializes SDL and creates a window. My code complies normally with 0 errors and warnings. However, when I run the executable file, I am not able to terminate the program nor a window appears.
My Code:
game.cc
#include "Game.hh"
#include <iostream>
using namespace std;
// Constructing Funtions
Game::Game()
{}
Game::~Game()
{}
// Initializing Function
void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{
int flags = 0;
// Check to see if Fullscreen Mode has been called
if(fullscreen)
flags = SDL_WINDOW_FULLSCREEN;
if(SDL_Init(SDL_INIT_EVERYTHING) == 1) {
cout << "Initialization Complete" << endl;
// Create the Window
window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
// Create the Renderer
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
}
// Set Is Running to True
isRunning = true;
} else {
isRunning = false;
}
}
// Looping Funtions
void Game::eventHandler()
{
// Initialize EventHandler & Get Event Type
SDL_Event event;
SDL_PollEvent(&event);
// Process Events
switch (event.type) {
case SDL_QUIT:
isRunning = false;
break;
default:
break;
}
}
void Game::update()
{}
void Game::render()
{
// Clear Renderer
SDL_RenderClear(renderer);
// Render Shit
SDL_RenderPresent(renderer);
}
void Game::clean()
{
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
cout << "Game Quit Successfuly" << endl;
}
bool Game::running()
{
return isRunning;
}
Game.hh
#ifndef GAME_HH
#define GAME_HH
#include "SDL.h"
class Game {
public:
// Constructor and Deconstructor
Game();
~Game();
// Initializing Functions
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
// Looping Commands
void eventHandler();
void update();
void render();
void clean();
// Application Running Checker
bool running();
private:
bool isRunning;
SDL_Window* window;
SDL_Renderer* renderer;
};
#endif
And finally main.cc
#include <iostream>
#include "Game.hh"
Game *game = nullptr;
int main()
{
game = new Game;
game->init("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, false);
do {
game->eventHandler();
game->update();
game->render();
} while(game->running());
game->clean();
}
Any Ideas?
EDIT: found a fix to the issue, I made the public function running return the private isRunning variable. However, now the issue is that the code returns "Game Quit Successfully" w/out initiating anything...
Today I started a C++/SDL2 Snake clone, and I've been looking for ways to make my code neater, -particularly with classes. I tried to put all the SDL code used for the window/display in a class. When I run the code, the window closes instantly. From the error tests I set up in display.cpp, it also tells me through the console that SDL_UpdateWindowSurface() (in display.update()) is always returning -1. Why does this happen when I rearrange my code like this?
With this code I load an image in main() and display it through my class' function applySurface(). The idea is to have classes/objects for the game's grid/board, the snake, etc., -each calling applySurface() for their own images. Feel free to tell me if this is a bad idea altogether.
main.cpp:
#include <SDL.h>
#include "display.h"
SDL_Event event;
SDL_Surface* image = nullptr;
int main(int argc, char* args[])
{
Display display;
display.loadImage("image.bmp");
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
return false;
bool quit = false;
while (!quit)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
quit = true;
}
display.applySurface(0, 0, image, display.windowSurface);
display.update();
}
SDL_FreeSurface(image);
SDL_Quit();
return 0;
}
display.h:
#pragma once
#include <SDL.h>
#include <string>
#include <iostream>
class Display
{
public:
SDL_Window* window;
SDL_Surface* windowSurface;
Display();
SDL_Surface *loadImage(std::string fileName);
void applySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = nullptr);
void update();
~Display();
private:
const int WINDOW_WIDTH = 612;
const int WINDOW_HEIGHT = 632;
const int SCREEN_BPP = 2;
};
display.cpp:
#pragma once
#include "display.h"
Display::Display()
{
window = SDL_CreateWindow("Snake", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
std::cout << "Error: SDL_CreateWindow failed." << std::endl;
windowSurface = SDL_GetWindowSurface(window);
}
SDL_Surface* Display::loadImage(std::string fileName)
{
SDL_Surface* loadedImage = NULL;
SDL_Surface* optimizedImage = NULL;
loadedImage = SDL_LoadBMP(fileName.c_str());
if (loadedImage != NULL)
{
optimizedImage = SDL_ConvertSurface(loadedImage, windowSurface->format, 0);
SDL_FreeSurface(loadedImage);
if (optimizedImage != NULL)
SDL_SetColorKey(optimizedImage, SDL_TRUE, SDL_MapRGB(optimizedImage->format, 255, 255, 255));
}
return optimizedImage;
}
void Display::applySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface(source, clip, destination, &offset);
}
void Display::update()
{
if (SDL_UpdateWindowSurface(window) == -1)
std::cout << "Error: SDL_UpdateWindowSurface() failed." << std::endl;
}
Display::~Display()
{
SDL_FreeSurface(windowSurface);
windowSurface = NULL;
SDL_DestroyWindow(window);
window = NULL;
}
This is a valid use of classes to structure your code. SDL_Init needs to come before any other SDL functions, which means you're best off moving SDL_Init to the top of main or adding it to the display constructor. If you add it to the beginning of the display constructor this means that you can only have one display class object running at a time, which would likely be fine in this case.