wxWidgets 3.15
Box2D 2.4.1
一、main.h
#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#define WX_PRECOMP
#include <wx/wx.h>
#endif // WX_PRECOMP
class MyApp:public wxApp
{
public:
virtual bool OnInit();
};
#endif // MAIN_H_INCLUDED
二、main.cpp
/***************************************************************
*
* Copyright 2021 by 海阳市宜家电脑
*
***************************************************************/
#include "main.h"
#include "simple.h"
wxIMPLEMENT_APP(MyApp);
wxDECLARE_APP(MyApp);
bool MyApp::OnInit()
{
Simple* simple= new Simple("Box2D First Demo");
simple->Show(true);
return true;
}
三、simple.h
#include <wx/wx.h>
#include <wx/dcbuffer.h>
#include <Box2D/box2d.h>
class Simple:public wxFrame,b2ContactListener
{
public:
Simple(const wxString& title);
~Simple();
protected:
wxTimer* timer;
b2World* world;
float timeStep;
int32 velocityIterations;
int32 positionIterations ;
private:
void OnPaint(wxPaintEvent& event);
void OnTimer(wxCommandEvent& event);
};
#endif // SIMPLE_H_INCLUDED
四、simple.cpp
/***************************************************************
*
* 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);
float x = 0.0f;//x轴重力
float y = 9.8f;//y轴重力
b2Vec2 gravity(x, y);
world = new b2World (gravity);
//*** 一、画物体 ***
//1.物体的运动和状态相关属性,如类型、线速度、角速度等。
b2BodyDef def;
def.position = b2Vec2(64/PTM_RATIO,3/PTM_RATIO);
def.type = b2_dynamicBody;
def.linearVelocity = b2Vec2(0,9.8);
b2Body* body = world->CreateBody(&def);
//2.物体形状
b2PolygonShape shape;
shape.SetAsBox(0.5,0.5);
//3.物体的物质属性,如密度、摩擦系数、弹性系数等,还有物体的形状。
b2FixtureDef fixtureDef;
fixtureDef.shape = &shape;
fixtureDef.density =1;//密度
fixtureDef.friction =0.3;//摩擦系数
fixtureDef.restitution =0.7;//弹性
body->CreateFixture(&fixtureDef);
//***二、画地面 ***
//1.地面的运动各状态等属性
b2BodyDef groundDef;
groundDef.position = b2Vec2(0,nHeight/PTM_RATIO);//位置
groundDef.type = b2_staticBody;//地面是静止的
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; //摩擦系数
groundBody->CreateFixture(&groundFixtureDef);
// 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);
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);
gc->SetBrush(*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();
b2Shape* shape = b->GetFixtureList()->GetShape();
printf("type=%i %4.2f %4.2f\n", b->GetType(), position.x, position.y);
wxGraphicsPath pathGround = gc->CreatePath();
if(b->GetType() == b2BodyType::b2_staticBody) // b2BodyType::b2_kinematicBody)//
{
if(shape->GetType() == b2Shape::e_polygon)
{
b2PolygonShape* poly = (b2PolygonShape*)shape;
int vertexCount = poly->m_count;
b2Vec2 v[vertexCount];
for(int j = 0; j < vertexCount; j++)
{
v[j] = b->GetWorldPoint(poly->m_vertices[j]);
v[j].x *= PTM_RATIO;
v[j].y *= PTM_RATIO;
pathGround.AddLineToPoint(v[j].x, v[j].y);
}
}
}
else if(b->GetType() == b2BodyType::b2_kinematicBody)// b2BodyType::b2_kinematicBody)//
{
printf("kinematic x=%4.2f y=%4.2f\n", position.x, position.y);
pathGround.AddRectangle(position.x * PTM_RATIO
, position.y * PTM_RATIO
, 400, 50);
}
else
{
if (shape->GetType() == b2Shape::e_circle)
{
b2CircleShape* circle = (b2CircleShape*) shape;
position = b->GetWorldPoint(circle->m_p);
// printf("radius = %f\n",circle->m_radius);
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];
for(int j =0;j<vertexCount;j++)
{
v[j] = b->GetWorldPoint(poly->m_vertices[j]);
v[j].x *= PTM_RATIO;
v[j].y *= PTM_RATIO;
pathGround.AddLineToPoint(v[j].x,v[j].y);
}
}
}
pathGround.CloseSubpath();
gc->FillPath(pathGround);
gc->StrokePath(pathGround);
}
delete gc;
}