I want to time text input in SDL2 to not spam it at 1000 key presses per second, rather the standard which is like ~33kps.
main.cpp
#include <iostream>
#include <SDL2/SDL.h>
#include "main.h"
void Main::Init()
{
std::cout << "Main Init called\n";
SDL_Init(SDL_INIT_VIDEO);
Get_Instance().window = SDL_CreateWindow("Program", 0, 30, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
Get_Instance().renderer = SDL_CreateRenderer(Get_Instance().window, -1, SDL_RENDERER_ACCELERATED );
Get_Instance().running = true;
}
void Main::Free()
{
SDL_DestroyRenderer(Get_Instance().renderer);
SDL_DestroyWindow(Get_Instance().window);
SDL_Quit();
std::cout << "Main Free called\n";
}
void Main::Mainloop()
{
Get_Instance(); ///To initialize constructor
if (Get_Instance().mainloopInstanceBlocker == 'C')
{
Get_Instance().mainloopInstanceBlocker = 'B'; ///Begins at I (initialized), then C (constructed) then B (began)
///It works as it begins as constructed, then does the main loop, after set to B, won't enter again.
Get_Instance().Init();
SDL_Event event;
SDL_StartTextInput();
while (Get_Instance().running)
{
///Poll events
SDL_PollEvent(&event);
///To quit program
if ( event.type == SDL_QUIT ){
Get_Instance().running = false;
break;
}
///Clear display to color
SDL_SetRenderDrawColor(Get_Instance().renderer, 0,255,0,255);
SDL_RenderClear(Get_Instance().renderer);
Get_Instance().m_Main_Loop.Mainloop( Get_Instance().window, Get_Instance().renderer, &event );
SDL_RenderPresent(Get_Instance().renderer);
}
SDL_StopTextInput();
Get_Instance().Free();
}
}
int main(int argc, char* argv[])
{
Main::Mainloop();
return 0;
}
main.h
#ifndef MAIN_H
#define MAIN_H
#include "main_loop.h"
class Main
{
public:
Main(const Main&) = delete;
Main(Main&&) = delete;
Main& operator=(const Main&) = delete;
Main& operator=(Main&&) = delete;
static void Mainloop();
private:
Main()
{
std::cout << "Main constructor called\n";
mainloopInstanceBlocker = 'C';
}
static Main& Get_Instance()
{
static Main instance;
return instance;
}
static void Init();
static void Free();
Main_Loop m_Main_Loop;
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
bool running = false;
char mainloopInstanceBlocker = 'I';
};
#endif // MAIN_H
main_loop.h
#ifndef MAIN_LOOP_H
#define MAIN_LOOP_H
#include <iostream>
#include <string>
#include <SDL2/SDL.h>
class Main_Loop
{
public:
Main_Loop();
~Main_Loop();
void Mainloop(SDL_Window* window, SDL_Renderer* renderer, SDL_Event* event);
};
#endif // MAIN_LOOP_H
main_loop.cpp
#include "main_loop.h"
Main_Loop::Main_Loop()
{
}
void Main_Loop::Mainloop(SDL_Window* window, SDL_Renderer* renderer, SDL_Event* event)
{
if (event->type == SDL_TEXTINPUT)
{
std::cout << event->text.text << std::endl;
}
}
Main_Loop::~Main_Loop()
{
}
Your problem is
SDL_PollEvent(&event);
SDL_PollEvent returns 0 if there are no more events in the queue, but in that case it doesn't write anything into passed event structure. Since you no longer check return value of PollEvent, you operate on stale data left by last event you've had. At the very least do something like
if(!SDL_PollEvent(&event)) event.type = 0;
Your Mainloop function is questionable - does it imply there could be only one event per frame? What'd you do if there are multiple events happened in single frame? I'd suggest separating event processing and rendering - i.e. make event processing function that handles entire event queue and reacts to events by modifying your data, and separate rendering function that only does rendering.
Related
I recently started working on SFML. I just created a window then later started to separating my main code. First i wrote a window class.
Nothing special, just draws my window and prints mouse coordinates.
#include "Window.hpp"
#include <iostream>
Window::Window()
{
SetWindow(800,600, "JUST SFML");
}
void Window::SetWindow(unsigned int width, unsigned int height, sf::String title)
{
m_sfmlWindow.create(sf::VideoMode(width, height), title);
}
void Window::StartDrawing()
{
m_sfmlWindow.clear();
}
void Window::EndDrawing()
{
m_sfmlWindow.display();
}
bool Window::isClosed()
{
return !m_sfmlWindow.isOpen();
}
void Window::EventControl()
{
sf::Event event;
while (m_sfmlWindow.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
m_sfmlWindow.close();
}
if (event.type == sf::Event::MouseMoved)
{
std::cout << event.mouseMove.x << " , " << event.mouseMove.y << std::endl;
}
}
}
void Window::Draw(sf::Drawable& shape)
{
m_sfmlWindow.draw(shape);
}
Everything worked perfectly.
Then i tought i need a GameManager class that i can just use in my main class.
#include "GameManager.hpp"
GameManager::GameManager()
{
m_shape.setRadius(30.0f);
m_shape.setFillColor(sf::Color::Magenta);
m_incVal = 1.0f;
m_posX = 10.0f;
m_frameRate = 1.0f / 60.0f;
}
GameManager::~GameManager()
{
}
void GameManager::InputControl()
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
m_incVal = 1.0f;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
m_incVal = -1.0f;
}
}
void GameManager::UpdateScene()
{
if (m_deltaTime.asSeconds() >= m_frameRate)
{
m_posX += m_incVal;
m_shape.setPosition(m_posX, 300);
m_deltaTime -= sf::seconds(m_frameRate);
}
}
void GameManager::DrawScene()
{
m_window.StartDrawing();
m_window.Draw(m_shape);
m_window.EndDrawing();
}
void GameManager::RestartClock()
{
m_deltaTime += m_clock.restart();
}
bool GameManager::isFinished()
{
return m_window.isClosed();
}
It was perfectly working when i use window object, later i've changed to gamemanager it start being not responding.. I can get keyboard inputs but not mouse move coordinates. Where am i make it wrong?
#include <SFML/Graphics.hpp>
#include "GameManager.hpp"
#include "Window.hpp"
int main()
{
GameManager gameManager;
while (!gameManager.isFinished())
{
gameManager.InputControl();
gameManager.UpdateScene();
gameManager.DrawScene();
gameManager.RestartClock();
}
/*
sf::CircleShape shape(100.0f);
shape.setFillColor(sf::Color::Magenta);
shape.setOutlineThickness(5.0f);
shape.setOutlineColor(sf::Color::White);
Window window;
while (!window.isClosed())
{
window.EventControl();
window.StartDrawing();
window.Draw(shape);
window.EndDrawing();
}
*/
return 0;
}
In order to receive events (such as the mouse moving), you need to call pollEvents on the window.
In your commented code, you were doing this through your Window::EventControl() method. Your new GameManager class isn't calling this, however, so you aren't receiving any events.
I have a event handler class that adds all events to a vector. This vector is cleared after each frame. However if it is cleared after each frame the events cannot be detected outside of the handle function of the event handler class. If I don't clear the vector at the end of each frame. The program becomes unresponsive. Although I can check that my for loop is reading the vector of events for a while until the vector becomes for to clogged up for the program to make sense of it.
My questions are:
Is the use of a for loop to iterate over the events a good way to check for these events? Or would it be more useful to use a while loop to check this vector for events much like you would using while(SDL_PollEvents(&e))?
Why would my program become unresponsive when I am checking the events within the vector when I am not clearing the vector?
How can I efficently check my vector eventList outside of the class. Where I could check for keydown events or similar using the vector and also clearing the vector after I have checked for the events without the program becoming unresponsive?
This is my main function where I am trying to read these events without the above mentioned problems.
int main(int argc, char* argv[]){
EventHandler handler;
SDL_SetRenderDrawColor(handler.render, 49, 49, 49, 255);
SDL_RenderClear(handler.render);
SDL_RenderPresent(handler.render);
if(handler.eventList.size() >= 1){
std::cout << "Detected an event: " << handler.eventList.size() << "\n";
}
for(std::vector<SDL_Event>::const_iterator i = handler.get().begin(); i != handler.get().end(); i++){
if(i->type == SDL_KEYDOWN){
if (i->key.keysym.sym == SDLK_w){
std::cout << "You pressed the W key\n";
}
}
}
handler.eventList.clear();
handler.handle();
}
return 0;
}
This is where I want to be able to check the events thats in the eventList
for(std::vector<SDL_Event>::const_iterator i = handler.get().begin(); i != handler.get().end(); i++){
if(i->type == SDL_KEYDOWN){
if (i->key.keysym.sym == SDLK_w){
std::cout << "You pressed the W key\n";
}
}
}
This is a simplified version of my eventHandler class
class EventHandler {
public:
bool quit;
SDL_Event event;
SDL_Window* window;
SDL_Renderer* render;
int width;
int height;
std::vector<SDL_Event> eventList;
EventHandler()
{
//Iniliaze SDL
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
std::cout << "SDL Error: " << SDL_GetError();
}
window = SDL_CreateWindow("Fallen Planets", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1024, 1080, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if (window == NULL){
std::cout << "SDL Error: " << SDL_GetError();
SDL_Quit();
quit = true;
}
render = SDL_CreateRenderer(window, -1, 0);
if (render == NULL){
SDL_DestroyWindow(window);
std::cout << "SDL Error: " << SDL_GetError();
SDL_Quit();
}
//Initialize quit bool
quit = false;
}
void handle(){
while (SDL_PollEvent(&event)){
eventList.push_back(event); // This adds the events to the eventList
if (event.type == SDL_QUIT){
SDL_DestroyWindow(window);
SDL_DestroyRenderer(render);
TTF_Quit();
SDL_Quit();
quit = true;
}
if (event.window.event == SDL_WINDOWEVENT_RESIZED){
width = SDL_GetWindowSurface(window)->w;
height = SDL_GetWindowSurface(window)->h;
}
//Update Mouse State
SDL_GetMouseState(&mouseX, &mouseY);
for (std::vector<SDL_Event>::const_iterator i = eventList.begin(); i != eventList.end(); ++i){
if (i->type == SDL_KEYDOWN){
if (i->key.keysym.sym == SDLK_w){
std::cout << "w key pressed\n";
}
}
}
}
std::vector<SDL_Event> get(){
return eventList;
}
void flush_events(){
eventList.clear();
}
};
The most effective way is to have some functions that are called for each event, whether that be mouse movement, mouse clicks, window resizes ect, and those should be handled in your main event loop by calling while (SDL_PollEvent(&event)) then have some if statements for each event and call the corresponding functions when those if statements are reached. SDL does this because you may have more then 1 event at the same time, ie, moving the mouse while pressing 'w' like any fps game. You can (im guessing by your example) just appending them to a vector within that event polling loop but then that defeats the purpose of having it loop through the events as youll just have to end up doing that to your vector anyway. You should just make some API variables that are set to some value when a specific event occurs, for example, instead of having functions, just have static variables such as static unsigned int mousePosition[2] and set [0] to the x mouse position an [1] to the y mouse position and then use that somewhere in the program when you need the mouse coordinates, or just even static SDL_Point mousePosition = {x, y} in that example.
Eg: (with a singleton class)
#pragma once
#ifndef EVENTS_H
#define EVENTS_H
#include <iostream>
#include <string>
#include <SDL2/SDL.h>
class Events ///Singleton
{
public:
Events(const Events&) = delete;
Events(Events&&) = delete;
Events& operator=(const Events&) = delete;
Events& operator=(Events&&) = delete;
static const bool& Display_Changed_Size();
///Mouse
static const SDL_Point& Mouse_Pos();
static const bool& Scrolled_Down();
static const bool& Scrolled_Up();
///Keyboard
static const std::string& Get_Text_Input();
static const bool& Pasted_Text();
static const bool& Copied_Text();
static const bool& Backspace();
private:
Events();
static Events& Get_Instance();
///Allow Main to access private members. Works well, one instance, only called once for those functions too. in Main
friend class Main;
///For event handling
static void Event_Loop();
///For event handling
static void Reset_Events();
///For quitting, used main only
static const bool& Quit_Application();
///For Event_Loop()
int eventLoopCounter = 0; ///To ensure Event_Loop() doesn't get used twice in the same loop
SDL_Event event;
bool m_quit = false;
bool m_Display_Changed_Size = false;
///Mouse
SDL_Point m_Mouse_Pos = {0,0};
bool m_Scrolled_Up = false;
bool m_Scrolled_Down = false;
///Keyboard
std::string m_Text_Input = "";
bool m_Copied_Text = false;
bool m_Pasted_Text = false;
bool m_Backspace = false;
};
#endif // EVENTS_H
and the .cpp
#include "events.h"
Events::Events()
{
std::cout << "Events constructor called\n";
}
Events& Events::Get_Instance()
{
static Events instance;
return instance;
}
void Events::Event_Loop()
{
if (Get_Instance().eventLoopCounter == 0)
{
Get_Instance().eventLoopCounter += 1;
while (SDL_PollEvent(&Get_Instance().event) != 0)
{
if (Get_Instance().event.type == SDL_QUIT)
{
Get_Instance().m_quit = true;
break;
}
if (Get_Instance().event.type == SDL_WINDOWEVENT){
if(Get_Instance().event.window.event == SDL_WINDOWEVENT_RESIZED) {
Get_Instance().m_Display_Changed_Size = true;
}
}
///Mouse
if (Get_Instance().event.type == SDL_MOUSEMOTION)
{
Get_Instance().m_Mouse_Pos = {Get_Instance().event.motion.x, Get_Instance().event.motion.y};
}
if (Get_Instance().event.type == SDL_MOUSEWHEEL){
if (Get_Instance().event.wheel.y > 0){ ///Scrolling up here
Get_Instance().m_Scrolled_Up = true;
}
if (Get_Instance().event.wheel.y < 0){ ///Scrolling down here
Get_Instance().m_Scrolled_Down = true;
}
}
///Keyboard
if (Get_Instance().event.type == SDL_TEXTINPUT)
{
Get_Instance().m_Text_Input = Get_Instance().event.text.text;
break; ///Break here for multiple key presses registered at once
}
///Keydown
if (Get_Instance().event.type == SDL_KEYDOWN)
{
///Handle copy
if( Get_Instance().event.key.keysym.sym == SDLK_c && SDL_GetModState() & KMOD_CTRL )
{
Get_Instance().m_Copied_Text = true;
}
///Handle paste
if( Get_Instance().event.key.keysym.sym == SDLK_v && SDL_GetModState() & KMOD_CTRL )
{
Get_Instance().m_Pasted_Text = true;
}
if (Get_Instance().event.key.keysym.sym == SDLK_BACKSPACE)
{
Get_Instance().m_Backspace = true;
}
}
}
}
else
{
std::cout << "Called Events::Event_Loop(); more than once\n";
}
}
void Events::Reset_Events()
{
Get_Instance().eventLoopCounter = 0;
Get_Instance().m_quit = false;
Get_Instance().m_Display_Changed_Size = false;
///Mouse
Get_Instance().m_Scrolled_Down = false;
Get_Instance().m_Scrolled_Up = false;
///Keyboard
Get_Instance().m_Text_Input = "";
Get_Instance().m_Pasted_Text = false;
Get_Instance().m_Copied_Text = false;
Get_Instance().m_Backspace = false;
}
const bool& Events::Quit_Application()
{
return Get_Instance().m_quit;
}
const bool& Events::Display_Changed_Size()
{
return Get_Instance().m_Display_Changed_Size;
}
///Mouse
const SDL_Point& Events::Mouse_Pos()
{
return Get_Instance().m_Mouse_Pos;
}
const bool& Events::Scrolled_Down()
{
return Get_Instance().m_Scrolled_Down;
}
const bool& Events::Scrolled_Up()
{
return Get_Instance().m_Scrolled_Up;
}
///Keyboard
const std::string& Events::Get_Text_Input()
{
return Get_Instance().m_Text_Input;
}
const bool& Events::Pasted_Text()
{
return Get_Instance().m_Pasted_Text;
}
const bool& Events::Copied_Text()
{
return Get_Instance().m_Copied_Text;
}
const bool& Events::Backspace()
{
return Get_Instance().m_Backspace;
}
I understand its alot of code but this type of implementation is what I use when I use SDL2, its not prone to any errors as its just a singleton, noone can instantiate and hence modify members. I would modify the line of friend class Main since its there so my main loop class can call the private functions. Even something like friend int main(int argc, char* argv[]); so the int main() can call it or something as such. In order to use it, just include the header "events.h" in anywhere you need events to be called
Usage in mainloop, assuming Mainloop is a function or class and is a friend of Events, just change the existing friend code in the header
Mainloop:
Events::Event_Loop();
.. Code
Events::Reset_Events();
In other files that need events:
if ( SDL_PointInRect( &Events::Mouse_Pos(), &rct) ) {} //example
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...
I am doing first examples from the "SDL Game Development Black and White" book.
The point where I have problems is in example where I should break "HelloSDL" code in one header( .h) and two cpp( .cpp) files.
Here they are:
main.cpp
#include "Game.h"
#include <stdio.h>
#include <SDL2/SDL.h>
Game* g_game = 0;
int main(int argc, char* args[])
{
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();
void Game::handleEvents()
{
SDL_Event event;
if(SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
m_bRunning = false;
break;
default;
break;
}
}
}
return 0;
}
Game.h
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
#include <SDL2/SDL.h>
class Game
{
public:
Game();
~Game();
void init();
void render();
void update();
void handleEvents();
void clean();
bool running() { return m_bRunning; }
private:
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
bool m_bRunning;
};
#endif // GAME_H_INCLUDED
Game.cpp
#include <iostream>
#include "Game.h"
//#include <stdio.h>
#include <SDL2/SDL.h>
bool Game::init(const char* title, int xpos, int ypos, int width, int height, int flags)
{
if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
std::cout << "SDL init success\n";
m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if(m_pWindow != 0)
{
std::cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0)
{
std::cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer, 255 255, 255, 255);
}
else
{
std::cout << "renderer init fail\n";
return false;
}
}
else
{
std::cout << "window init fail\n";
return false;
}
}
else
{
std::cout << "SDL init fail\n";
return false;
}
std::cout << "init success\n";
m_bRunning = true;
return true;
}
void Game::render()
{
SDL_RenderClear(m_pRenderer);
SDL_RenderPresent(m_pRenderer);
}
SDL_Quit()
+{
std::cout << "cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
void Game::clean()
{
std::cout << "cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
After compiling it in CodeBlocks(16.11) I get next error messages:
Game.cpp|6|error: prototype for 'bool Game::init(const char*, int, int, int, int, int)' does not match any in class 'Game'
Game.h|12|error: candidate is: void Game::init()
Firstly, I got much more errors but I managed to solve it.
There is still two more errors to solve.
I suppose that is something wromg in Game.h file, but I cannot find it.
Thank you in advance!
The init() declared in the game.h returns void, but the definition you provide returns bool.
It seems that you may be coming from C background. In C++ omitting function signature at function declaration is not permitted. Basically by declaring void init(); you declare void Game::init(void) function, not bool Game::init(const char* title, int xpos, int ypos, int width, int height, int flags). So one must carefully check that function declaration does exactly match function definition. Another thing is that in C++ one should perform object initialization at constructor and cleanup at destructor.
so i have just started playing with sdl and i have it working fine in a single class but for some reason when i separate things into seperate classes the display opens a insta closes. an ideas ?
Main Class Header
#pragma once
#include <SDL.h>
#include <glew.h>
#include <iostream>
#include "Input.h"
#include "Display.h"
#include "RenderingEngine.h"
#include "PhysicsEngine.h"
class Main
{
public:
Main();
~Main();
/* Engine settings & Engine Controlls*/
void start();
void stop();
void pause(bool value);
void run();
private:
/* Loop Controllers */
bool running;
bool paused;
/* Engine Initialisation */
void initSDL();
RenderingEngine render_core = RenderingEngine(4, 2);
PhysicsEngine physics_core = PhysicsEngine();
Display display = Display("game engine", 900, 900, 900, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
Input input;
};
Main Class
#include "Main.h"
Main::Main()
{
initSDL();
start();
}
Main::~Main()
{
}
void Main::initSDL()
{
SDL_Init(SDL_INIT_EVERYTHING);
}
void Main::start()
{
if (running) return;
running = true;
run();
}
void Main::stop()
{
if (!running) return;
running = false;
exit(0);
}
void Main::pause(bool value)
{
paused = value;
}
void Main::run()
{
while (running)
{
if (!paused)
{
}
render_core.render();
display.swapBackBuffer();
input.update();
}
}
int main(int argc, char *argv[])
{
Main engine;
return 0;
}
Display Header
#pragma once
#include <iostream>
#include <SDL.h>
class Display
{
public:
Display(const char* name, int x, int y, int w, int h, Uint32 flags);
~Display();
void swapBackBuffer();
private:
int x;
int y;
int w;
int h;
const char* name;
Uint32 flags;
SDL_Window *window;
SDL_GLContext opengl;
};
Display Class
#include "Display.h"
Display::Display(const char* n, int x, int y, int w, int h, Uint32 f)
{
this->x = x;
this->y = y;
this->w = w;
this->h = h;
this->name = name;
this->flags = flags;
this->window = SDL_CreateWindow(n, x, y, w, h, f);
this->opengl = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, opengl);
printf("Display: initialised\n\n");
}
Display::~Display()
{
SDL_GL_DeleteContext(opengl);
SDL_DestroyWindow(window);
printf("Display: destroyed\n\n");
}
void Display::swapBackBuffer()
{
SDL_GL_SwapWindow(window);
}
Render Engine class.... there isn't anything important in the header
#include "RenderingEngine.h"
RenderingEngine::RenderingEngine(int major_version, int minor_version)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major_version);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor_version);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
setClearColour(0, 0, 0, 1);
printf("Rendering Engine:: initialised\n\n");
}
RenderingEngine::~RenderingEngine()
{
printf("Rendering Engine:: destroyed\n");
}
void RenderingEngine::setClearColour(float r, float g, float b, float a)
{
glClearColor(r, g, b, a);
}
void RenderingEngine::clearScreen()
{
glClear(GL_COLOR_BUFFER_BIT || GL_DEPTH_BUFFER_BIT);
}
void RenderingEngine::render()
{
clearScreen();
}
input class
#include "Input.h"
Input::Input()
{
printf("Input:: initialised\n");
}
Input::~Input()
{
printf("Input:: destroyed\n");
}
void Input::setMouseVisabilityTo(bool value)
{
if (value) SDL_ShowCursor(1);
else SDL_ShowCursor(0);
}
int Input::getMouseX()
{
return mouseX;
}
int Input::getMouseY()
{
return mouseY;
}
void Input::update()
{
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
break;
case SDL_KEYDOWN:
keyboard[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
keyboard[event.key.keysym.sym] = false;
break;
case SDL_MOUSEBUTTONDOWN:
mouse[event.button.button] = true;
break;
case SDL_MOUSEBUTTONUP:
mouse[event.button.button] = false;
break;
case SDL_MOUSEWHEEL:
break;
case SDL_MOUSEMOTION:
mouseX = event.button.x;
mouseY = event.button.y;
break;
}
}
}
i know there are a lot a files so the help will be greatly appreciated, this has been bugging me for a while now
my edited main.h file
#include "Display.h"
#include "RenderingEngine.h"
#include "PhysicsEngine.h"
class Main
{
public:
Main() :
render_core(4, 2),
display("game engine", 900, 900, 900, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL),
physics_core(),
input()
{
running = false;
paused = false;
initSDL();
start();
}
~Main();
/* Engine settings & Engine Controlls*/
void start();
void stop();
void pause(bool value);
void run();
private:
/* Loop Controllers */
bool running;
bool paused;
/* Engine Initialisation */
void initSDL();
RenderingEngine render_core;
PhysicsEngine physics_core;
Display display;
Input input;
Is this some weird version of C++ (e.g. C++11) where you can declare and initialize a non-static member variable all in the same statement?
You should not be doing that kind of thing, the order in which your render context is constructed and initialized in relation to the rest of your software is extremely important. This is what constructors are for.
Assuming you actually are intentionally (ab)using C++11 here, your window closes immediately because this statement:
Display display = Display("game engine", 900, 900, 900, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
Constructs a Display object, and then makes a copy of that object and assigns it to display. After this statement "returns", the original object is destroyed.
And look at what the destructor for Display does:
Display::~Display()
{
SDL_GL_DeleteContext(opengl);
SDL_DestroyWindow(window);
printf("Display: destroyed\n\n");
}
Long story short, do not initialize your members this way. Constructors were perfectly fine before C++11 came along and made life more difficult.
Consider something like the following constructor instead:
Main () : render_core (4, 2),
display ("game engine", 900, 900, 900, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL),
physics_core ()
{
initSDL ();
start ();
}
...
private:
RenderingEngine render_core;
PhysicsEngine physics_core;
Display display;
This solution initializes all of the members of Main when it is constructed, without any copy-assignment and is compatible with a much wider range of C++ compilers. No temporary Display object in this code means that your window is not going to be created and then immediately destroyed.