Box2D & XNA Рендеринг данных - PullRequest
       9

Box2D & XNA Рендеринг данных

0 голосов
/ 02 августа 2010

Итак, я обнаружил, что для Box2D ваша физическая информация не должна быть вашей информацией рендеринга

так что вы не можете делать такие вещи, как

spriteBatch.Draw (mazeBox, mazeBody.Position / 0.01f, Color.White)

Вместо этого вы должны создать преобразования физической информации и использовать ее в качестве рендеринга.

Так что это значит? Я пытался найти информацию о том, как использовать преобразования и рендеринг, но я получаю пробелы.

Ответы [ 2 ]

0 голосов
/ 10 марта 2011

Учитывая Body, представляющее прямоугольник, следующий код c # будет отображать текстуру в соответствии с физикой Body:

spritebatch.Begin();
spritebatch.Draw(texture,
        Body.Position * Scale,
        textureSourceRectangle,
        Color.White,
        Body.Rotation,
        new Vector2(textureWidth / 2f, textureHeight / 2f),
        1f,
        SpriteEffects.None,
        0);
spritebatch.End();

Масштаб определен для меня как 100.0f, что означает, что Body с Height установлено0,1f равно 0,1f * 100,0f = 10 пикселей.То же самое касается Body.Position.(0.1f, 0.1f) в box2D равно (10,10) в экранных координатах.

При рисовании также важно установить начало координат в центр прямоугольника.Таким образом, вращение происходит вокруг центра вашей текстуры.

0 голосов
/ 24 декабря 2010

Это означает, что физика может быть отображена так, как вы хотите: больше, меньше, повернут, переведен и так далее.Вам просто нужно выяснить, в каких пропорциях ваш рендерер (в нашем случае это XNA) будет рисовать ваши физические тела.Просто сделайте следующее: нарисуйте линию в исходном положении и коробку 1x1 в положении шара / ящика, используя приложение «hello box2d» (этого вообще нет, но вы можете просто создать новое приложение box2d, которое ничего не делаетно имитирующий падение шарика / коробки на пол. И не забывайте о том, что вы можете улучшить свою физику!).

Если вам интересно, вот мое SFML-приложение с box2d и некоторыми основами контроллера персонажей:

#include <stdio.h>

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

#include "Animation.h"

#pragma comment(lib, "Box2D.lib")
#pragma comment(lib, "sfml-system.lib")
#pragma comment(lib, "sfml-window-s.lib")
#pragma comment(lib, "sfml-graphics.lib")

#define M_PI 3.14f

#define PIXELS_PER_METER 64.f
#define METERS_PER_PIXEL (1.f / PIXELS_PER_METER)

#define PPM PIXELS_PER_METER
#define MPP METERS_PER_PIXEL

#define x_cor 2.f * METERS_PER_PIXEL
#define y_cor METERS_PER_PIXEL

// Thanks to bobasaurus =)
class DebugDraw : public b2DebugDraw
{
public:
    DebugDraw(sf::RenderWindow *renderWindow)
    {
        window = renderWindow;
    }

    void DrawPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color)
    {
        sf::Shape polygon;

        for (int32 i = 0; i < vertexCount; i++)
        {
            b2Vec2 vertex = vertices[i];
            polygon.AddPoint(vertex.x * PIXELS_PER_METER, window->GetHeight() - (vertex.y * PIXELS_PER_METER), sf::Color(0, 0, 0, 0), B2SFColor(color));
        }

        window->Draw(polygon);
    }

    void DrawSolidPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color)
    {
        sf::Shape polygon;

        for (int32 i = 0; i < vertexCount; i++)
        {
            b2Vec2 vertex = vertices[i];
            polygon.AddPoint(vertex.x * PIXELS_PER_METER, window->GetHeight() - (vertex.y * PIXELS_PER_METER), B2SFColor(color)); //need transparant outline?
        }

        window->Draw(polygon);
    }

    void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
    {
        sf::Shape circle = sf::Shape::Circle(center.x * PPM, window->GetHeight() - (center.y * PPM), radius * PPM, sf::Color(0, 0, 0, 0), 1.0f, B2SFColor(color));
        window->Draw(circle);
    }

    void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
    {
        sf::Shape circle = sf::Shape::Circle(center.x * PPM, window->GetHeight() - (center.y * PPM), radius * PPM, B2SFColor(color));
        window->Draw(circle);
    }

    void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) {}

    void DrawTransform(const b2Transform& xf) {}

private:
    sf::RenderWindow *window;

    sf::Color B2SFColor(const b2Color &color)
    {
        sf::Color result((sf::Uint8) (color.r * 255), (sf::Uint8) (color.g * 255), (sf::Uint8) (color.b * 255));

        return result;
    }
};

int main()
{
    sf::RenderWindow *App = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "SFML + Box2D Test");
    App->UseVerticalSync(true);

    // ================= Init Physics ====================
    b2World *world = new b2World(b2Vec2(0.0f, -10.0f), true);

    DebugDraw *debugDraw = new DebugDraw(App);
    debugDraw->SetFlags(b2DebugDraw::e_shapeBit);
    world->SetDebugDraw(debugDraw);

    // Define the ground body.
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(0.0f * x_cor, 0.0f * y_cor);

    b2Body* groundBody = world->CreateBody(&groundBodyDef);
    b2PolygonShape groundBox;
    groundBox.SetAsBox(500.f * x_cor, 10.0f * y_cor);
    groundBody->CreateFixture(&groundBox, 0.0f);
    // ====================================================

    // ====================================
    /*b2PolygonShape shape;
    shape.SetAsBox(5.f * x_cor, 5.f * x_cor);

    b2FixtureDef fd;
    fd.shape = &shape;
    fd.density = 1.0f;
    fd.friction = 0.3f;
    fd.restitution = 0.7f;

    b2BodyDef bd;
    bd.type = b2_dynamicBody;
    bd.angle = M_PI / 4.f;
    bd.position.Set(10.f * x_cor, 80.f * x_cor);
    b2Body* body = world->CreateBody(&bd);

    body->CreateFixture(&fd);*/

    b2BodyDef bd;
    bd.position.Set(3.0f, 5.0f);
    bd.type = b2_dynamicBody;
    bd.fixedRotation = true;
    bd.allowSleep = false;

    b2Body* body = world->CreateBody(&bd);

    b2PolygonShape shape;
    shape.SetAsBox(0.25f, 0.25f);

    b2FixtureDef fd;
    fd.shape = &shape;
    fd.friction = 20.0f;
    fd.density = 20.0f;
    body->CreateFixture(&fd);
    // ====================================

    sf::Image Image;

    if (!Image.LoadFromFile("moo.jpg"))
        return 1;

    //Image.Copy(Image, 0, 0, sf::IntRect(0, 0, 67 * 5, 68));

    sf::Animation Sprite(Image, 45, 50, 5);
    Sprite.SetLoopSpeed(20);
    Sprite.Play(0, 4);
    Sprite.SetBlendMode(sf::Blend::Alpha);
    Sprite.SetCenter(Sprite.GetSize().x / 2, Sprite.GetSize().y / 2);

    while (App->IsOpened())
    {
        sf::Event Event;
        static std::vector<sf::Vector2f> points;
        static sf::Color cl;
        bool nonConvex = false;

        while (App->GetEvent(Event))
        {
            if (Event.Type == sf::Event::Closed)
                App->Close();

            if (Event.Type == sf::Event::KeyPressed)
            {
                if (Event.Key.Code == sf::Key::Escape)
                    App->Close();

                if (Event.Key.Code == sf::Key::W && abs(body->GetLinearVelocity().y) < 1.0f)
                    body->ApplyLinearImpulse(b2Vec2(0, 5 * body->GetMass()), body->GetWorldCenter());
            }
        }

        {
            if (App->GetInput().IsKeyDown(sf::Key::A) && abs(body->GetLinearVelocity().x) < 5.0f)
            {
                body->ApplyForce(b2Vec2(-30 * body->GetMass(), 0), body->GetPosition());
            }
            if (App->GetInput().IsKeyDown(sf::Key::D) && abs(body->GetLinearVelocity().x) < 5.0f)
            {
                body->ApplyForce(b2Vec2(30 * body->GetMass(), 0), body->GetPosition());
            }

            if (App->GetInput().IsKeyDown(sf::Key::D))
            {
                //if (Sprite.IsStopped())
                {
                    Sprite.FlipX(false);
                    Sprite.Play(0, 5);
                }
            } else
            if (App->GetInput().IsKeyDown(sf::Key::A))
            {
                //if (Sprite.IsStopped())
                {
                    Sprite.FlipX(true);
                    Sprite.Play(0, 5);
                }
            } else
            //if (!Sprite.IsStopped())
            {
                Sprite.Play(12, 22);
            }
        }

        world->Step(App->GetFrameTime(), 1024, 1024);
        world->ClearForces();

        App->Clear();

        // And draw all the stuff
        world->DrawDebugData();

        Sprite.Update();
        Sprite.SetPosition(body->GetPosition().x * PPM, App->GetHeight() - (body->GetPosition().y * PPM));
        App->Draw(Sprite);

        App->Display();
    }

    return 0;
}
...