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

Author Topic: Jittery Program  (Read 2743 times)

0 Members and 1 Guest are viewing this topic.

legacyblade

  • Newbie
  • *
  • Posts: 25
    • View Profile
Jittery Program
« on: August 27, 2012, 10:25:00 pm »
Hello again. I've got some of the base functionality behind my program in place, and I've run into something I don't know how to get around.

My program doesn't have a steady speed. I'm using the clock functionality to have it run the animations at a certain speed regardless of framerate. However, it will pause for long periods, pump twitch back and forth between the two poses I'm testing with, then pause again.

I thought I'd been using efficient code so far. Though even if I don't, this computer can run skyrim on full graphics settings while ripping a DVD and converting fifty some odd media files without even a slight hangup in speed in any program.

Not sure what's causing it, but I'll copy and paste the bits that are being used currently.

main.cpp
#include "global.h"

int main()
{
        gameSystem.gameLoop();

        return 0;
}
 

global.h
#ifndef _GLOBAL_H
#define _GLOBAL_H

#include "game.h"

extern game gameSystem;

#endif
 

global.cpp
#include "global.h"

game gameSystem;
 

game.h
#ifndef _GAME_H
#define _GAME_H

#include <vector>

#include "graphic.h"
#include "gameSprite.h"

//#include "input.h"
//#include "setting.h"



class game
{
public:
         game();
        void gameLoop();

        graphic graphics;
        std::vector<gameSprite> sprites;

        //std::vector<input> inputs;
        //setting settings;
};

#endif
 

(since I'm not using input or settings at the moment, I commented them out so if their functions were causing the lag, they wouldn't be used. It didn't change anything)

game.cpp
#include <vector>

#include <iostream>

#include "game.h"
#include <SFML/Graphics.hpp>

game::game()
{
        sprites.push_back(gameSprite("img/arsh.png",4,4));
}

void game::gameLoop()
{
        while(graphics.gameWindow.isOpen())
        {

                sf::Event Event;
                while(graphics.gameWindow.pollEvent(Event))
                {
                        switch(Event.type)
                        {
                        case sf::Event::Closed:
                                std::cout << "The window was closed." << std::endl;
                                graphics.gameWindow.close();
                                break;

                        default:
                                break;

                        }

                        graphics.gameWindow.clear(sf::Color(0,255,255));
                        // Draw all the sprites!
                        for (std::size_t i=0; i<sprites.size(); i++) {
                                sprites[i].update();
                                graphics.gameWindow.draw(sprites[i].getSprite());
                        }
                        graphics.gameWindow.display();

                }
        }
        std::cout << "Loop has ended." << std::endl;
}


graphic.h
#ifndef _GRAPHIC_H
#define _GRAPHIC_H

#include <SFML/Graphics.hpp>

#include <iostream>
#include <vector>

class graphic
{
public:
          graphic();
         bool windowStayOpen();
         void changeWindowSize(int width, int height);

         sf::RenderWindow gameWindow;

private:
        int numWindows;
        int numViewports;


};

#endif
 

graphic.cpp
#include <iostream>

#include "graphic.h"

graphic::graphic()
{
        sf::VideoMode VMode(800, 600, 32);

        gameWindow.create(VMode,"test",sf::Style::Close);

        //gameWindow.setFramerateLimit(40);
               
        std::cout << "Graphics engine been made ^.^" << std::endl;
}

void graphic::changeWindowSize(int width, int height)
{

}

gameSprite.h
#ifndef _GAMESPRITE_H
#define _GAMESPRITE_H

#include <SFML/Graphics.hpp>

#include <vector>
#include <utility>
#include <string>

#include <iostream>

using namespace std;

class gameSprite
{
public:
         gameSprite(string SpriteSheet, int Rows = 1, int Columns = 1, int x = 0, int y = 0);
         void update();

         sf::Sprite getSprite();
         void changeSpriteSheet(string newSheet);

private:
        void setFrame(int row = 1, int column = 1);
       
         sf::Sprite sprite;
         sf::Texture texture;
         string spriteSheet;

         int rows;
         int columns;

         int frameWidth;
         int frameHeight;
         sf::IntRect animFrame;

         vector< pair<pair<int,int>, int> > frameBuffer;
         int currentFrame;

         sf::Clock timer;
         sf::Time elapsedTime;
};

#endif

gameSprite.cpp
#include <SFML/Graphics.hpp>

#include <vector>
#include <utility>
#include <string>

#include <iostream>

using namespace std;

#include "gameSprite.h"
#include "global.h"

gameSprite::gameSprite(string SpriteSheet, int Rows, int Columns, int x, int y)
{
        spriteSheet = SpriteSheet;

        rows = Rows;
        columns = Columns;

        texture.loadFromFile(spriteSheet);

        frameWidth = texture.getSize().x / rows;
        frameHeight = texture.getSize().y / columns;

        animFrame.width = frameWidth;
        animFrame.height = frameHeight;

        setFrame(0,0);

        pair<pair<int,int>, int> tempFrameBuff ((make_pair(0,0)),.9);
        pair<pair<int,int>, int> tempFrameBuff2 ((make_pair(0,1)),.9);
        frameBuffer.push_back(tempFrameBuff);
        frameBuffer.push_back(tempFrameBuff2);

        currentFrame = 0;



}

void gameSprite::update()
{
        elapsedTime = timer.getElapsedTime();

        if (elapsedTime.asSeconds() >= frameBuffer[currentFrame].second)
        {
                if(currentFrame + 1 < frameBuffer.size()) {
                        currentFrame += 1;
                } else {
                        currentFrame = 0;
                }
                cout << currentFrame << endl;

                setFrame ( (frameBuffer[currentFrame].first).first, (frameBuffer[currentFrame].first).second );

                cout << "The time has elapsed!" << endl;
                timer.restart();
        }

}

sf::Sprite gameSprite::getSprite()
{
        sprite.setTexture(texture);

        return sprite;
}

void gameSprite::changeSpriteSheet(string newSheet)
{
        spriteSheet = newSheet;
}

void gameSprite::setFrame(int row, int column)
{
        cout << "row: " << row << "column: " << column << endl;
        //std::cout << row << std::endl;
        //std::cout << frameWidth << std::endl;

        animFrame.left = column * frameWidth;
        animFrame.top = row * frameHeight;

        sprite.setTextureRect(animFrame);
}
 

Sorry for that massive wall of text x.x If anyone could help that'd be awesome. I don't know why it's running in bursts like this. I'm using SFML 2 btw.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Jittery Program
« Reply #1 on: August 27, 2012, 10:29:32 pm »
Put your drawing code outside the event loop. It doesn't make sense to keep it inside: it will be executed only when something happens (mouse moved, key pressed, ...).
Laurent Gomila - SFML developer

legacyblade

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: Jittery Program
« Reply #2 on: August 27, 2012, 10:38:00 pm »
Doing that and taking out many of the cout statements have made it run at more or less a steady speed (though it occasionally jitters). However, even when I've changed the timer to check for miliseconds, it won't change frames faster than once every half a second (even if I have it set to do it every 100 miliseconds). So it's running slower now, but it's running SOMEWHAT more steadily. It sometimes makes his animation rush even faster than 100 miliseconds per second. But it generally changes frames every half a second.

I'm making a sidescrolling fighting game, so I need to be able to animate characters faster than this x.x

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Jittery Program
« Reply #3 on: August 27, 2012, 10:57:16 pm »
Do you test this also all in release mode? Because optimization and removale of all the debug code will make your application run a bit faster.

If you have noticable speed problems then you can use a profiler to find out what the bottleneck is and if it's in your code then you can optimize it, if it's in SFML's code then you maybe doing something wrong by calling SFML functions too often otherwise you could tell us which part of SFML makes your application so slow.

Does it also happen when you don't move your mouse over the window or press any key?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

legacyblade

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: Jittery Program
« Reply #4 on: August 28, 2012, 12:11:51 am »
It happens when I'm not clicking, moving the mouse, or running any other functions than the sprite updating stuff (clearing the window, drawing to the window, and displaying the window), and checking to see if the window should close. I've removed all the debug code. I've run it in release mode. And it's still super jittery.

The only way I've been able to really test my program's speed so far is by implementing this animation system. In my main loop, I have the program run the update method for the gameSprite (it contains a sprite). This update method checks it's frame buffer, checks to see if the sfml clock contained in the gameSprite has hit a certain number of milliseconds (in the example code, I'm using seconds, but changing it didn't do anything), then moving the rect to the next frame defined in the frame buffer (a vector containing pairs. These pairs have a pair of ints, and and int. The pair of ints tells it where to move the frame. The int tells it how many milliseconds to wait before advancing the frame). Until then, all I'd done was created the input class. That was all just outputting the the console when I pressed something. So I couldn't test any lag.

What is a profiler and how can I find one? Will that help me figure out what I'm doing to cause the program to be jittery?

I have an idea that it just may be due to the clock being contained in the gameSprite class. I'm going to try putting it in the class that runs the main game loop and see if that fixes anything.

-edit

When I put the code to update the sprites either in or after the switch that handles window events, it causes this jitteryness.  (I'm going to make a better way to check if the window's closed. That is just the code I learned from the tutorial that got me started with SFML.) So the way to make it work is just to have it handle sprites and window updating before it checks if the window needs to be closed. It works like a charm now :)

If anyone else runs into this problem, I hope this little edit helps.

And thanks Laurent. I wouldn't have thought to move the code before the event loop without your comment :)
« Last Edit: August 28, 2012, 12:20:04 am by legacyblade »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Jittery Program
« Reply #5 on: August 28, 2012, 12:31:16 am »
Quote
When I put the code to update the sprites either in or after the switch that handles window events, it causes this jitteryness.  (I'm going to make a better way to check if the window's closed. That is just the code I learned from the tutorial that got me started with SFML.) So the way to make it work is just to have it handle sprites and window updating before it checks if the window needs to be closed. It works like a charm now
Looks strange. Can you show how you did before, and how you do now?
Laurent Gomila - SFML developer

legacyblade

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: Jittery Program
« Reply #6 on: August 28, 2012, 01:39:50 am »
Upon closer inspection, it was inside the window poll event, even if it was outside of the result switch statement. So it was only running every time the window polled. (which I've read before varies from computer to computer) I noticed this when I modified the code so that my graphics class (the bit that holds the render window) would have a function that polled the window and let us know if it was open, and close it if it were not.

How the code was:

        while(graphics.gameWindow.isOpen())
        {

                sf::Event Event;
                while(graphics.gameWindow.pollEvent(Event))
                {
                        switch(Event.type)
                        {
                        case sf::Event::Closed:
                                std::cout << "The window was closed." << std::endl;
                                graphics.gameWindow.close();
                                break;

                        default:
                                break;

                        }

                        graphics.gameWindow.clear(sf::Color(0,255,255));
                        // Draw all the sprites!
                        for (std::size_t i=0; i<sprites.size(); i++) {
                                sprites[i].update();
                                graphics.gameWindow.draw(sprites[i].getSprite());
                        }
                        graphics.gameWindow.display();

                }
        }

Here's how it is now
void game::gameLoop()
{
        while(graphics.windowIsOpen() == true)
        {
                //---------------------//
                //   Update the Level  //
                //---------------------//
                        // coming soon //
                //---------------------//
                //  Update the actors  //
                //---------------------//
                        // coming soon //
                //---------------------//
                //    Update the ui    //
                //---------------------//
                        // coming soon //
                //---------------------//
                //  Refresh the Window //
                //---------------------//
                       
                // erase the current window contents
                graphics.gameWindow.clear(sf::Color(0,255,255));

                // go through all the game sprites and draw them
                for (std::size_t i=0; i<sprites.size(); i++) {
                        sprites[i].update();
                        graphics.gameWindow.draw(sprites[i].getSprite());
                }

                // show the window contents
                graphics.gameWindow.display();
        }
}

My problem was just due to some messy coding. I always feel stupid when it's something so n00bish :P Sorry for asking a question without looking more closely at my own work. x.x

 

anything