| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | // Copyright (C) 2019 Nomango
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #include "easy2d.h"
 | 
					
						
							|  |  |  |  | #include "Box2D/Box2D.h"
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | using namespace easy2d; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | //
 | 
					
						
							|  |  |  |  | // Box2D <20>dz<EFBFBD><C7B3>õ<EFBFBD><C3B5><EFBFBD>Ӧ<EFBFBD><D3A6> <20><>/ǧ<><C7A7>/<2F><> <20>ĵ<EFBFBD>λ, <20><><EFBFBD><EFBFBD>
 | 
					
						
							|  |  |  |  | // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λ<EFBFBD><CEBB><EFBFBD>м<EFBFBD><D0BC><EFBFBD>.
 | 
					
						
							|  |  |  |  | // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD> Box2D <20><> Easy2D <20><><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>ʱ, <20><>Ҫ
 | 
					
						
							|  |  |  |  | // <20><><EFBFBD><EFBFBD>һЩת<D0A9><D7AA>.
 | 
					
						
							|  |  |  |  | //
 | 
					
						
							|  |  |  |  | namespace | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const float GLOBAL_SCALE = 100.0f; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 	b2Vec2 Vec2Convert(const Point& pos) | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return b2Vec2(pos.x / GLOBAL_SCALE, pos.y / GLOBAL_SCALE); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 	Point Vec2Convert(const b2Vec2& pos) | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return Point(pos.x * GLOBAL_SCALE, pos.y * GLOBAL_SCALE); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // СԲ<D0A1><D4B2>
 | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | E2D_DECLARE_SMART_PTR(Circle); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | class Circle | 
					
						
							|  |  |  |  | 	: public Sprite | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | public: | 
					
						
							|  |  |  |  | 	Circle(b2World* world, const Point& pos) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		Load(L"circle.png"); | 
					
						
							|  |  |  |  | 		SetAnchor(0.5f, 0.5f); | 
					
						
							|  |  |  |  | 		SetScale(0.7f); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2BodyDef bodyDef; | 
					
						
							|  |  |  |  | 		bodyDef.type = b2_dynamicBody; | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 		bodyDef.position = Vec2Convert(pos); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2Body* body = world->CreateBody(&bodyDef); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		SetUserData(body); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2CircleShape shape; | 
					
						
							|  |  |  |  | 		shape.m_radius = GetWidth() / GLOBAL_SCALE / 2 * 0.7f; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2FixtureDef fixtureDef; | 
					
						
							|  |  |  |  | 		fixtureDef.shape = &shape; | 
					
						
							|  |  |  |  | 		fixtureDef.density = 1.0f; | 
					
						
							|  |  |  |  | 		fixtureDef.friction = 0.3f; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		body->CreateFixture(&fixtureDef); | 
					
						
							|  |  |  |  | 		body->SetUserData(this); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // С<><D0A1><EFBFBD><EFBFBD>
 | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | E2D_DECLARE_SMART_PTR(Square); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | class Square | 
					
						
							|  |  |  |  | 	: public Sprite | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | public: | 
					
						
							|  |  |  |  | 	Square(b2World* world, const Point& pos) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		Load(L"square.png"); | 
					
						
							|  |  |  |  | 		SetAnchor(0.5f, 0.5f); | 
					
						
							|  |  |  |  | 		SetScale(0.7f); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2BodyDef bodyDef; | 
					
						
							|  |  |  |  | 		bodyDef.type = b2_dynamicBody; | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 		bodyDef.position = Vec2Convert(pos); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2Body* body = world->CreateBody(&bodyDef); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		SetUserData(body); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2PolygonShape shape; | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 		b2Vec2 sz = Vec2Convert(GetSize() / 2 * 0.7f); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 		shape.SetAsBox(sz.x, sz.y); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2FixtureDef fixtureDef; | 
					
						
							|  |  |  |  | 		fixtureDef.shape = &shape; | 
					
						
							|  |  |  |  | 		fixtureDef.density = 1.0f; | 
					
						
							|  |  |  |  | 		fixtureDef.friction = 0.3f; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		body->CreateFixture(&fixtureDef); | 
					
						
							|  |  |  |  | 		body->SetUserData(this); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // <20>̶<EFBFBD><CCB6><EFBFBD>ľ<EFBFBD><C4BE>
 | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | E2D_DECLARE_SMART_PTR(Board); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | class Board | 
					
						
							|  |  |  |  | 	: public GeometryNode | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | public: | 
					
						
							|  |  |  |  | 	Board(b2World* world, const Size& size, const Point& pos) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 		GeometryPtr geo = new RectangleGeometry(Point(), size); | 
					
						
							|  |  |  |  | 		SetGeometry(geo); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 		SetStrokeColor(Color::White); | 
					
						
							|  |  |  |  | 		SetFillColor(Color(0, 0, 0, 0)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		SetSize(size); | 
					
						
							|  |  |  |  | 		SetAnchor(0.5f, 0.5f); | 
					
						
							|  |  |  |  | 		SetRotation(10); | 
					
						
							|  |  |  |  | 		SetPosition(pos); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2BodyDef groundBodyDef; | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 		groundBodyDef.position = Vec2Convert(GetPosition()); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 		groundBodyDef.angle = 10 * math::constants::PI_F / 180.f; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2Body* groundBody = world->CreateBody(&groundBodyDef); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		b2PolygonShape groundBox; | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 		b2Vec2 sz = Vec2Convert(Point{ size.x / 2, size.y / 2 }); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 		groundBox.SetAsBox(sz.x, sz.y); | 
					
						
							|  |  |  |  | 		groundBody->CreateFixture(&groundBox, 0.0f); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | class MainScene | 
					
						
							|  |  |  |  | 	: public Scene | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	b2World* world_; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | public: | 
					
						
							|  |  |  |  | 	MainScene() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-03-12 00:27:54 +08:00
										 |  |  |  | 		// <20><><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>Ӧ״̬, ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD> Click <20><>Ϣ
 | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 		SetResponsible(true); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>
 | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 		AddListener(Event::Click, Closure(this, &MainScene::Click)); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | 
					
						
							|  |  |  |  | 		world_ = new b2World(b2Vec2(0, 10)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-12 00:27:54 +08:00
										 |  |  |  | 		BoardPtr board = new Board(world_, Size(GetWidth() - 100, 20), Point(GetWidth() / 2, GetHeight() - 50)); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 		AddChild(board); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 		CirclePtr circle = new Circle(world_, Point(320, 240)); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 		AddChild(circle); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	~MainScene() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (world_) | 
					
						
							|  |  |  |  | 			delete world_; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void OnUpdate(Duration dt) override | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		// <20><><EFBFBD><EFBFBD> Box2D <20><><EFBFBD><EFBFBD>
 | 
					
						
							|  |  |  |  | 		world_->Step(dt.Seconds(), 6, 2); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// <20><><EFBFBD><EFBFBD>ÿһ<C3BF><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ú<EFBFBD><C3BA><EFBFBD>ת<EFBFBD>Ƕ<EFBFBD>
 | 
					
						
							|  |  |  |  | 		b2Body* body = world_->GetBodyList(); | 
					
						
							|  |  |  |  | 		while (body) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			Node* node = (Node*)body->GetUserData(); | 
					
						
							|  |  |  |  | 			b2Body* next = body->GetNext(); | 
					
						
							|  |  |  |  | 			if (node) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				const b2Vec2& pos = body->GetPosition(); | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 				node->SetPosition(Vec2Convert(pos)); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 				node->SetRotation(body->GetAngle() * 180.f / math::constants::PI_F); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD>䵽<EFBFBD><E4B5BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | 
					
						
							|  |  |  |  | 				if (node->GetPosition().y > GetHeight() + 50) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					body->SetUserData(0); | 
					
						
							|  |  |  |  | 					world_->DestroyBody(body); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					node->RemoveFromParent(); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			body = next; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Click(Event const& evt) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (evt.mouse.button == MouseButton::Left) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 			CirclePtr circle = new Circle(world_, Point{ evt.mouse.x, evt.mouse.y }); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 			AddChild(circle); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		else if (evt.mouse.button == MouseButton::Right) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-02-12 16:12:15 +08:00
										 |  |  |  | 			SquarePtr rect = new Square(world_, Point{ evt.mouse.x, evt.mouse.y }); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 			AddChild(rect); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | int main() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	try | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		Application app; | 
					
						
							| 
									
										
										
										
											2019-03-12 00:27:54 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		Options options(L"Box2D Demo"); | 
					
						
							|  |  |  |  | 		app.Init(options); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ScenePtr scene = new MainScene; | 
					
						
							|  |  |  |  | 		app.EnterScene(scene); | 
					
						
							|  |  |  |  | 		app.Run(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	catch (std::exception& e) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-03-10 13:44:02 +08:00
										 |  |  |  | 		::MessageBoxA(nullptr, e.what(), "An exception has occurred!", MB_ICONERROR | MB_OK); | 
					
						
							| 
									
										
										
										
											2019-02-03 22:38:39 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } |