1、首先配置Box2D的VS环境
①在官网或GitHub上下载Box2D的源码,http://www.box2d.org,https://github.com/erincatto/Box2D
②在官网下载premake,https://premake.github.io/
③将下载好的premake.exe放入解压好的Box2D文件夹内(只是为了方便编译,查看帮助可以了解)
④生成工程文件
⑤打开Build工程文件,设置Box2D为启动项,生成解决方案
错误 MSB8036 找不到 Windows SDK 版本8.1。
C1083: 无法打开包括文件: “stddef.h”: No such file or directory
vc++目录-->包含目录下拉条点击编辑,增加了路径:C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt
⑥把生成的Box2D.lib和Box2D文件夹分别放入新建的lib和include文件夹
⑦此时Box2D已经配置完成。只需要在工程中想SFML一样添加Box2D就可以使用。
2、准备游戏需要的背景图
3、渲染一个800x600的屏幕
#include<SFML/Graphics.hpp>
#include<Box2D/Box2D.h>
using namespace sf;
const float SCALE = 30.f;
const float DEG = 57.29577f;
b2Vec2 Gravity(0.f, 9.8f);
b2World World(Gravity);
int main()
{
RenderWindow window(VideoMode(800, 600), "Volleyball Game!");
window.setFramerateLimit(60);
Texture t1;
Texture t2;
t1.loadFromFile("./Resources/images/background.PNG");
t2.loadFromFile("./Resources/images/ball.png");
Sprite sBackground(t1);
Sprite sBall(t2);
sBall.setOrigin(32, 32);
//box2d
b2PolygonShape shape;
shape.SetAsBox(30 / SCALE, 30 / SCALE);
b2BodyDef bdef;
bdef.type = b2_dynamicBody;
//ball
bdef.position.Set(5, 1);
b2CircleShape circle;
circle.m_radius = 32 / SCALE;
b2Body *b = World.CreateBody(&bdef);
b2FixtureDef fdef;
fdef.shape = &circle;
fdef.restitution = 0.95;
fdef.density = 0.2;
b->CreateFixture(&fdef);
b->SetUserData("ball");
while (window.isOpen())
{
Event e;
while (window.pollEvent(e))
{
if (e.type == Event::Closed)
{
window.close();
}
}
World.Step(1 / 60.f, 8, 3);
//Draw
window.draw(sBackground);
for (b2Body* it = World.GetBodyList(); it != 0; it = it->GetNext())
{
b2Vec2 pos = it->GetPosition();
float angle = it->GetAngle();
if (it->GetUserData() == "ball")
{
sBall.setPosition(pos.x*SCALE, pos.y*SCALE);
sBall.setRotation(angle*DEG);
window.draw(sBall);
}
}
window.display();
}
return 0;
}
4、添加玩家完善游戏逻辑
#include<SFML/Graphics.hpp>
#include<Box2D/Box2D.h>
using namespace sf;
const float SCALE = 30.f;
const float DEG = 57.29577f;
b2Vec2 Gravity(0.f, 9.8f);
b2World World(Gravity);
void setWall(int x, int y, int w, int h)
{
b2PolygonShape gr;
gr.SetAsBox(w / SCALE, h / SCALE);
b2BodyDef bdef;
bdef.position.Set(x / SCALE, y / SCALE);
b2Body * b_ground = World.CreateBody(&bdef);
b_ground->CreateFixture(&gr, 1);
}
int main()
{
RenderWindow window(VideoMode(800, 600), "Volleyball Game!");
window.setFramerateLimit(60);
Texture t1;
Texture t2;
Texture t3;
t1.loadFromFile("./Resources/images/background.PNG");
t2.loadFromFile("./Resources/images/ball.png");
t3.loadFromFile("./Resources/images/blobby.png");
t1.setSmooth(true);
t2.setSmooth(true);
t3.setSmooth(true);
Sprite sBackground(t1);
Sprite sBall(t2);
Sprite sPlayer(t3);
sPlayer.setOrigin(75 / 2, 90 / 2);
sBall.setOrigin(32, 32);
//box2d
setWall(400, 520, 2000, 10);
setWall(400, 450, 10, 170);
setWall(0, 0, 10, 2000);
setWall(800, 0, 10, 2000);
b2PolygonShape shape;
shape.SetAsBox(30 / SCALE, 30 / SCALE);
b2BodyDef bdef;
bdef.type = b2_dynamicBody;
//players
b2Body *pBody[2];
for (int i = 0; i < 2; i++)
{
bdef.position.Set(20 * i, 2);
b2CircleShape circle;
circle.m_radius = 32 / SCALE;
circle.m_p.Set(0, 13 / SCALE);
pBody[i] = World.CreateBody(&bdef);
pBody[i]->CreateFixture(&circle, 5);
circle.m_radius = 25 / SCALE;
circle.m_p.Set(0, -20 / SCALE);
pBody[i]->CreateFixture(&circle, 5);
pBody[i]->SetFixedRotation(true);
}
pBody[0]->SetUserData("player1");
pBody[1]->SetUserData("player2");
//ball
bdef.position.Set(5, 1);
b2CircleShape circle;
circle.m_radius = 32 / SCALE;
b2Body *b = World.CreateBody(&bdef);
b2FixtureDef fdef;
fdef.shape = &circle;
fdef.restitution = 0.95;
fdef.density = 0.2;
b->CreateFixture(&fdef);
b->SetUserData("ball");
bool onGround = 0;
while (window.isOpen())
{
Event e;
while (window.pollEvent(e))
{
if (e.type == Event::Closed)
{
window.close();
}
}
for (int n = 0; n < 2; n++)
{
World.Step(1 / 60.f, 8, 3);
}
//player1
b2Vec2 pos = pBody[0]->GetPosition();
b2Vec2 vel = pBody[0]->GetLinearVelocity();
if (Keyboard::isKeyPressed(Keyboard::Right))
{
vel.x = 5;
}
if (Keyboard::isKeyPressed(Keyboard::Left))
{
vel.x = -5;
}
if (Keyboard::isKeyPressed(Keyboard::Up))
{
if (pos.y*SCALE >= 463)
{
vel.y = -13;
}
}
if (!Keyboard::isKeyPressed(Keyboard::Right))
{
if (!Keyboard::isKeyPressed(Keyboard::Left))
{
vel.x = 0;
}
}
pBody[0]->SetLinearVelocity(vel);
//player2
pos = pBody[1]->GetPosition();
vel = pBody[1]->GetLinearVelocity();
if (Keyboard::isKeyPressed(Keyboard::D))
{
vel.x = 5;
}
if (Keyboard::isKeyPressed(Keyboard::A))
{
vel.x = -5;
}
if (Keyboard::isKeyPressed(Keyboard::W))
{
if (pos.y*SCALE >= 463)
{
vel.y = -13;
}
}
if (!Keyboard::isKeyPressed(Keyboard::D))
{
if (!Keyboard::isKeyPressed(Keyboard::A))
{
vel.x = 0;
}
}
pBody[1]->SetLinearVelocity(vel);
//ball max speed
vel = b->GetLinearVelocity();
if (vel.Length() > 15)
{
b->SetLinearVelocity(15 / vel.Length() * vel);
}
//Draw
window.draw(sBackground);
for (b2Body* it = World.GetBodyList(); it != 0; it = it->GetNext())
{
b2Vec2 pos = it->GetPosition();
float angle = it->GetAngle();
if(it->GetUserData() == "player1")
{
sPlayer.setPosition(pos.x*SCALE, pos.y*SCALE);
sPlayer.setRotation(angle*DEG);
sPlayer.setColor(Color::Red);
window.draw(sPlayer);
}
if (it->GetUserData() == "player2")
{
sPlayer.setPosition(pos.x*SCALE, pos.y*SCALE);
sPlayer.setRotation(angle*DEG);
sPlayer.setColor(Color::Green);
window.draw(sPlayer);
}
if (it->GetUserData() == "ball")
{
sBall.setPosition(pos.x*SCALE, pos.y*SCALE);
sBall.setRotation(angle*DEG);
window.draw(sBall);
}
}
window.display();
}
return 0;
}
结果图: