/***************************************************************
*
* 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;
}
}