gpt4 book ai didi

java - 静止后 JMonkey 物理对象被卡住在适当的位置

转载 作者:行者123 更新时间:2023-11-30 04:04:50 26 4
gpt4 key购买 nike

这是 JME3 教程中 HelloPhysics 的一个非常简单的扩展。当您点击一 block 砖 block 时,该砖 block 就会从游戏和物理空间中移除。如果你移走砖 block 的速度足够快,在墙沉降之前,它就会像你想象的那样崩塌,但如果你在移走砖 block 之前稍等一下,就什么也不会发生。

我认为物体停止移动后物理功能会关闭,以防止过度抖动,并且我想再次手动启动它。

package jme3test.helloworld;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.material.Material;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;


/**
* Example 12 - how to give objects physical properties so they bounce and fall.
* @author base code by double1984, updated by zathras
*/
class HelloPhysics extends SimpleApplication {

public static void main(String args[]) {
HelloPhysics app = new HelloPhysics();
app.start();
}

/** Prepare the Physics Application State (jBullet) */
private BulletAppState bulletAppState;

/** Prepare Materials */
Material wall_mat;
Material stone_mat;
Material floor_mat;

/** Prepare geometries and physical nodes for bricks and cannon balls. */
Node removables;
private RigidBodyControl brick_phy;
private static final Box box;
private RigidBodyControl ball_phy;
private static final Sphere sphere;
private RigidBodyControl floor_phy;
private static final Box floor;

/** dimensions used for bricks and wall */
private static final float brickLength = 0.48f;
private static final float brickWidth = 0.24f;
private static final float brickHeight = 0.12f;

static {
/** Initialize the cannon ball geometry */
sphere = new Sphere(32, 32, 0.4f, true, false);
sphere.setTextureMode(TextureMode.Projected);
/** Initialize the brick geometry */
box = new Box(Vector3f.ZERO, brickLength, brickHeight, brickWidth);
box.scaleTextureCoordinates(new Vector2f(1f, .5f));
/** Initialize the floor geometry */
floor = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
floor.scaleTextureCoordinates(new Vector2f(3, 6));
}

@Override
public void simpleInitApp() {
/** Set up Physics Game */
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);

/** Configure cam to look at scene */
cam.setLocation(new Vector3f(0, 4f, 6f));
cam.lookAt(new Vector3f(2, 2, 0), Vector3f.UNIT_Y);
/** Add InputManager action: Left click triggers shooting. */
inputManager.addMapping("shoot",
new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(actionListener, "shoot");
removables = new Node("Removables");
rootNode.attachChild(removables);
/** Initialize the scene, materials, and physics space */
initMaterials();
initWall();
initFloor();
initKeys();
initCrossHairs();
}
/** Declaring the "Shoot" action and mapping to its triggers. */
private void initKeys() {
inputManager.addMapping("Shoot",
new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar
new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); // trigger 2: left-button click
inputManager.addListener(actionListener, "Shoot");
}
/** Initialize the materials used in this scene. */
public void initMaterials() {
wall_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg");
key.setGenerateMips(true);
Texture tex = assetManager.loadTexture(key);
wall_mat.setTexture("ColorMap", tex);

stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
key2.setGenerateMips(true);
Texture tex2 = assetManager.loadTexture(key2);
stone_mat.setTexture("ColorMap", tex2);

floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.jpg");
key3.setGenerateMips(true);
Texture tex3 = assetManager.loadTexture(key3);
tex3.setWrap(WrapMode.Repeat);
floor_mat.setTexture("ColorMap", tex3);
}

/** Make a solid floor and add it to the scene. */
public void initFloor() {
Geometry floor_geo = new Geometry("Floor", floor);
floor_geo.setMaterial(floor_mat);
floor_geo.setLocalTranslation(0, -0.1f, 0);
this.rootNode.attachChild(floor_geo);
/* Make the floor physical with mass 0.0f! */
floor_phy = new RigidBodyControl(0.0f);
floor_geo.addControl(floor_phy);
bulletAppState.getPhysicsSpace().add(floor_phy);
}

/** This loop builds a wall out of individual bricks. */
public void initWall() {
float startpt = brickLength / 4;
float height = 0;
for (int j = 0; j < 15; j++) {
for (int i = 0; i < 6; i++) {
Vector3f vt =
new Vector3f(i * brickLength * 2 + startpt, brickHeight + height, 0);
makeBrick(vt);
}
startpt = -startpt;
height += 2 * brickHeight;
}
}
/** This method creates one individual physical brick. */
public void makeBrick(Vector3f loc) {
/** Create a brick geometry and attach to scene graph. */
Geometry brick_geo = new Geometry("brick", box);
brick_geo.setMaterial(wall_mat);
/** Position the brick geometry */
brick_geo.setLocalTranslation(loc);
/** Make brick physical with a mass > 0.0f. */
brick_phy = new RigidBodyControl(2f);

/** Add physical brick to physics space. */
brick_geo.addControl(brick_phy);
bulletAppState.getPhysicsSpace().add(brick_phy);
removables.attachChild(brick_geo);

}

/** This method creates one individual physical cannon ball.
* By defaul, the ball is accelerated and flies
* from the camera position in the camera direction.*/
public void makeCannonBall() {
/** Create a cannon ball geometry and attach to scene graph. */
Geometry ball_geo = new Geometry("cannon ball", sphere);
ball_geo.setMaterial(stone_mat);
rootNode.attachChild(ball_geo);
/** Position the cannon ball */
ball_geo.setLocalTranslation(cam.getLocation());
/** Make the ball physcial with a mass > 0.0f */
ball_phy = new RigidBodyControl(1f);
/** Add physical ball to physics space. */
ball_geo.addControl(ball_phy);
bulletAppState.getPhysicsSpace().add(ball_phy);
/** Accelerate the physcial ball to shoot it. */
ball_phy.setLinearVelocity(cam.getDirection().mult(25));
}
private ActionListener actionListener = new ActionListener() {

public void onAction(String name, boolean keyPressed, float tpf) {
if (name.equals("Shoot") && !keyPressed) {
// 1. Reset results list.
CollisionResults results = new CollisionResults();
// 2. Aim the ray from cam loc to cam direction.
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
// 3. Collect intersections between Ray and Shootables in results list.
removables.collideWith(ray, results);
// 4. Print the results
System.out.println("----- Collisions? " + results.size() + "-----");
for (int i = 0; i < results.size(); i++) {
// For each hit, we know distance, impact point, name of geometry.
float dist = results.getCollision(i).getDistance();
Vector3f pt = results.getCollision(i).getContactPoint();
String hit = results.getCollision(i).getGeometry().getName();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away.");
}
// 5. Use the results (we mark the hit object)
if (results.size() > 0) {
// The closest collision point is what was truly hit:
Geometry closest = results.getClosestCollision().getGeometry();
// Let's interact - we mark the hit with a red dot.

bulletAppState.getPhysicsSpace().remove(closest.getControl(0));
removables.detachChild(closest);
bulletAppState.getPhysicsSpace().clearForces();
bulletAppState.getPhysicsSpace().applyGravity();
System.out.println("removing a "+closest.getName());

}
}
}
};
/** A plus sign used as crosshairs to help the player with aiming.*/
protected void initCrossHairs() {
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // fake crosshairs :)
ch.setLocalTranslation( // center
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}
}

最佳答案

不移动 sleep 的对象

你最初的想法是正确的,当一个物体静止时,它就进入了 sleep 状态,这有很多原因;避免抖动是其中之一,但它也可以显着提高效率。

sleep 时,物体不会受到重力,因此如果您移除支撑它的物体,它不会注意到。

通常你不必担心这个;如果对象经历“物理引擎内部”的效果,例如涉及碰撞,它会自动唤醒。但是,如果您进行外部更改(例如删除对象),则必须担心唤醒对象。

唤醒可能受外部变化影响的对象

您可以通过调用.activate()来唤醒正在 hibernate 的对象。关于rigidBodyControl记住 sleep 是按每个对象进行的,因此您可能需要唤醒超过 1 个对象。

目前该程序并未跟踪所有 RigidBodyControl所以我添加了 HashSet<RigidBodyControl>()为了容纳它们,当将一 block 砖 block 添加到场景中时,它是 rigidBodyControl应该添加到这个哈希集中,当它从场景中删除时,它应该从哈希集中删除。

为了获得有效的解决方案,您应该只唤醒可能受到删除影响的对象,但在这种情况下,它可能是所有内容,我只是通过运行所有 HashSet<RigidBodyControl>() 来唤醒所有内容。并调用activate()在他们身上。

演示这些更改的完整程序如下所示

public class HelloPhysics extends SimpleApplication {

public static void main(String args[]) {
HelloPhysics app = new HelloPhysics();
app.start();
}

/** Prepare the Physics Application State (jBullet) */
private BulletAppState bulletAppState;

/** Prepare Materials */
Material wall_mat;
Material stone_mat;
Material floor_mat;

/** Prepare geometries and physical nodes for bricks and cannon balls. */
Node removables;

private static final Box box;
private RigidBodyControl ball_phy;
private static final Sphere sphere;
private RigidBodyControl floor_phy;
private static final Box floor;

private static Collection<RigidBodyControl> objectsThatNeedWaking=new HashSet<RigidBodyControl>();

/** dimensions used for bricks and wall */
private static final float brickLength = 0.48f;
private static final float brickWidth = 0.24f;
private static final float brickHeight = 0.12f;

static {
/** Initialize the cannon ball geometry */
sphere = new Sphere(32, 32, 0.4f, true, false);
sphere.setTextureMode(TextureMode.Projected);
/** Initialize the brick geometry */
box = new Box(Vector3f.ZERO, brickLength, brickHeight, brickWidth);
box.scaleTextureCoordinates(new Vector2f(1f, .5f));
/** Initialize the floor geometry */
floor = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
floor.scaleTextureCoordinates(new Vector2f(3, 6));
}

@Override
public void simpleInitApp() {
/** Set up Physics Game */
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);

/** Configure cam to look at scene */
cam.setLocation(new Vector3f(0, 4f, 6f));
cam.lookAt(new Vector3f(2, 2, 0), Vector3f.UNIT_Y);
/** Add InputManager action: Left click triggers shooting. */
inputManager.addMapping("shoot",
new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(actionListener, "shoot");
removables = new Node("Removables");
rootNode.attachChild(removables);
/** Initialize the scene, materials, and physics space */
initMaterials();
initWall();
initFloor();
initKeys();
initCrossHairs();
}
/** Declaring the "Shoot" action and mapping to its triggers. */
private void initKeys() {
inputManager.addMapping("Shoot",
new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar
new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); // trigger 2: left-button click
inputManager.addListener(actionListener, "Shoot");
}
/** Initialize the materials used in this scene. */
public void initMaterials() {
wall_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg");
key.setGenerateMips(true);
Texture tex = assetManager.loadTexture(key);
wall_mat.setTexture("ColorMap", tex);

stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
key2.setGenerateMips(true);
Texture tex2 = assetManager.loadTexture(key2);
stone_mat.setTexture("ColorMap", tex2);

floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.jpg");
key3.setGenerateMips(true);
Texture tex3 = assetManager.loadTexture(key3);
tex3.setWrap(WrapMode.Repeat);
floor_mat.setTexture("ColorMap", tex3);
}

/** Make a solid floor and add it to the scene. */
public void initFloor() {
Geometry floor_geo = new Geometry("Floor", floor);
floor_geo.setMaterial(floor_mat);
floor_geo.setLocalTranslation(0, -0.1f, 0);
this.rootNode.attachChild(floor_geo);
/* Make the floor physical with mass 0.0f! */
floor_phy = new RigidBodyControl(0.0f);
floor_geo.addControl(floor_phy);
bulletAppState.getPhysicsSpace().add(floor_phy);
}

/** This loop builds a wall out of individual bricks. */
public void initWall() {
float startpt = brickLength / 4;
float height = 0;
for (int j = 0; j < 15; j++) {
for (int i = 0; i < 6; i++) {
Vector3f vt =
new Vector3f(i * brickLength * 2 + startpt, brickHeight + height, 0);
makeBrick(vt);
}
startpt = -startpt;
height += 2 * brickHeight;
}
}
/** This method creates one individual physical brick. */
public void makeBrick(Vector3f loc) {
/** Create a brick geometry and attach to scene graph. */
Geometry brick_geo = new Geometry("brick", box);
brick_geo.setMaterial(wall_mat);
/** Position the brick geometry */
brick_geo.setLocalTranslation(loc);
/** Make brick physical with a mass > 0.0f. */
RigidBodyControl brick_phy = new RigidBodyControl(2f);

objectsThatNeedWaking.add(brick_phy);


/** Add physical brick to physics space. */
brick_geo.addControl(brick_phy);


bulletAppState.getPhysicsSpace().add(brick_phy);
removables.attachChild(brick_geo);

}

/** This method creates one individual physical cannon ball.
* By defaul, the ball is accelerated and flies
* from the camera position in the camera direction.*/
public void makeCannonBall() {
/** Create a cannon ball geometry and attach to scene graph. */
Geometry ball_geo = new Geometry("cannon ball", sphere);
ball_geo.setMaterial(stone_mat);
rootNode.attachChild(ball_geo);
/** Position the cannon ball */
ball_geo.setLocalTranslation(cam.getLocation());
/** Make the ball physcial with a mass > 0.0f */
ball_phy = new RigidBodyControl(1f);
/** Add physical ball to physics space. */
ball_geo.addControl(ball_phy);
bulletAppState.getPhysicsSpace().add(ball_phy);
/** Accelerate the physcial ball to shoot it. */
ball_phy.setLinearVelocity(cam.getDirection().mult(25));
}
private ActionListener actionListener = new ActionListener() {

public void onAction(String name, boolean keyPressed, float tpf) {
if (name.equals("Shoot") && !keyPressed) {
// 1. Reset results list.
CollisionResults results = new CollisionResults();
// 2. Aim the ray from cam loc to cam direction.
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
// 3. Collect intersections between Ray and Shootables in results list.
removables.collideWith(ray, results);
// 4. Print the results
System.out.println("----- Collisions? " + results.size() + "-----");
for (int i = 0; i < results.size(); i++) {
// For each hit, we know distance, impact point, name of geometry.
float dist = results.getCollision(i).getDistance();
Vector3f pt = results.getCollision(i).getContactPoint();
String hit = results.getCollision(i).getGeometry().getName();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away.");
}
// 5. Use the results (we mark the hit object)
if (results.size() > 0) {
// The closest collision point is what was truly hit:
Geometry closest = results.getClosestCollision().getGeometry();
// Let's interact - we mark the hit with a red dot.

bulletAppState.getPhysicsSpace().remove(closest.getControl(0));
objectsThatNeedWaking.remove(closest.getControl(0));
removables.detachChild(closest);
bulletAppState.getPhysicsSpace().clearForces();
bulletAppState.getPhysicsSpace().applyGravity();
System.out.println("removing a "+closest.getName());

for(RigidBodyControl wakeMeUp: objectsThatNeedWaking){
wakeMeUp.activate();
}

}
}
}
};
/** A plus sign used as crosshairs to help the player with aiming.*/
protected void initCrossHairs() {
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // fake crosshairs :)
ch.setLocalTranslation( // center
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}
}

关于java - 静止后 JMonkey 物理对象被卡住在适当的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21011676/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com