我正在使用 libgdx api (java) 中包含的 box2d
我正在使用一个矩形 box2d 主体作为传感器,用于检测 4 个方向(向上、向下、向左、向右倾斜 90°)的剑刃碰撞(使用身体作为传感器)。因此,为了向上切割,我基本上创建了一个新的矩形 box2d 主体并每次设置其起始位置:
swordBodyDef.position.set(playerBody.getPosition().x, playerBody.getPosition().y + 4);
仅此一项就会导致玩家将剑笔直向上(12 点钟方向)。但它应该从 12:10 开始(然后通过施加力移动到 11:50)所以为了在玩家面前将剑的天使设置为 12:10,我使用以下代码:
swordBody.setTransform(playerBody.getPosition().x, playerBody.getPosition().y + 4 ), (float)Math.toRadians(-125));
整个剑术有效,但每次我击中敌人时,命中计为 2。我有一种感觉,当我在 12:00(setPosition)创建剑时,它已经参与物理模拟并计为命中。因此,当我通过 setTransform 方法将其调整为正确的角度(12:10)时,它将再次命中。至少当我不通过 setTransform 方法更改天使时它可以工作。我认为如果有一种方法可以原子地设置剑的位置和天使,它会起作用。
任何关于我如何防止双重打击的想法都值得赞赏:)
编辑: 我在有关旋转关节的 box2d 手册中找到以下内容:“要指定旋转,您需要在世界空间中提供两个物体和一个锚点。初始化函数假定物体已经在正确的位置。 ”这个与我所做的完全相反。首先,我创建了 RevoluteJoint,然后设置了剑身的位置(所需的天使)。所以很明显这会导致物理学上的麻烦,但我仍然不知道如何正确设置剑身的初始角度
EDIT2: 我使用了一些解决方法来解决 iforce2d 建议的问题。该问题仅出现在以下world.step所以我正在做的是通过禁用swordBody
swordBody.setActive(false);
对于这个游戏循环,并在下一个游戏循环中将其设置为 true。这有点难看,但至少它有效。
向上斜线的完整 box2d 代码(12:10 到 11:50):
//if the sword is active (slashing)
if(swordBody != null)
{
//destroy swordbody when it reaches a certain angel (11:50)
if(swordBody.getAngle() >= (float)Math.toRadians(50))
{
for (Body box : swordBody_List)
GameplayScreen.world.destroyBody(box);
swordBody_List.clear();
swordBody = null;
}
}
//construct a sword, set its position over the player's head, join it to the player's body, set the sword's angel to 12:10 and the
else if (playerInput.getMoveDirection() == Action.HIT)
{
//start state of hitting
hitUp = true;
//a short delay before the next hit starts
if (hitTestUpdateTimer < .50f)
{
hitTestUpdateTimer += Gdx.graphics.getDeltaTime();
}
else
{
//Player's sword (box2d collision detection)
BodyDef swordBodyDef = new BodyDef();
swordBodyDef.type = BodyDef.BodyType.DynamicBody;
swordBodyDef.position.set(playerBody.getPosition().x, playerBody.getPosition().y + 4);
swordBody = GameplayScreen.world.createBody(swordBodyDef);
swordBody.setUserData(this);
PolygonShape swordShape = new PolygonShape();
swordShape.setAsBox(.1f , 1.3f); //sword size
FixtureDef swordFixtureDef = new FixtureDef();
swordFixtureDef.shape = swordShape;
swordFixtureDef.density = 1f;
swordFixtureDef.isSensor = true;
swordBody.createFixture(swordFixtureDef);
swordShape.dispose();
swordBody_List.add(swordBody);
//Connection between sword & player
swordJointDef = new RevoluteJointDef();
swordJointDef.initialize(playerBody, swordBody, playerBody.getPosition().sub(new Vector2(0, -2)));
@SuppressWarnings("unused")
RevoluteJoint swordRevJointDef = (RevoluteJoint)GameplayScreen.world.createJoint(swordJointDef);
//set the angel of the sword to 12:10 when the hit starts
swordBody.setTransform(new Vector2(playerBody.getPosition().x, playerBody.getPosition().y + 4 ), (float)Math.toRadians(-125));
//rotate the sword (left-direction)
swordBody.applyTorque(1600f);
//Set update timer back to zero
hitTestUpdateTimer = 0;
hitUp = false; //state of hitting is finished
}
}