Resizing window using SDL and OpenGL - opengl

Before writing this question, I have read the question: Handling window resizing using OpenGL and SDL. However that question does not solve my problem, since I am using SDL2 and not SDL1.2. But I do use OpenGL2. My complete source code is available at: http://dpaste.com/17BVBP6
I am writing a program that displays a white square in the window. However I am having trouble while handling window resize events.Here is my resize function:
void resize(int width,int height)
{
if(height<=0) height=1;
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,float(width)/float(height),1.0f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
My Main event loop:
while( !quit )
{
while( SDL_PollEvent( &e ) != 0 )
{
switch (e.type) {
case SDL_QUIT:
quit=true;
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
resize(e.window.data1,e.window.data2);
break;
case SDL_KEYDOWN:
switch (e.key.keysym.sym) {
case SDLK_ESCAPE:
quit=true;
break;
default:
break;
}
default:
break;
}
}
render();
update(gWindow);
}
Here is my window when it is not resized:
Here is my window when it is resized:
What is the causing the problem here??

SDL_WINDOWEVENT_SIZE_CHANGED is not an event type, it is variation of SDL_WINDOWEVENT. Your event checking should be like
switch(e.type) {
case SDL_WINDOWEVENT:
if(e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
resize(e.window.data1,e.window.data2);
}
break;
Also remove your perspective projection setting - it is inconsistend with your draw, and you don't have perspective setup before resize.

Related

Some problem with touch events with cef and SDL2

I'm experiencing some problem to getting working touch events with CEF in offscreen rendering using SDL2 in some situation:
Im writing an SDL-CEF application that need to execute some online game into a videolottery. so I start the application from tty using startx and not in DE. Morever, I can't use the mouse but is only possible use touchscreen to interact with the machine.The touch event work pretty well in the most os cases, but with some game the click event is not recognized by the web application.
For pass the correct event to the CEF browser I have written some specialized handler functions that catchs the SDL_Event and converts their to CEF_Event. Fo example for processing tauch events I have a function called handleFingerEvent(SDL_Event, CEF_Browser*). This specialized function is called from a generic handleEvents(SDL_Event, VEF_Browser*) handler function of highter level .
// The Touch Event Hendler function
void handleFingerEvent(SDL_Event &e, CefBrowser* browser) {
CefMouseEvent event;
switch (e.type) {
case SDL_FINGERDOWN:
// W_SIZE and H_SIZE are the dimension of the screen in px
if (e.tfinger.pressure > 0.9) {
event.x = static_cast<int>(e.tfinger.x*W_SIZE);
event.y = static_cast<int>(e.tfinger.y*H_SIZE);
browser->GetHost()->SendMouseClickEvent(event,
MBT_LEFT,
false, 1);
}
break;
case SDL_FINGERUP:
event.x = static_cast<int>(e.tfinger.x*W_SIZE);
event.y = static_cast<int>(e.tfinger.y*H_SIZE);
browser->GetHost()->SendMouseClickEvent(event, MBT_LEFT, true, 1);
break;
case SDL_FINGERMOTION: {
int scrollX = static_cast<int>(e.tfinger.dx);
int scrollY = static_cast<int>(e.tfinger.dy);
event.x = static_cast<int>(e.tfinger.x*W_SIZE);
event.y = static_cast<int>(e.tfinger.y*H_SIZE);
browser->GetHost()->SendMouseWheelEvent(event, scrollX, scrollY);
break;
}
default:
break;
}
}
void handleEvents(SDL_Event &e, CefBrowser *browser) {
switch (e.type) {
// Key events
case SDL_KEYDOWN:
case SDL_KEYUP:
handleKeyEvent(e, browser);
break;
// Window events
case SDL_WINDOWEVENT:
handleWindowEvent(e, browser);
break;
//Mouse events
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEWHEEL:
handleMouseEvent(e, browser);
break;
// Touch events
case SDL_FINGERDOWN:
case SDL_FINGERMOTION:
case SDL_FINGERUP:
handleFingerEvent(e, browser);
break;
default:
break;
}
}
I call it from a SDL_PollEvent() while loop like this:
browser = CefBrowserHost::CreateBrowserSync(window_info,
browserClient, //My BrowserClient implementation
"https://www.something.sometother",
browserSettings, // The cef setting
nullptr, nullptr);
while(!browserClient->closeAllowed()) {
//Send events to the browser
SDL_Event e;
while(SDL_PollEvent(&e) != 0){
//Quit and window resize
if(e.type == SDL_QUIT) {
browser->GetHost()->CloseBrowser(false);
}
else if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
renderHandler->resize(e.window.data1, e.window.data2);
browser->GetHost()->WasResized();
}
else {
handleEvents(e, browser.get());
}
}
// Cef main work loop
cefApp->doCefWork();
//Set background color
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
//Clear window/renderer
SDL_RenderClear(renderer);
renderHandler->render();
//Update screen contents
SDL_RenderPresent(renderer);
}
Now I really don't know why in some game the event isn't caught by the browser. Morever if I open the game in a machine with mouse connected and a DM, and so I use the mouse pointer for interact with the game, it works without any problem. Maybe is there a better approach to send a click event to CefBrowser?

Non instantaneous/jerky movement using SDL2 & OpenGL

I've been working on a little 3D engine trying to fix up the camera and make it less jerky. I've been using SDL for the input and while it works it's doing this thing where if I press and hold a button it will instantly move once then pause and then start moving properly making the movement feel unresponsive.
I recorded a GIF of it and while it may be slightly hard to see what's happening hopefully it'll give some idea:
Moving forward and then right would be like:
w wwwwwwwwwwwwwwww a aaaaaaaaaaaaaaaaaaaaa
The important code is here but feel free to ask for more if necessary:
//Poll events
SDL_Event event;
while (m_EngineState != EngineState::EXIT)
{
m_last = m_current;
m_current = SDL_GetPerformanceCounter();
deltaTime = (double)((m_current - m_last) * 1000 / SDL_GetPerformanceFrequency());
while (SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_QUIT:
m_EngineState = EngineState::EXIT;
break;
case SDL_MOUSEMOTION:
break;
case SDL_KEYDOWN:
m_Keys[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
m_Keys[event.key.keysym.sym] = false;
break;
}
ProcessEvents();
}
void Engine::ProcessEvents()
{
if (m_Keys[SDLK_w])
{
m_Camera->MoveForward(5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_s])
{
m_Camera->MoveForward(-5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_d])
{
m_Camera->MoveRight(5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_a])
{
m_Camera->MoveRight(-5.0f*(deltaTime*0.001));
}
}
void Camera::MoveForward(float amount)
{
m_pos += m_forward * amount;
}
void Camera::MoveRight(float amount)
{
m_pos += glm::cross(m_forward, m_up) * amount;
}
Do not use SDL_PollEvent with the SDL_KEYDOWN and SDL_KEYUP events, it is subject to OS keyboard repeat rates. Which is great for typing, but not for camera/player controls. Use SDL_GetKeyboardState(NULL) in stead to query the current state of the keys.
For example:
Uint8* keystate = SDL_GetKeyboardState(NULL);
if (keystate[SDL_SCANCODE_W])
{
m_Camera->MoveForward(5.0f*(deltaTime*0.001));
}
if (keystate[SDL_SCANCODE_S])
{
m_Camera->MoveForward(-5.0f*(deltaTime*0.001));
}

Render issues when resetting mouse position inside of a switch case with sfml

I'm making a basic breakout game using SFML in order to familiarize myself with C++ (moving up from C). Inside the game loop, I've placed an event poll that leads to a switch statement. When the mouse is moved, the switch-case will retrieve the mouse xy change and move the paddle accordingly, like so:
while (window.isOpen())
{
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyPressed:
switch (event.key.code)
{
case sf::Keyboard::Escape:
window.close();
break;
}
break;
case sf::Event::MouseMoved:
paddle.move(sf::Vector2f((sf::Mouse::getPosition(window).x - windowOffset.x) * sensitivity, 0));
break;
}
}
sf::Mouse::setPosition(windowOffset, window);
window.clear();
window.draw(paddle);
window.display();
}
Now, that works just fine and dandy, but I'm resetting the mouse position to the center of the window on every loop, which isn't necessary if the mouse hasn't moved. So, I tried moving sf::Mouse::setPosition() into the switch statement, underneath paddle.move, like so:
case sf::Event::MouseMoved:
paddle.move(sf::Vector2f((sf::Mouse::getPosition(window).x - windowOffset.x) * sensitivity, 0));
sf::Mouse::setPosition(windowOffset, window);
break;
However, when I rebuild the project, I now get a blank white window.
So, my question is: What's causing this to happen?
edit(minimal complete code)
int WinMain()
{
sf::Vector2i windowRes(700, 900);
sf::Vector2i windowOffset(350, 450);
sf::ContextSettings settings;
sf::RectangleShape paddle;
paddle.setSize(sf::Vector2f(150, 20));
paddle.setOrigin(350, 0);
paddle.setPosition(350, 825);
sf::RenderWindow window(sf::VideoMode(windowRes.x, windowRes.y), "Breakout", sf::Style::Default, settings);
window.setMouseCursorVisible(false);
sf::Mouse::setPosition(windowOffset, window);
sf::Event event;
while (window.isOpen())
{
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyPressed:
switch (event.key.code)
{
case sf::Keyboard::Escape:
window.close();
break;
}
break;
case sf::Event::MouseMoved:
paddle.move(sf::Vector2f((sf::Mouse::getPosition(window).x - windowOffset.x), 0));
//sf::Mouse::setPosition(windowOffset, window);
break;
}
}
sf::Mouse::setPosition(windowOffset, window);
window.clear();
window.draw(paddle);
window.display();
}
return 0;
}
So, through some tinkering, it seems that sf::MOUSE::setposition() generates an event.type of sf::Event::MouseMoved, which would be added to the event queue, causing an infinite loop.

Managing multiple RenderWindow's in sfml

I seem to be having a bit of trouble when managing multiple windows in SFML C++. When I try to manage multiple windows, they both open correctly and I can interact in the larger one, however, the smaller one, which upon creation is overlapping the larger window, I can not interact with until I move the large window away. An image is below to help with the visual. Also below is the main loop for my code.
The main loop of the code is as follows:
while (MainWin.isOpen() || F1Menu.isOpen())
{
sf::Event Event;
if (MainWin.pollEvent(Event))
{
switch (Event.type)
{
case sf::Event::Closed:
MainWin.close();
if (F1Menu.isOpen())
F1Menu.close();
break;
case sf::Event::Resized:
MainView.reset(sf::FloatRect(0.f, 0.f, (MainWin.getSize().x*0.9f), (MainWin.getSize().y*0.9)));
MainWin.setView(MainView);
break;
case sf::Event::KeyPressed:
if (Event.key.code == sf::Keyboard::F1)
F1Menu.create(sf::VideoMode(200, 500), "SFML 2D - F1 Menu");
else if (Event.key.code == sf::Keyboard::Escape)
{
MainWin.close();
if (F1Menu.isOpen())
F1Menu.close();
}
break;
}
}
if (F1Menu.pollEvent(Event))
{
switch (Event.type)
{
case sf::Event::Closed:
F1Menu.close();
break;
case sf::Event::MouseButtonReleased:
if (Event.mouseButton.button == sf::Mouse::Left)
if (LMButton.mouseIn(F1Menu))
LoadMap("MapA.dat");
break;
case sf::Event::MouseMoved:
if (LMButton.mouseIn(F1Menu))
LMButton.setColor(sf::Color::Yellow);
else
LMButton.setColor(sf::Color::White);
break;
}
}
moveClock.restart();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
player.move(0, -4 * time);
player.setDirection(sfm::Direction::Up);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
player.move(0, 4 * time);
player.setDirection(sfm::Direction::Down);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
player.move(-4 * time, 0);
player.setDirection(sfm::Direction::Left);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
player.move(4 * time, 0);
player.setDirection(sfm::Direction::Right);
}
if (F1Menu.isOpen())
{
F1Menu.clear();
F1Menu.draw(LMButton);
F1Menu.display();
}
if (MainWin.isOpen())
{
MainWin.clear();
if (SplashScreen.didAnimate)
SplashScreen.Animate(MainWin, sfg::Animation::FadeIn);
if (inMenu)
{
}
if (isPlaying)
{
DrawMap(MainWin);
MainWin.draw(player);
}
MainWin.display();
}
}
In my knowledge, you aren't able to poll two separate windows with one sf::Event object. this is because when polling events, you are essentially popping off of the event stack and handling each one. The signature of pollEvent is
bool pollEvent(sf::Event &event);
note that there is no const qualifier here, because each processed event gets popped off the event stack. By the time you finish polling your main window there are no events left for your other window. This could be the cause of your window being unable to focus. Your second window should use it's own separate sf::Event
On a side note I would highly recommend encapsulating your data inside classes. You can find a great reference here on how to go about doing so. It's great coding practice and helps minimize confusion when bug hunting

Sprite isn't moving

I'm new to programming and, since I find it easier to learn doing, I was playing around with C++ and SFML. I was trying to get a sprite to move, but for some reason, I can't do it. I've tried everything I found, but no luck. Anyone know why this isn't working? I'm using Visual Studio 2012 Express and SFML 2.1, by the way.
int main()
{
sf::RenderWindow window(sf::VideoMode(1000, 800), "Project");
window.setFramerateLimit(30);
glEnable(GL_TEXTURE_2D);
window.clear(sf::Color::White);
window.display();
sf::Texture charMain;
if (!charMain.loadFromFile("Images/playerFrontSprite.png"))
{
return 1;
}
sf::Sprite charaMain;
charaMain.setPosition(500.f , 500.f);
charaMain.setTexture(charMain);
window.draw(charaMain);
window.display();
sf::Font cavefont;
sf::Font::Font(cavefont);
if (!cavefont.loadFromFile("Cave-Story.ttf"))
return 1;
while (window.isOpen())
{
sf::Event playerAction;
while (window.pollEvent(playerAction))
{
switch(playerAction.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyPressed:
std::cout << "sf::Event::KeyPressed" << std::endl;
switch(playerAction.key.code)
{
case sf::Keyboard::W:
charaMain.move(0 , 1);
break;
case sf::Keyboard::A:
charaMain.move(-1 , 0);
break;
case sf::Keyboard::S:
charaMain.move(0 , -1);
break;
case sf::Keyboard::D:
charaMain.move(1 , 0);
break;
}
break;
}
}
}
}
Your problem is that you're moving the object, but you're not drawing it on the screen at its new position. Your drawing code is outside the main loop, so it never gets called after you move the sprite, so you never see the effects.
You basically need to pull the rendering code (ie. window.draw(charaMain) and window.display()) inside the while (window.isOpen()) loop, outside the event handling loop.