KeyJustDown implementation in emscripten using GLFW3 - glfw

I want to implement KeyJustDown function which checks, if given key was just pressed down. Key was just pressed down, if it is down in the current state and was up in the previous state.
int isKeyJustDown(int key) {
return !inputState.keysPrev[key] && inputState.keysCurr[key];
}
At the beginning of the frame I also update the input state like so:
struct InputState {
char keysPrev[256];
char keysCurr[256];
} inputState;
void updateInput() {
memcpy(inputState.keysPrev, inputState.keysCurr, 256);
glfwPollEvents();
}
This works fine with glfw3 application on desktop. Callbacks are dispatched when glfwPollEvents function is called. However this does not apply when using emscripten.
I have two questions. When exactly are callbacks dispatched when using emscripten (do they happen as soon as event occurs or is there a certain point in the loop it happens)? And how can I achieve the same behaviour as on desktop when using emscripten?
Here is the full example:
#include <GLFW/glfw3.h>
#include <memory.h>
#include <stdio.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
GLFWwindow *window;
struct InputState {
char keysPrev[256];
char keysCurr[256];
} inputState;
void updateInput() {
memcpy(inputState.keysPrev, inputState.keysCurr, 256);
glfwPollEvents();
}
int isKeyJustDown(int key) {
return !inputState.keysPrev[key] && inputState.keysCurr[key];
}
void update() {
updateInput();
if (isKeyJustDown(GLFW_KEY_E)) {
printf("Key E\n");
}
glfwSwapBuffers(window);
}
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {
if (key < 0) return;
inputState.keysCurr[key] = action != GLFW_RELEASE;
}
int main() {
if (!glfwInit()) return 1;
window = glfwCreateWindow(1280, 720, "Input test", NULL, NULL);
if (!window) return 1;
glfwSetKeyCallback(window, keyCallback);
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(update, 0, 1);
#else
while (!glfwWindowShouldClose(window)) {
update();
}
glfwTerminate();
#endif
return 0;
}

It looks like glfwPollInput does nothing in the emscripten implementation. The actual event callbacks can happen at any time. To solve my problem I moved updateInput function after checking for input:
void update() {
if (isKeyJustDown(GLFW_KEY_E)) {
printf("Key E\n");
}
glfwSwapBuffers(window);
updateInput();
}
Relevant links:
https://github.com/raysan5/raylib/pull/2380
https://github.com/raysan5/raylib/issues/2379

Related

OpenGL can't create window object

I've bee trying to make a class for a window and I'm not sure why this error shows up.
I've been also trying to add the functions and everything else manually into the "main.cpp" file to check if openGl is working, and it does, but when I try to make a openGl object, it's not working.
Maybe the problem it's easy to spot, but I can't figure it out.(sorry I'm just trying to learn here :3 )
Here is my code:
The header file
#pragma once
#include <iostream>
#include <GLFW/glfw3.h>
class Window {
private:
const char* p_title;
int p_width;
int p_height;
GLFWwindow* window;
public:
Window(const char* title, int width, int height);
~Window();
bool close();
void update();
private:
void init();
};
The .cpp file
#include "window .h"
Window::Window(const char* title, int width, int height)
{
p_title = title;
p_width = width;
p_height = height;
init();
}
Window::~Window()
{
glfwTerminate();
}
bool Window::close()
{
return glfwWindowShouldClose(window);
}
void Window::update()
{
glfwPollEvents();
glfwSwapBuffers(window);
}
void Window::init()
{
window = glfwCreateWindow(p_width, p_height, p_title, NULL, NULL);
if (!window) {
std::cout << "The window could not be created\n";
glfwTerminate();
}
glfwMakeContextCurrent(window);
}
If it helps, here is the debugger:

opengl window initialization issue

I'm trying to encapsulate GLFW in a class to make my code cleaner.
So in my class, I've made the basic window creation but when I execute the program, it always enter in the if statement where I check if the initialization went right or not and I don't know why.
This is what I have
#include "include/Window.h"
#include <iostream>
Window::Window(int x, int y) {
_window = glfwCreateWindow(x, y, "Heightmap Visualizer", NULL, NULL);
}
Window::~Window() {
glfwTerminate();
}
int Window::createWindow() {
if (!_window) {
std::cerr << "went here" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(_window);
run();
glfwTerminate();
return 0;
}
void Window::run() {
while (!glfwWindowShouldClose(_window)) {
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(_window);
glfwPollEvents();
}
}
This is the header file
#include <GLFW/glfw3.h>
class Window {
public:
Window(int x, int y);
~Window();
int createWindow();
void run();
private:
GLFWwindow* _window;
};
Make sure to glfwInit().
Also good luck in your jorney learning GL and C++!

Passing in an SDL_Event* into a method

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.

Failing to create a window in GLFW C++

Some background if you care/if it helps. I am pretty knew to programming and C++, I tried to learn it a couple times before but couldn't stay interested. As I couldn't think of an interesting project to do as I learn. Eventually I thought of making a game engine(dumb idea for a noob, but it will be a good learning experience and I'm interested in doing it.), so I searched for a series on making one to get an idea and found TheChernoProject's series and here I am.
I'm trying to make a make a window in GLFW and C++ but it keeps failing, I have no idea what to do.
Main.cpp
#include "src\graphics\window.h"
int main() {
using namespace tmge;
using namespace graphics;
Window window("Test", 1280, 720);
while (!window.windowClosed()) {
window.update();
}
return 0;
}
Window.h
#pragma once
#include <GLFW\glfw3.h>
#include <iostream>
namespace tmge { namespace graphics {
class Window {
private:
GLFWwindow *privateWindow;
int privateWidth, privateHeight;
const char *privateTitle;
bool privateWindowClosed();
public:
Window(const char *title, int width, int height);
~Window();
bool init();
void update() const;
bool windowClosed() const;
};
} }
Window.cpp
#include "window.h"
namespace tmge { namespace graphics {
Window::Window(const char *title, int width, int height) {
privateTitle = title;
privateWidth = width;
privateHeight = height;
if (!init()) {
glfwTerminate();
}
}
Window::~Window() {
glfwTerminate();
}
bool Window::init() {
if (!glfwInit) {
std::cout << "GLFW initialaztion failed" << std::endl;
return false;
}
privateWindow = glfwCreateWindow(privateWidth, privateHeight, privateTitle, NULL, NULL);
if (!privateWindow) {
std::cout << "Failed to create GLFW window" << std::endl;
return false;
}
glfwMakeContextCurrent(privateWindow);
return true;
}
bool Window::windowClosed() const{
return glfwWindowShouldClose(privateWindow);
}
void Window::update() const{
glfwPollEvents();
glfwSwapBuffers(privateWindow);
}
} }

SDL OpenGL window instantly closes

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.