Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Problem with smooth movement in 2d game (scrolling view, render interpolation)  (Read 16004 times)

0 Members and 1 Guest are viewing this topic.

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
okay, I *eliminated* all my interpolation for render, and came up with very simple example, which, sadly, doesn't work as supposed. No tiles, just yellow background and the red square. I still see micro-glitches and tearing:

#include <iostream>

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/System/Vector2.hpp>

enum E_MOVE_TYPE {
    LEFT, RIGHT, IDLE
};

struct Entity {
    sf::RectangleShape shape;
    sf::Vector2f pos;
    E_MOVE_TYPE stepX;
    sf::Vector2f vxy;

    void update(float dt) {
        sf::Vector2f movement(0, 0);
        if (stepX == E_MOVE_TYPE::LEFT) {
            movement.x -= vxy.x;
        } else if (stepX == E_MOVE_TYPE::RIGHT) {
            movement.x += vxy.x;
        }
        shape.move(movement*dt);
    }

    void render(sf::RenderWindow *window, sf::RenderStates states) {
        window->draw(shape, states);
    }
};

//GLOBAL VARIABLES
Entity player;

////////
void updateLogic(float dt) {
    player.update(dt);
}

void render(sf::RenderWindow *window) {
    window->clear(sf::Color::Yellow);
    player.render(window, sf::RenderStates::Default);
}

void gameLoop(sf::RenderWindow *window) {

    const sf::Time UPDATE_STEP = sf::seconds(1.0f / 60.0f);
    sf::Time timeSinceLastUpdate = sf::Time::Zero;

    sf::Clock clock;
    while (window->isOpen()) {

        sf::Time dt = clock.restart();
        timeSinceLastUpdate += dt;

        while (timeSinceLastUpdate > UPDATE_STEP) {

            timeSinceLastUpdate -= UPDATE_STEP;

            sf::Event event;
            while (window->pollEvent(event)) {
                switch (event.type) {
                    case sf::Event::KeyPressed:
                        switch (event.key.code) {
                        case sf::Keyboard::Escape:
                            window->close();
                            break;
                        case sf::Keyboard::Left:
                            player.stepX = E_MOVE_TYPE::LEFT;
                            break;
                        case sf::Keyboard::Right:
                            player.stepX = E_MOVE_TYPE::RIGHT;
                            break;
                        break;
                    case sf::Event::KeyReleased:
                        player.stepX = E_MOVE_TYPE::IDLE;
                        break;
                    case sf::Event::Closed:
                        window->close();
                        break;
                    }
                }
            }
            updateLogic(UPDATE_STEP.asSeconds());
        }

        render(window);
        window->display();
    }
}

int main() {

    sf::RenderWindow window;
    window.create(sf::VideoMode(640, 480), "test smooth movement", sf::Style::Close);
    window.setFramerateLimit(60);

    player.pos = sf::Vector2f(10.0, 240.0);
    player.stepX = E_MOVE_TYPE::IDLE;
    player.shape.setSize(sf::Vector2f(40, 40));
    player.shape.setPosition(player.pos);
    player.shape.setFillColor(sf::Color::Red);
    player.vxy = sf::Vector2f(100, 0);

    gameLoop(&window);

    return 0;
}
 

compile it with:
Quote
g++ -o buggy ./main.cpp -lsfml-graphics -lsfml-window -lsfml-system -std=c++11 -Wall
run it:
Quote
./buggy

I see tearing when the red square moves. Can somebody confirm that?
« Last Edit: January 25, 2015, 10:22:06 am by grok »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Same if you replace framerate limit with v-sync?
Laurent Gomila - SFML developer

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
yes :-/

btw, I have tried a few OpenGL games to test that they do not suffer from the tearing.
yes, all games I have tried so far run smoothly, including SuperTux (it has an option to use OpenGL renderer), and such giants as WarZone 2100 (it uses OpenGL renderer).

tried switching to FluxBox desktop environment from XFCE4, tested on two computers (namely, PC and notebook, i.e. they have different video cards, although both have Nvidia ones), nothing changes.
« Last Edit: January 25, 2015, 11:07:35 am by grok »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Might be related to this.

The fix is described in that issue and on the linked thread. See if it helps.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
1) changed there the string to "glXSwapIntervalMESA", rebuilt, tested -- nothing changed
I added std::cout to be sure the pointer is valid. in this case it was not (i.e. I haven't seen a line printed in the console).

2) ok, then I changed the string to  "glXSwapIntervalEXT", rebuilt, tested -- my app coredumped and I saw my debug line in the console twice.
GDB reported the following:
Quote
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff23448bd in XQueryExtension () from /usr/lib/x86_64-linux-gnu/libX11.so.6
(gdb) backtrace
#0  0x00007ffff23448bd in XQueryExtension () from /usr/lib/x86_64-linux-gnu/libX11.so.6
#1  0x00007ffff2338be2 in XInitExtension () from /usr/lib/x86_64-linux-gnu/libX11.so.6
#2  0x00007ffff210c8ff in XextAddDisplay () from /usr/lib/x86_64-linux-gnu/libXext.so.6
#3  0x00007ffff66462e3 in ?? () from /usr/lib/nvidia-331/libGL.so.1
#4  0x00007ffff663e299 in glXSwapIntervalEXT () from /usr/lib/nvidia-331/libGL.so.1

3) then I reverted everything back and added std::cout to be sure it gets applied.
and, suddenly, it reports that it is enabled even when I do not explicitly set it in my application!

But the problem is that the movement is yet buggy...

4) binary1248, finally I applied your patch, i.e. checked out your branch, rebuilt SFML, recompiled my test application.
it gives an error:
Quote
X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  2 (X_ChangeWindowAttributes)
  Serial number of failed request:  55
  Current serial number in output stream:  57
and terminates. no coredumps, at least ;)
« Last Edit: January 25, 2015, 07:08:54 pm by grok »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
finally I applied your patch, i.e. checked out your branch, rebuilt SFML, recompiled my test application.
it gives an error:
That branch isn't complete yet (i.e. I know it is broken). I am waiting for the other OpenGL stuff to be finished before I work on this again.

What is the output of glxinfo?
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
good day.
here's the glxinfo output from the first computer (PC):
(click to show/hide)

I'll paste the output from another computer (notebook) later as well.

Updated:
here comes the output from the notebook:
(click to show/hide)
« Last Edit: January 26, 2015, 05:21:34 pm by grok »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Well... according to glxinfo you should be able to use glXSwapIntervalEXT (and it crashing is probably the main problem). Can you show us more frames? The backtrace starts inside the GL library, which is too deep to provide us with any useful information.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
I use debug SFML libraries built.
Okay, I use the GDB, executing program step by step:

Quote
234       window.setVerticalSyncEnabled(true);
(gdb) s
sf::Window::setVerticalSyncEnabled (this=0xbfffee40, enabled=true) at /home/varnie/thrash/SFML/src/SFML/Window/Window.cpp:278
278       if (setActive())
(gdb) s
sf::Window::setActive (this=0xbfffee40, active=true) at /home/varnie/thrash/SFML/src/SFML/Window/Window.cpp:320
320       if (m_context)
(gdb) s
322           if (m_context->setActive(active))
(gdb) s
sf::priv::GlContext::setActive (this=0x82371a8, active=true) at /home/varnie/thrash/SFML/src/SFML/Window/GlContext.cpp:216
216       if (active)
(gdb) s
218           if (this != currentContext)
(gdb) s
sf::ThreadLocalPtr<sf::priv::GlContext>::operator sf::priv::GlContext* (this=0xb7f79744 <(anonymous namespace)::currentContext>)
    at /home/varnie/thrash/SFML/include/SFML/System/ThreadLocalPtr.inl:56
56       return static_cast<T*>(getValue());
(gdb) s
sf::ThreadLocal::getValue (this=0xb7f79744 <(anonymous namespace)::currentContext>) at /home/varnie/thrash/SFML/src/SFML/System/ThreadLocal.cpp:64
64       return m_impl->getValue();
(gdb) s
sf::priv::ThreadLocalImpl::getValue (this=0x806c8e8) at /home/varnie/thrash/SFML/src/SFML/System/Unix/ThreadLocalImpl.cpp:59
59       return pthread_getspecific(m_key);
(gdb) s
__GI___pthread_getspecific (key=3) at pthread_getspecific.c:26
26   pthread_getspecific.c: No such file or directory.
(gdb) s
__x86.get_pc_thunk.bx () at ../sysdeps/i386/crti.S:66
66   ../sysdeps/i386/crti.S: No such file or directory.
(gdb) s
__GI___pthread_getspecific (key=3) at pthread_getspecific.c:31
31   pthread_getspecific.c: No such file or directory.
(gdb) s
32   in pthread_getspecific.c
(gdb) s
56   in pthread_getspecific.c
(gdb) s
57   in pthread_getspecific.c
(gdb) s
61   in pthread_getspecific.c
(gdb) s
66   in pthread_getspecific.c
(gdb) s
sf::priv::ThreadLocalImpl::getValue (this=0x806c8e8) at /home/varnie/thrash/SFML/src/SFML/System/Unix/ThreadLocalImpl.cpp:60
60   }
(gdb) s
sf::ThreadLocal::getValue (this=0xb7f79744 <(anonymous namespace)::currentContext>) at /home/varnie/thrash/SFML/src/SFML/System/ThreadLocal.cpp:65
65   }
(gdb) s
sf::ThreadLocalPtr<sf::priv::GlContext>::operator sf::priv::GlContext* (this=0xb7f79744 <(anonymous namespace)::currentContext>)
    at /home/varnie/thrash/SFML/include/SFML/System/ThreadLocalPtr.inl:57
57   }
(gdb) s
sf::priv::GlContext::setActive (this=0x82371a8, active=true) at /home/varnie/thrash/SFML/src/SFML/Window/GlContext.cpp:235
235               return true;
(gdb) s
252   }
(gdb) s
sf::Window::setActive (this=0xbfffee40, active=true) at /home/varnie/thrash/SFML/src/SFML/Window/Window.cpp:324
324               return true;
(gdb) s
336   }
(gdb) s
sf::Window::setVerticalSyncEnabled (this=0xbfffee40, enabled=true) at /home/varnie/thrash/SFML/src/SFML/Window/Window.cpp:279
279           m_context->setVerticalSyncEnabled(enabled);
(gdb) s
sf::priv::GlxContext::setVerticalSyncEnabled (this=0x82371a8, enabled=true) at /home/varnie/thrash/SFML/src/SFML/Window/Unix/GlxContext.cpp:160
160       const GLubyte* name = reinterpret_cast<const GLubyte*>("glXSwapIntervalEXT");
(gdb) s
161       PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(glXGetProcAddress(name));
(gdb) s
162       if (glXSwapIntervalSGI)
(gdb) s
163           glXSwapIntervalSGI(enabled ? 1 : 0);
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0xb5b50f6a in XQueryExtension () from /usr/lib/i386-linux-gnu/libX11.so.6
(gdb) backtrace
#0  0xb5b50f6a in XQueryExtension () from /usr/lib/i386-linux-gnu/libX11.so.6
#1  0xb5b4522e in XInitExtension () from /usr/lib/i386-linux-gnu/libX11.so.6
#2  0xb5b1d6ee in XextAddDisplay () from /usr/lib/i386-linux-gnu/libXext.so.6
#3  0xb7b7e0ff in ?? () from /usr/lib/nvidia-304/libGL.so.1
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) info registers
eax            0xbfffea84   -1073747324
ecx            0xb7e13420   -1209977824
edx            0x1   1
ebx            0xb5c56000   -1245356032
esp            0xbfffea10   0xbfffea10
ebp            0xb7bbfe14   0xb7bbfe14
esi            0x1   1
edi            0xbfffeda8   -1073746520
eip            0xb5b50f6a   0xb5b50f6a <XQueryExtension+26>
eflags         0x10286   [ PF SF IF RF ]
cs             0x73   115
ss             0x7b   123
ds             0x7b   123
es             0x7b   123
fs             0x0   0
gs             0x33   51

After we executed
Quote
glXSwapIntervalSGI(enabled ? 1 : 0);
we have the corrupted stack.

Just a guess, maybe the following is incorrect:
Quote
const GLubyte* name = reinterpret_cast<const GLubyte*>("glXSwapIntervalEXT");
 PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>

Shouldn't it be
Quote
PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = reinterpret_cast<PFNGLXSWAPINTERVALEXTPROC>

I.e. do all these function pointers have the same signature, maybe in case of glxSwapIntervalEXT it should have the different signature..?
From there: http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2010-January/063396.html
Quote
The attached patch fixes a crash in MPlayer when using "-vo gl" with recent
NVIDIA drivers.

The function prototypes for glxSwapIntervalSGI and glxSwapIntervalEXT are:

int glXSwapIntervalSGI(int interval);

void glXSwapIntervalEXT(Display *dpy, GLXDrawable drawable, int interval);

However, libvo/gl_common.c assigns either of those functions to the
SwapInterval pointer, and libvo/vo_gl.c calls through that pointer using
glxSwapIntervalSGI's prototype. This effectively passes invalid parameters to
glxSwapIntervalEXT, and causes a segfault.

Note: NVIDIA's 195.* drivers implement both of these functions; previous
drivers implemented only glxSwapIntervalSGI.

This source https://www.opengl.org/registry/specs/EXT/swap_control.txt confirms that that function has a different signature:
    void glXSwapIntervalEXT(Display *dpy,
                            GLXDrawable drawable,
                            int interval);
 
.
« Last Edit: January 27, 2015, 09:01:49 am by grok »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Oh... wait... you didn't change the call to fit the signature? ;D

Yeah... I should have mentioned that. ::)

What happens when you call it with the right arguments? Does the issue resolve itself?
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
to be honest, I don't understand well how the call should look like (i.e. I am about the other arguments passed to the function).
for example, how can I obtain Display and GLXDrawable from that part of code in SFML?
thank you for clarifications.

Updated: okay, I got it. first test shows that now v-syncs got applied! I'll try my other SFML app too.
Updated: yay, my test SFML app works now!!!  no more tearing and glitches!

if you care, here's the code which did the trick for my nvidia-card:
void GlxContext::setVerticalSyncEnabled(bool enabled)
{
    const GLubyte* name = reinterpret_cast<const GLubyte*>("glXSwapIntervalEXT");
    PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = reinterpret_cast<PFNGLXSWAPINTERVALEXTPROC>(glXGetProcAddress(name));
    if (glXSwapIntervalEXT)
        glXSwapIntervalEXT(m_display, m_window, enabled ? 1 : 0);
}
 

BUT as for notebook, it didn't work. :-/
« Last Edit: January 27, 2015, 07:06:03 pm by grok »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Does your notebook have switchable graphics (i.e. IGP + discrete GPU)? Did you try other games on your notebook as well to see if they exhibit tearing? Can you check if any of the glXSwapInterval (EXT/MESA/SGI) functions are found/called by the code?
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
Hi.
I am continuing exploring the obscure depths of video system on my notebook ;)

You're right, I have an integrated video card (intel) and nvidia geforce gt 635m.
I downloaded a standalone openGL app to test whether or not glXSwapIntervalEXT works on the notebook. It gets invoked, but makes no difference. I perform FPS calculation with and without glXSwapIntervalEXT being set, but the results are the same: the FPS remains high, (~1500 FPS or above).
That test OpenGL program works correctly on my PC; I see 60 FPS when that function is set.

I'll test other games and write back.
« Last Edit: January 28, 2015, 07:31:11 am by grok »

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
yes, as I guessed, all OpenGL games run smoothly.
speaking about Warzone 2100, it has an option in the game menu to enable/disable vsync. in both cases the game runs without any glitches.
« Last Edit: January 29, 2015, 07:07:23 am by grok »

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
if I even don't have
window.setVerticalSyncEnabled(true);
 
in my SFML app, I see in the console that that method gets invoked once, is this intentional?
hmm, yes:
void Window::initialize()
...
setVerticalSyncEnabled(false);
...
 
« Last Edit: January 29, 2015, 02:36:37 pm by grok »