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

Author Topic: box2d  (Read 8754 times)

0 Members and 1 Guest are viewing this topic.

Kubik

  • Newbie
  • *
  • Posts: 13
    • View Profile
    • Email
box2d
« on: August 15, 2012, 01:09:37 pm »
Please give me example how work with him in sfml with sprites

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: box2d
« Reply #1 on: August 15, 2012, 02:44:12 pm »
Please use the search function and your brain to find such examples. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

TheVirtualDragon

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Control + Alt + Delete!
Re: box2d
« Reply #2 on: August 15, 2012, 06:34:44 pm »
I will give you a hint which will make life easier: Box2D has y increasing towards the top and calculates angles in radians while SFML has y increasing towards the bottom and calculates angles in degrees.

Also, GetPosition() in box2d returns the centre of a body while in SFML getPositon() (or GetPosition in SFML 1.6) returns the top left corner.

P.S. I don't blame Kubic for asking for an example, because I had loads of problems with Box2D and SFML and I searched for ages before I found anything decent.
« Last Edit: August 15, 2012, 06:37:04 pm by TheVirtualDragon »

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: box2d
« Reply #3 on: August 15, 2012, 07:31:06 pm »
1. Don't assume Box2d has y increasing towards the top, it's much easier this way.
2. #define or (preferably) make const floats to convert between pixels and meters, and radians and degrees to make your life easier.
3. Read sfml tutorials and documentation.
4. Read official user manual from box2d site.
5. Read this tutorials series, it's not for the latest version of box2d but changes are minor and it points out when something is done differently in latest version: http://www.iforce2d.net/b2dtut/
Back to C++ gamedev with SFML in May 2023

TheVirtualDragon

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Control + Alt + Delete!
Re: box2d
« Reply #4 on: August 16, 2012, 05:11:39 pm »
Quote
1. Don't assume Box2d has y increasing towards the top, it's much easier this way.

Actually, if you set gravity to be something like (0.0f, -10.0f) like it is in the real world, then you can't not assume that Box2D has y increasing to the top. If you make gravity to be (0.0f, 10.0f) then you don't need to flip the y axis.
« Last Edit: August 16, 2012, 05:14:53 pm by TheVirtualDragon »

Kubik

  • Newbie
  • *
  • Posts: 13
    • View Profile
    • Email
Re: box2d
« Reply #5 on: August 21, 2012, 09:18:53 am »
Thanks for your answers... I use sfml 2.0 and box2d 2.1.2. I read documeantation of sfml 2.0 and not found function of set center of sprite.
how this function is named in sfml 2.0? How many pixels per meter? 64 or 32?

TheVirtualDragon

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Control + Alt + Delete!
Re: box2d
« Reply #6 on: August 21, 2012, 11:42:26 am »
You cannot set centre of a sprite, as there is no such function. You can implement your own function, or use the existing function - which is sf::Sprite::SetPosition - to align the centre of the sprite to the body's centre of mass. You can do it like this:

Code: [Select]
b2Vec2 bodyPos = body->GetPosition();
exampleSprite.setPosition(bodyPos.x - bodySize.x, bodyPos.y - bodySize.y);

Note that you might need to mess around with the second parameter of the setPosition function if gravity is negative in your world (i.e. b2Vec2 gravity(0.0f, -9.81f)). This works for me:

Code: [Select]
exampleSprite.setPosition(bodyPos.x - bodySize.x, - (bodyPos.y + bodySize.y) );

There are other ways of doing this, but I think that is the easiest.

Also note that you will have to declare bodySize yourself, either as a b2Vec2 or a sf::Vector2f. I don't recall there being anyway of getting the dimensions of a fixture or body, I think you will have to set it manually.

Kubik

  • Newbie
  • *
  • Posts: 13
    • View Profile
    • Email
Re: box2d
« Reply #7 on: August 21, 2012, 11:59:32 am »
what is bodySize? Is b2PolygonShape size?

Kubik

  • Newbie
  • *
  • Posts: 13
    • View Profile
    • Email
Re: box2d
« Reply #8 on: August 21, 2012, 12:02:53 pm »
#include <SFML/Graphics.hpp>
#include <Box2D/Box2D.h>
#include <iostream>

using namespace std;

const float M = 64.0;
const float P = 1.0/64.0;

int main()
{
    sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "Test");
    // &#1089;&#1086;&#1079;&#1076;&#1072;&#1077;&#1084; &#1084;&#1080;&#1088;
    b2Vec2 gravity(0.0, 9.8);
    bool sleep = true;
    b2World world(gravity, sleep);

    // &#1089;&#1086;&#1079;&#1076;&#1072;&#1077;&#1084; &#1092;&#1080;&#1079;&#1080;&#1095;&#1077;&#1089;&#1082;&#1080;&#1081; &#1086;&#1073;&#1098;&#1077;&#1082;&#1090;
    b2BodyDef bodydef;
    bodydef.type = b2_dynamicBody;
    // &#1086;&#1087;&#1088;&#1077;&#1076;&#1077;&#1083;&#1103;&#1077;&#1084; &#1077;&#1075;&#1086; &#1082;&#1072;&#1082; &#1089;&#1090;&#1072;&#1090;&#1080;&#1095;&#1077;&#1089;&#1082;&#1080;&#1081;
    bodydef.position.Set(0,0);
    bodydef.angle = 0;
    // cjplftv &#1089;&#1072;&#1084; &#1086;&#1073;&#1098;&#1077;&#1082;&#1090;
    b2Body* body = world.CreateBody(&bodydef);
    // &#1089;&#1086;&#1079;&#1076;&#1072;&#1077;&#1084; &#1087;&#1086;&#1083;&#1080;&#1075;&#1086;&#1085; &#1080; &#1082;&#1088;&#1077;&#1087;&#1083;&#1077;&#1085;&#1080;&#1077;
    b2PolygonShape polygonShape;
    polygonShape.SetAsBox(64/2*P, 64/2*P);
    b2FixtureDef fixture;
    fixture.density = 0.5;
    fixture.friction = 0.7;
    fixture.shape = &polygonShape;
    body->CreateFixture(&fixture);
    //body->GetWorldPoint( b2Vec2(0,0) );
    // &#1089;&#1086;&#1079;&#1076;&#1072;&#1077;&#1084; &#1090;&#1077;&#1082;&#1089;&#1090;&#1091;&#1088;&#1091;
    sf::Texture texture;
    texture.loadFromFile("block.png");
    sf::Sprite sprite(texture);

    while (Window.isOpen())
    {
        Window.clear();
        world.Step(1/60, 6, 2);

        b2Vec2 bodyPos = body->GetPosition();
        b2Vec2 bodySize = b2Vec2(64*P, 64*P);
        sprite.setPosition(bodyPos.x - bodySize.x, bodyPos.y - bodySize.y);


        cout << "(" << body->GetPosition().x << ";" << body->GetPosition().y << ")" << endl;
        Window.draw(sprite);
        Window.display();
    }
    return 0;
}
 
why my body don't fly down? please help

TheVirtualDragon

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Control + Alt + Delete!
Re: box2d
« Reply #9 on: August 21, 2012, 03:20:49 pm »
Your body won't fly down because gravity is:

b2Vec2 gravity(0.0, 9.8);
 

It should be:

b2Vec2 gravity(0.0f, -9.80f); //The minus is important. In physics, a negative force means down.
 

And bodySize is the size of the body. If the shape of the body is not a rectangle (i.e. the shape is a custom polygon), then body size should be the size of the sprite. So, for clarity, it really should be this:

exampleSprite.setPosition(bodyPos.x - spriteSize.x, - (bodyPos.y + spriteSize.y) );
 

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: box2d
« Reply #10 on: August 21, 2012, 08:48:06 pm »
You cannot set centre of a sprite, as there is no such function. You can implement your own function, or use the existing function - which is sf::Sprite::SetPosition - to align the centre of the sprite to the body's centre of mass.
Isn't it what setOrigin is doing?
Using setPosition here is totally incorrect.

TheVirtualDragon

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Control + Alt + Delete!
Re: box2d
« Reply #11 on: August 21, 2012, 09:28:48 pm »
Good point, setOrigin is the SFML1.6 equivalent of SetCenter...

Note to self: Must read documentation before posting answers  :-\

Edit: No wait, there is a reason it was renamed. SetOrigin does not set the centre of the sprite - it is just the point around which all transformations will happen. So after calling setOrigin and passing the position of the body to it, you will still need to call setPosition - or otherwise the sprite's top left corner will be located at the centre of the body.
« Last Edit: August 21, 2012, 10:51:08 pm by TheVirtualDragon »

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: box2d
« Reply #12 on: August 22, 2012, 02:58:41 am »
1. It's good thing you made gravity positive, one less minus sign to write/forget/cause problems. Try not to listen too much to virtualdragon about that...  :)
2. 1/60 in your step call is integer division, it rounds to 0 so box2d thinks you want to do a time step equal to 0 seconds, that can't be good. ::) Change it to 1.f/60.f or 0.0166666667 and it'll work. Write .f after integer if you mean that it's a float that just happen to also be integer or things like that happen.
3. You should convert body position back into pixels in sprite.setPosition
4. You shouldn't tie your steps to framerate but I understand that's just a test here.
5. If you set origin of sprite to it's center then you CAN just do:
sprite.setPosition(bodyPos.x*M, bodyPos.y*M);
Back to C++ gamedev with SFML in May 2023

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: box2d
« Reply #13 on: August 22, 2012, 04:51:29 am »
AFAIR you HAVE to set the origin of the sprite to its center, or else rotations will be wrong.

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: box2d
« Reply #14 on: August 22, 2012, 05:12:14 am »
It depends on what you're doing with that sprite, in a side view metroidvania style game most of the sprites never rotate.
Back to C++ gamedev with SFML in May 2023