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

Author Topic: SFML Graphics, or Box2D  (Read 3027 times)

0 Members and 1 Guest are viewing this topic.

siegeon

  • Newbie
  • *
  • Posts: 3
    • View Profile
SFML Graphics, or Box2D
« on: July 30, 2010, 03:24:05 am »
Like a lot of people here I got it into my head that it would be a good idea to implement Box2D with SFML. So working with examples from this site I threw together this little ball bouncing program. The problem is that the movement of the ball is choppy, it will be smooth for a few moments, then get choppy, for a few moments, then back to smooth, its very aggravating. I was hoping that someone smarter then myself can take a look at the code here and let me know if its a SMFL graphics thing, or Box2D.
Code: [Select]

#include <SFML/Graphics.hpp>
#include <Box2D/Box2D.h>

#define PIXELS_METER 30.f
#define PI 3.1415926

double degreeToRadian(double degree) {
        double radian = 0;
        radian = degree * (PI/180);
        return radian;
}
double radianToDegree(double radian) {
        double degree = 0;
        degree = radian * (180/PI);
        return degree;
}

b2Body* makePolBody(b2World *World, b2BodyType type, sf::Shape &Shape, const sf::Vector2f &Position, const sf::Vector2f &Size)
{
// Create the body
    b2BodyDef def;
    def.type = type;
    def.position.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
    b2Body* Body = World->CreateBody(&def);
    b2PolygonShape pol;
    pol.SetAsBox(Size.x/PIXELS_METER, Size.y/PIXELS_METER);
    b2FixtureDef fix;
    fix.shape = &pol;
    fix.density = 1.0f;
    fix.friction = 0.3f;
    Body->CreateFixture(&fix);
    Shape = sf::Shape::Rectangle(0.f, 0.f, Size.x*2, Size.y*2, sf::Color::White);
    Shape.SetCenter(Size);
    Shape.SetPosition(Position);

    return Body;
}
b2Body* makeCirBody(b2World *World, b2BodyType type, sf::Shape &Shape, const sf::Vector2f &Position, const float radius)
{
// Create the body
   b2BodyDef def;
   def.type = type;
   def.position.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
   b2Body* Body = World->CreateBody(&def);

   // Creating the box2d circle shape (size in pixels)
   b2CircleShape circle;
   circle.m_p.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
   circle.m_radius = radius/PIXELS_METER;

   b2FixtureDef fix;
   fix.shape = &circle;
   fix.density = 1.0f;
   fix.friction = .0f;
   fix.restitution = 1.0f;

   b2Vec2 force = b2Vec2(10, 10);
   
   Body->ApplyLinearImpulse(force, def.position);
   Body->CreateFixture(&fix);
     
   Shape = sf::Shape::Circle(Position, radius, sf::Color::White);
   return Body;
}
void Synchronize(b2Body *Body, sf::Shape &Shape)
{
   Shape.SetRotation((float)-radianToDegree(Body->GetAngle()));
   Shape.SetPosition(Body->GetPosition().x*PIXELS_METER, Body->GetPosition().y*PIXELS_METER);
}
int main() {

    // Create the SFML Window
   sf::RenderWindow Game(sf::VideoMode(800, 600, 32), "SFML Blank Window");
   sf::Event Event;
   Game.SetFramerateLimit(60);

    // Create the world
    b2Vec2 Gravity(.0f, .0f);
    b2World World(Gravity, true);

    // Create the body and the shape
    sf::Shape ball;
    b2Body *bBody = makeCirBody(&World, b2_dynamicBody, ball, sf::Vector2f(200,200),15);

    sf::Shape tWall;
sf::Shape bWall;
sf::Shape lWall;
sf::Shape rWall;
    b2Body *tGroundBody = makePolBody(&World, b2_staticBody, tWall, sf::Vector2f(600.f, 1.f), sf::Vector2f(800.f, 1.f));
b2Body *bGroundBody = makePolBody(&World, b2_staticBody, bWall, sf::Vector2f(1.f, 600.f), sf::Vector2f(800.f, 1.f));
b2Body *lGroundBody = makePolBody(&World, b2_staticBody, lWall, sf::Vector2f(1.f, 800.f), sf::Vector2f(1.f, 800.f));
b2Body *rGroundBody = makePolBody(&World, b2_staticBody, rWall, sf::Vector2f(800.f, 1.f), sf::Vector2f(1.f, 600.f));

    while (Game.IsOpened())
{
        while (Game.GetEvent(Event))
{
            if (Event.Type == sf::Event::Closed)
                Game.Close();
        }

        World.Step(Game.GetFrameTime(), 10, 10);

        Synchronize(bBody, ball);
 
        Game.Clear();

        Game.Draw(ball);
        Game.Draw(tWall);
Game.Draw(bWall);
Game.Draw(lWall);
Game.Draw(rWall);

        Game.Display();
    }

    return EXIT_SUCCESS;
}
[/code]

siegeon

  • Newbie
  • *
  • Posts: 3
    • View Profile
Box2D removed
« Reply #1 on: August 03, 2010, 05:54:04 pm »
So I have removed Box2D for the time being, and am working with simple shapes, circles and rectangles. However the choppy, almost laggy effect remains. Some times the ball will move smoothly, and other times it will slow down or speed up causing a very inconsistent effect. I thought that it may have something to do with my graphics card, but I get the same thing on another system. I have simplified the code, would someone please take a look at it and let me know what I am doing wrong here.

Code: [Select]

int main()
{
// Create the SFML Window
sf::RenderWindow Game(sf::VideoMode(DEF_WIDTH, DEF_HEIGHT, BPP), "SFML Blank Window");
sf::Event Event;
Game.SetFramerateLimit(60);
Game.ShowMouseCursor(false);

   
    // Set up the ball
ball.setUpBall(DEF_WIDTH/2,DEF_HEIGHT/2,DEF_VX,DEF_VY,0,true);

// Main Loop
while (Game.IsOpened())
{
        while (Game.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
                Game.Close();

if(Event.MouseMoved)
paddle.move(Event);

        }
if(collision.paddleBallTest(paddle,ball))
collision.paddleBall(paddle,ball);

ball.move();
        Game.Clear();
        Game.Draw(ball.image())
        Game.Draw(paddle.image());
Game.Display();

    }

Dig

  • Newbie
  • *
  • Posts: 31
    • View Profile
SFML Graphics, or Box2D
« Reply #2 on: August 04, 2010, 02:10:34 am »
This can't be the full listing as ball isn't defined anywhere.

My guess would be that the ball is moving a set amount each call to ball.move().  As this is called in your drawing loop then your ball's speed will vary with frame rate.

simple fix is pass a frame rate to move and adjust how much you move accordingly.  Better fix is to update based on frame rate and draw at a fixed rate:

This might help
http://gpwiki.org/index.php/Basic_Timing

siegeon

  • Newbie
  • *
  • Posts: 3
    • View Profile
SFML Graphics, or Box2D
« Reply #3 on: August 04, 2010, 08:55:48 am »
You are right, it is not the whole code base, ball is a circle shape, and move takes advantage of the SF::Shape .Move function. You are also right that the ball is being moved by a velocity factor every call.

So I thought the line Game.SetFramerateLimit(60); enforced the frame rate of 60, if this is not the case what does it do? Does it simply prevent going over 60 frames? This is a little confusing...

If I understand the example from the link,I would have to force my program to sleep when not enough time has passed, and skip the logic in the other case. However we are talking about a very insignificant amount of logic here, and on this system running it to completion every time should not be a problem.

On a side note while asking google about this problem today I found a link that referenced the .UseVerticalSync(true) while this did resolve the issue, I read that it could cause more issues, I will try to implement a system more like what you pointed out in the link.

Dig

  • Newbie
  • *
  • Posts: 31
    • View Profile
SFML Graphics, or Box2D
« Reply #4 on: August 04, 2010, 10:24:44 am »
It might not be the framerate but it seems the most likely culprit.

There is no way SFML can make enforce a FASTER frame rate than your computer can render so setting the frame rate caps it.  You don't want to set the timing of your game based on framerate or vertical sync.

Actually right here in the SFML tutorials is a useful article on this:



http://www.sfml-dev.org/tutorials/1.6/window-time.php

I've been away from SFML too long :)[/code]