3. wxWidgets之Box2D刚体旋转(自转)

这篇博客展示了如何使用Box2D库创建一个简单的物理世界,包括静态和动态物体,如地面和不同形状的物体。作者通过C++代码详细解释了如何设置重力、创建边界、定义物体属性以及处理碰撞。此外,还涵盖了物体的运动状态更新和图形渲染。
摘要由CSDN通过智能技术生成

/***************************************************************
*
*  Copyright 2021 by 海阳富润德智能科技有限公司
*
***************************************************************/
#include "simple.h"

Simple::~Simple(){
    delete world;
}
Simple::Simple(const wxString& title)
    :wxFrame(NULL,-1,title,wxPoint(-1,-1),wxSize(800,600))
{
    SetBackgroundStyle(wxBG_STYLE_PAINT);

    srand(time(NULL));
    timer = new wxTimer(this,-1);

    nWidth = GetSize().GetWidth();
    nHeight = GetSize().GetHeight();

    float x = 0.0f;//x轴重力
    float y = 10.0f;//y轴重力 9.8简化为10.0,方便计算
    b2Vec2 gravity(x, y);
    world = new b2World (gravity);

    //*** 一、画地面 ***
    //1.地面的运动各状态等属性
    b2BodyDef groundDef;
    groundDef.type = b2_staticBody;//地面是静止的  b2_kinematicBody;//
    groundDef.position = b2Vec2(0,(nHeight-50)/PTM_RATIO);//位置
    b2Body* groundBody = world->CreateBody(&groundDef);
    //2.形状
    b2PolygonShape groundShape;//多边形
    groundShape.SetAsBox(nWidth/PTM_RATIO,0.5/PTM_RATIO);//在物理世界中的半长 的 半宽 是多少米
    //3.地面的属性
    b2FixtureDef groundFixtureDef;
    groundFixtureDef.shape = &groundShape;//形状
    groundFixtureDef.density = 1;//密度
    groundFixtureDef.friction = 0.3; //摩擦系数 取值范围[ 0 - 1 ]
    groundFixtureDef.restitution=0.5;//弹性系数 取值范围[ 0 - 1 ]
    groundBody->CreateFixture(&groundFixtureDef);


    //*** 二、物体1 多边形 ***
    //1.物体的运动和状态相关属性,如类型、线速度、角速度等。
    b2BodyDef defRect;
    defRect.position = b2Vec2(300/PTM_RATIO,30/PTM_RATIO);
    defRect.type = b2_dynamicBody;//b2_kinematicBody;//
    defRect.linearVelocity = b2Vec2(0,10.0);//x轴、y轴移动单位数
    defRect.fixedRotation=true;
    defRect.angularVelocity= b2Rot(45).GetAngle();// 45 * 3.14 /180;
    b2Body* bodyRect = world->CreateBody(&defRect);
    //2.物体形状
    vs[0].Set(-0.5,0.5);
    vs[1].Set(0.5,0.5);
    vs[2].Set(0.5,-0.5);
    vs[3].Set(-0.5,-0.5);
    b2PolygonShape shapeRect;
    shapeRect.Set(vs,4);
//    shapeRect.SetAsBox(0.5f/PTM_RATIO, 0.5f/PTM_RATIO, b2Vec2(0.25f/PTM_RATIO, 0.25f/PTM_RATIO),60*3.14/180);
//    shapeRect.SetAsBox(0.5f, 0.5f, b2Vec2(0.25f, 0.25f),60*3.14/180);
    shapeRect.SetAsBox(0.5,0.5);//设定边框.这是一个向量,本质上说他就是一个形状的中心坐标

    //3.物体的物质属性,如密度、摩擦系数、弹性系数等,还有物体的形状。
    b2FixtureDef fixtureDefRect;
    fixtureDefRect.shape = &shapeRect;
    fixtureDefRect.density =1;//密度
    fixtureDefRect.friction =0.2;//摩擦系数
    fixtureDefRect.restitution =0.6;//弹性
    bodyRect->CreateFixture(&fixtureDefRect);

    //*** 三、画物体 2 球形 ***
    //1.物体的运动和状态相关属性,如类型、线速度、角速度等。
    b2BodyDef defCircle;
    defCircle.type = b2_dynamicBody;
    defCircle.position = b2Vec2(164/PTM_RATIO,3/PTM_RATIO);
    //2.物体形状
    b2CircleShape shapeCircle;
    shapeCircle.m_p = b2Vec2(0,0);//在b2Body中的位置
    shapeCircle.m_radius =11.0 / PTM_RATIO;
    //3.赋予物体大小、形状和其他有形特征
    b2FixtureDef fixtureDefCircle;
    fixtureDefCircle.shape = &shapeCircle;
    fixtureDefCircle.density =1;//密度
    fixtureDefCircle.friction =0.3;//摩擦系数
    fixtureDefCircle.restitution =0.6;//弹性
    for (int i = 0; i < 3; i++)
    {
        defCircle.position.Set((170 + i * 100) / PTM_RATIO, 20 / PTM_RATIO);
        defCircle.angularVelocity = b2Rot(10).GetAngle();
        bodies[i] = world->CreateBody(&defCircle);
        fixtureDefCircle.friction = 0.3 * (i + 1);
        fixtureDefCircle.restitution = 0.3 * (i + 1);
        bodies[i]->CreateFixture(&fixtureDefCircle);
    }

    // simullation.
    timeStep = 1.0f / 60.0f;//delta延迟几秒的画面
    velocityIterations = 8;//
    positionIterations = 3;//


    Bind(wxEVT_PAINT,wxPaintEventHandler(Simple::OnPaint),this);
    Bind(wxEVT_TIMER,wxCommandEventHandler( Simple::OnTimer),this);
    Bind(wxEVT_KEY_DOWN,wxKeyEventHandler(Simple::OnKeyDown),this);

    timer->Start(100);
    Centre();
}

void Simple::OnTimer(wxCommandEvent& event)
{
    world->Step(timeStep, velocityIterations, positionIterations);
    Refresh();
}

void Simple::OnPaint(wxPaintEvent& event){

    wxBufferedPaintDC dc(this);
    dc.Clear();
    wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
    gc->SetPen(*wxRED);
//  e_circle = 0, e_edge = 1, e_polygon = 2, e_chain = 3,  e_typeCount = 4

    for (b2Body *b = world->GetBodyList(); b; b = b->GetNext())
    {

        b2Vec2 position = b->GetPosition();
        float angle = b->GetAngle();

        b2Vec2 center = b->GetWorldCenter();
        center.x = center.x *PTM_RATIO;
        center.y = center.y *PTM_RATIO;
        printf("type=%i %4.2f %4.2f angle=%4.2f\n", b->GetType(), position.x, position.y,angle);

        wxGraphicsPath pathGround = gc->CreatePath();
        if(b->GetType() ==b2BodyType::b2_staticBody)// b2BodyType::b2_kinematicBody)//
        {
            pathGround.AddRectangle(position.x * PTM_RATIO
                                , position.y * PTM_RATIO
                                , 400, 50);
        }
        else
        {
            b2Fixture* fixture = b->GetFixtureList();
            b2Shape* shape = b->GetFixtureList()->GetShape();
            position = b->GetPosition();
            printf("type=%i x = %4.2f y=%4.2f angle=%4.2f\n"
                   , shape->GetType()
                   , position.x, position.y
                   ,angle);

            if (shape->GetType() == b2Shape::e_circle)
            {
                b2CircleShape* circle = (b2CircleShape*) shape;
                pathGround.AddCircle(position.x * PTM_RATIO
                                     , position.y * PTM_RATIO
                                     , circle->m_radius*PTM_RATIO);
                pathGround.MoveToPoint(position.x*PTM_RATIO,position.y*PTM_RATIO);
                pathGround.AddLineToPoint(position.x * PTM_RATIO + circle->m_radius*PTM_RATIO
                                          ,position.y * PTM_RATIO + circle->m_radius*PTM_RATIO);
            }
            else if(shape->GetType() == b2Shape::e_polygon)
            {
                b2PolygonShape* poly = (b2PolygonShape*)shape;

                int vertexCount = poly->m_count;
                b2Vec2 v[vertexCount];

                printf("center count=%i x=%4.2f y=%4.2f\n",vertexCount,center.x,center.y);

                for (int i = 0; i < vertexCount; i++)
                {
                    v[i] = poly->m_vertices[i] + position;;//
                    v[i].x = v[i].x  * PTM_RATIO;
                    v[i].y = v[i].y  * PTM_RATIO;
                    pathGround.AddLineToPoint(v[i].x ,v[i].y );

                }

            }
            else
            {
                pathGround.AddRectangle(position.x * PTM_RATIO
                                        , position.y * PTM_RATIO
                                        , 50, 50);
            }//end if
        }//end if

        //刚体旋转
        if(angle != 0.0)
        {
            wxGraphicsMatrix mx = gc->CreateMatrix();
            mx.Translate(center.x, center.y);
            mx.Rotate(angle);//*3.14/180);//);//
            mx.Translate(-center.x, -center.y);
            pathGround.Transform(mx);
        }


        pathGround.CloseSubpath();
        gc->FillPath(pathGround);
        gc->StrokePath(pathGround);
    }//end for
    delete gc;
}

void Simple::OnKeyDown(wxKeyEvent& event)
{
//    wxLogMessage("you pressed '%i'",event.GetKeyCode());
    switch(event.GetKeyCode())
    {
    case WXK_LEFT:
        bodies[0]->ApplyForce(b2Vec2(0,1),bodies[0]->GetWorldCenter(),true);
        break;
    case WXK_RIGHT:
        bodies[1]->ApplyForceToCenter(b2Vec2(1,1),false);//,bodies[0]->GetWorldCenter(),true);
        break;
    case WXK_UP:
        bodies[2]->SetTransform(b2Vec2(0,1),1);
        break;
    case WXK_DOWN:
        break;
    case WXK_F1:
        break;
    }

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值