Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site











SourceForge.net Logo

Box2DExample

 

Box2D "Bridge" example

Description

Example of usage Box2D a 2D physics engine with U++.

Result

 

 

 

main.cpp

 

#include <CtrlLib/CtrlLib.h>

#include <Painter/Painter.h>

#include <plugin/box2d/Box2D.h>

 

using namespace Upp;

 

struct QueryCallback : b2QueryCallback

{

    QueryCallback(const b2Vec2& point)

    {

        this->point = point;

        fixture = NULL;

    }

 

    bool ReportFixture(b2Fixture* fixture)

    {

        b2Body* body = fixture->GetBody();

        if (body->GetType() == b2_dynamicBody)

        {

            bool inside = fixture->TestPoint(point);

            if (inside)

            {

                this->fixture = fixture;

                return false;

            }

        }

 

        return true;

    }

 

    b2Vec2 point;

    b2Fixture* fixture;

};

 

struct DebugDraw : b2Draw

{

    Draw* w;

    Sizef sz;

    float cx, cy;

    float aspect;

    float zoom;

 

    DebugDraw()

    {}

 

    void Init(Draw& d, Size s)

    {

        w = &d;

        sz = s;

        zoom = 15.0f;

        cx = float(sz.cx / 2.0f);

        cy = float(sz.cy / 2.0f + 150.0f);

        aspect = float(sz.cx / sz.cy);

        aspect *= zoom;

    }

 

    Point conv(const b2Vec2& v)

    {

        return Point(int(v.x * aspect + cx), int(cy - v.y * aspect));

    }

 

    b2Vec2 conv(const Point& p)

    {

        b2Vec2 v;

 

        v.x = (p.x - cx) / aspect;

        v.y = (cy - p.y) / aspect;

 

        return v;

    }

 

    Color conv(const b2Color& c, double f = 255.0)

    {

        return Color(int(c.r * f), int(c.g * f), int(c.b * f));

    }

 

    virtual void DrawPolygon(const b2Vec2* v, int32 vertexCount, const b2Color& color)

    {

        Vector<Point> p;

        p.SetCount(vertexCount + 1);

        for(int i = 0; i < vertexCount; ++i)

            p[i] = conv(v[i]);

        p[vertexCount] = p[0];

 

        w->DrawPolyline(p, 1, conv(color, 150.0));

    }

 

    virtual void DrawSolidPolygon(const b2Vec2* v, int32 vertexCount, const b2Color& color)

    {

        Vector<Point> p;

        p.SetCount(vertexCount);

        for(int i = 0; i < vertexCount; ++i)

            p[i] = conv(v[i]);

 

        w->DrawPolygon(p, conv(color, 255.0), 1, conv(color, 150));

    }

 

    virtual void DrawCircle(const b2Vec2& center, float radius, const b2Color& color)

    {

        int r = int(aspect * radius * 2.0f);

        // int r = int(radius * 2.0f);

        Point p = conv(b2Vec2(center.x - radius, center.y + radius));

        w->DrawEllipse(p.x, p.y, r, r, conv(color, 150.0));

    }

 

    virtual void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color)

    {

        int r = int(aspect * radius * 2.0f);

        Point p = conv(b2Vec2(center.x - radius, center.y + radius));

        w->DrawEllipse(p.x, p.y, r, r, conv(color, 255.0), PEN_SOLID, conv(color, 150.0));

    }

 

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

    {

        w->DrawLine(conv(p1), conv(p2), 1, conv(color, 150.0));

    }

 

    virtual void DrawTransform(const b2Transform& xf)

    {

    }

 

    virtual void DrawPoint(const b2Vec2& p0, float size, const b2Color& color)

    {

        Point p = conv(p0);

        // int s = int(size * aspect);

        int s = int(size);

        w->DrawRect(p.x, p.y, s, s, conv(color, 255.0));

    }

 

    void DrawString(int x, int y, const char* string, ...)

    {

        char buffer[256];

 

        va_list arg;

        va_start(arg, string);

        vsprintf(buffer, string, arg);

        va_end(arg);

 

        w->DrawText(x, y, buffer);

    }

 

    void DrawAABB(b2AABB* aabb, const b2Color& color)

    {

        Point lb = conv(aabb->lowerBound);

        Point ub = conv(aabb->upperBound);

        Color fg = conv(color, 150.0);

 

        w->DrawRect(lb.x, lb.y, ub.x, ub.y, fg);

    }

};

 

struct App : TopWindow

{

    b2World world;

    b2MouseJoint* mouseJoint;

    b2Vec2 mouseWorld;

    b2Body* groundBody;

    Option showBoxes;

    DropList drawMode;

    DebugDraw debugDraw;

 

    typedef App CLASSNAME;

 

    App() : world(b2Vec2(0.0, -10.0))

    {

        Title("Box2D Example");

        SetRect(0, 0, Zx(640), Zy(480));

        Sizeable().Zoomable();

        BackPaint();

        SetTimeCallback(-1, THISBACK(Render));

        mouseJoint = NULL;

        b2Vec2 gravity;

        gravity.Set(0.0f, -10.0f);

        world.SetGravity(gravity);

        world.SetDebugDraw(&debugDraw);

        b2BodyDef bodyDef;

        groundBody = world.CreateBody(&bodyDef);

        showBoxes.SetLabel("AABBs");

 

        drawMode

            .Add(0, "Draw")

            .Add(1, "Painter - No aa")

            .Add(2, "Painter - Antialiased")

            .Add(3, "Painter - Subpixel");

 

        drawMode <<= 2;

 

        Add(showBoxes.LeftPosZ(5, 55).TopPosZ(5, 19));

        Add(drawMode.LeftPosZ(5, 130).TopPosZ(28, 19));

        Bridge();

    }

 

    void Bridge()

    {

        const int e_count = 30;

        b2Body* ground = NULL;

        {

            b2BodyDef bd;

            ground = world.CreateBody(&bd);

 

            b2EdgeShape shape;

            shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));

            ground->CreateFixture(&shape, 0.0f);

        }

 

        {

            b2PolygonShape shape;

            shape.SetAsBox(0.5f, 0.125f);

 

            b2FixtureDef fd;

            fd.shape = &shape;

            fd.density = 20.0f;

            fd.friction = 0.2f;

 

            b2RevoluteJointDef jd;

 

            b2Body* prevBody = ground;

            for (int32 i = 0; i < e_count; ++i)

            {

                b2BodyDef bd;

                bd.type = b2_dynamicBody;

                bd.position.Set(-14.5f + 1.0f * i, 5.0f);

                b2Body* body = world.CreateBody(&bd);

                body->CreateFixture(&fd);

 

                b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f);

                jd.Initialize(prevBody, body, anchor);

                world.CreateJoint(&jd);

 

                prevBody = body;

            }

 

            b2Vec2 anchor(-15.0f + 1.0f * e_count, 5.0f);

            jd.Initialize(prevBody, ground, anchor);

            world.CreateJoint(&jd);

        }

 

        for (int32 i = 0; i < 2; ++i)

        {

            b2Vec2 vertices[3];

            vertices[0].Set(-0.5f, 0.0f);

            vertices[1].Set(0.5f, 0.0f);

            vertices[2].Set(0.0f, 1.5f);

 

            b2PolygonShape shape;

            shape.Set(vertices, 3);

 

            b2FixtureDef fd;

            fd.shape = &shape;

            fd.density = 1.0f;

 

            b2BodyDef bd;

            bd.type = b2_dynamicBody;

            bd.position.Set(-8.0f + 8.0f * i, 12.0f);

            b2Body* body = world.CreateBody(&bd);

            body->CreateFixture(&fd);

        }

 

        for (int32 i = 0; i < 3; ++i)

        {

            b2CircleShape shape;

            shape.m_radius = 0.5f;

 

            b2FixtureDef fd;

            fd.shape = &shape;

            fd.density = 1.0f;

 

            b2BodyDef bd;

            bd.type = b2_dynamicBody;

            bd.position.Set(-6.0f + 6.0f * i, 10.0f);

            b2Body* body = world.CreateBody(&bd);

            body->CreateFixture(&fd);

        }

    }

 

    void Render() { Refresh(); }

 

    virtual void Paint(Draw& w)

    {

        int m = ~drawMode;

 

        float hz = 60;

        int velocityIterations = 8;

        int positionIterations = 10;

 

        float timeStep = 1.0f / hz;

 

        int flags = b2Draw::e_shapeBit | b2Draw::e_jointBit;

        if(showBoxes)

            flags |= b2Draw::e_aabbBit;

 

        debugDraw.SetFlags(flags);

 

        world.SetWarmStarting(1);

        world.SetContinuousPhysics(1);

        world.Step(timeStep, velocityIterations, positionIterations);

 

        Point p1, p2;

        if(mouseJoint)

        {

            p1 = debugDraw.conv(mouseJoint->GetAnchorB());

            p2 = debugDraw.conv(mouseJoint->GetTarget());

        }

 

        Size sz = GetSize();

 

        if(m > 0)

        {

            ImageBuffer ib(sz);

            BufferPainter bp(ib, m == 1 ? MODE_NOAA : m == 2 ? MODE_ANTIALIASED : MODE_SUBPIXEL);

            RGBA bg;

            bg.r = bg.g = bg.b = bg.a = 255;

            bp.Clear(bg);

            debugDraw.Init(bp, sz);

 

            world.DebugDraw();

            if(mouseJoint)

            {

                bp.DrawLine(p1, p2, 2, LtGreen);

                bp.DrawEllipse(p2.x - 3, p2.y - 3, 6, 6, Green, PEN_SOLID, Black);

            }

 

            w.DrawImage(0, 0, ib);

        }

        else

        {

            w.DrawRect(sz, White);

            debugDraw.Init(w, sz);

            world.DebugDraw();

            if(mouseJoint)

            {

                w.DrawLine(p1, p2, 2, LtGreen);

                w.DrawEllipse(p2.x - 3, p2.y - 3, 6, 6, Green, PEN_SOLID, Black);

            }

        }

    }

 

    virtual void LeftDown(Point p0, dword keyflags)

    {

        b2Vec2 p = debugDraw.conv(p0);

        mouseWorld = p;

 

        if(mouseJoint != NULL)

            return;

 

        b2AABB aabb;

        b2Vec2 d;

        d.Set(0.001f, 0.001f);

        aabb.lowerBound = p - d;

        aabb.upperBound = p + d;

 

        QueryCallback callback(p);

        world.QueryAABB(&callback, aabb);

 

        if (callback.fixture)

        {

            b2Body* body = callback.fixture->GetBody();

            b2MouseJointDef md;

            md.bodyA = groundBody;

            md.bodyB = body;

            md.target = p;

            md.maxForce = 1000.0f * body->GetMass();

            mouseJoint = (b2MouseJoint*) world.CreateJoint(&md);

            body->SetAwake(true);

        }

    }

 

    virtual void LeftUp(Point p0, dword keyflags)

    {

        if (mouseJoint)

        {

            world.DestroyJoint(mouseJoint);

            mouseJoint = NULL;

        }

    }

 

    virtual void MouseMove(Point p, dword keyflags)

    {

        mouseWorld = debugDraw.conv(p);

 

        if(mouseJoint)

            mouseJoint->SetTarget(mouseWorld);

    }

 

    virtual void MouseWheel(Point p, int zdelta, dword keyflags)

    {

        debugDraw.zoom += zdelta / 80.0f;

    }

};

 

GUI_APP_MAIN

{

    App().Run();

}

 

 

 

 

 

Do you want to contribute?