I replicated the TestBoneRagdoll demo in hopes that I would be able to make two enemies and shoot them on both two different locations. However, as you can see on my code (below), the ogres stay at the same position. How do I make them placed on a different position? Also, if I hit one of them, both of them dies. How can I make this properly?
Here’s the code:
package jme3test.bullet;
import com.jme3.animation.*;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.RagdollCollisionListener;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.KinematicRagdollControl;
import com.jme3.bullet.control.RigidBodyControl;
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.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.debug.SkeletonDebugger;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.texture.Texture;
public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener, AnimEventListener {
private BulletAppState bulletAppState;
Material matBullet;
Node model;
Node orc_model;
KinematicRagdollControl ragdoll;
KinematicRagdollControl orc;
float bulletSize = 1f;
Material mat;
Material mat3;
Material orcMat;
private Sphere bullet;
private SphereCollisionShape bulletCollisionShape;
public static void main(String[] args) {
TestBoneRagdoll app = new TestBoneRagdoll();
app.start();
}
public void simpleInitApp() {
initCrossHairs();
initMaterial();
cam.setLocation(new Vector3f(0.26924422f, 6.646658f, 22.265987f));
cam.setRotation(new Quaternion(-2.302544E-4f, 0.99302495f, -0.117888905f, -0.0019395084f));
bulletAppState = new BulletAppState();
bulletAppState.setEnabled(true);
stateManager.attach(bulletAppState);
bullet = new Sphere(32, 32, 1.0f, true, false);
bullet.setTextureMode(TextureMode.Projected);
bulletCollisionShape = new SphereCollisionShape(1.0f);
PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());
setupLight();
model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
orc_model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
//debug view
AnimControl control = model.getControl(AnimControl.class);
SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton", control.getSkeleton());
Material mat2 = new Material(getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
mat2.getAdditionalRenderState().setWireframe(true);
mat2.setColor("Color", ColorRGBA.Green);
mat2.getAdditionalRenderState().setDepthTest(false);
skeletonDebug.setMaterial(mat2);
skeletonDebug.setLocalTranslation(model.getLocalTranslation());
AnimControl orc_control = orc_model.getControl(AnimControl.class);
SkeletonDebugger orc_skeletonDebug = new SkeletonDebugger("skeleton", control.getSkeleton());
Material mater3 = new Material(getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
mater3.getAdditionalRenderState().setWireframe(true);
mater3.setColor("Color", ColorRGBA.Blue);
mater3.getAdditionalRenderState().setDepthTest(false);
orc_skeletonDebug.setMaterial(mater3);
orc_skeletonDebug.setLocalTranslation(orc_model.getLocalTranslation());
//Note: PhysicsRagdollControl is still TODO, constructor will change
ragdoll = new KinematicRagdollControl(0.5f);
setupSinbad(ragdoll);
ragdoll.addCollisionListener(this);
model.addControl(ragdoll);
orc = new KinematicRagdollControl(0.5f);
setupOrc(orc);
orc.addCollisionListener(this);
orc_model.addControl(orc);
float eighth_pi = FastMath.PI * 0.125f;
ragdoll.setJointLimit("Waist", eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi);
ragdoll.setJointLimit("Chest", eighth_pi, eighth_pi, 0, 0, eighth_pi, eighth_pi);
orc.setJointLimit("Waist", eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi);
orc.setJointLimit("Chest", eighth_pi, eighth_pi, 0, 0, eighth_pi, eighth_pi);
//Oto's head is almost rigid
// ragdoll.setJointLimit("head", 0, 0, eighth_pi, -eighth_pi, 0, 0);
getPhysicsSpace().add(ragdoll);
getPhysicsSpace().add(orc);
speed = 1.3f;
rootNode.attachChild(model);
rootNode.attachChild(orc_model);
// rootNode.attachChild(skeletonDebug);
flyCam.setMoveSpeed(50);
animChannel = control.createChannel();
animChannel.setAnim("Dance");
animChannelX = orc_control.createChannel();
animChannelX.setAnim("Dance");
control.addListener(this);
orc_control.addListener(this);
inputManager.addListener(new ActionListener() {
public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals("toggle") && isPressed) {
Vector3f v = new Vector3f();
Vector3f u = new Vector3f();
v.set(model.getLocalTranslation());
v.set(orc_model.getLocalTranslation());
v.y = 0;
u.y = 0;
model.setLocalTranslation(v);
orc_model.setLocalTranslation(u);
Quaternion q = new Quaternion();
float[] angles = new float[3];
Quaternion r = new Quaternion();
float[] r_angles = new float[3];
model.getLocalRotation().toAngles(angles);
orc_model.getLocalRotation().toAngles(r_angles);
q.fromAngleAxis(angles[1], Vector3f.UNIT_Y);
r.fromAngleAxis(angles[1], Vector3f.UNIT_Y);
model.setLocalRotation(q);
orc_model.setLocalRotation(r);
if (angles[0] < 0) {
animChannel.setAnim("StandUpBack");
ragdoll.blendToKinematicMode(0.5f);
orc.blendToKinematicMode(0.5f);
} else {
animChannel.setAnim("StandUpFront");
ragdoll.blendToKinematicMode(0.5f);
orc.blendToKinematicMode(0.5f);
}
}
if (name.equals("bullet+") && isPressed) {
bulletSize += 0.1f;
}
if (name.equals("bullet-") && isPressed) {
bulletSize -= 0.1f;
}
if (name.equals("stop") && isPressed) {
ragdoll.setEnabled(!ragdoll.isEnabled());
ragdoll.setRagdollMode();
orc.setEnabled(!orc.isEnabled());
orc.setRagdollMode();
}
if (name.equals("shoot") && !isPressed) {
Geometry bulletg = new Geometry("bullet", bullet);
bulletg.setMaterial(matBullet);
bulletg.setLocalTranslation(cam.getLocation());
bulletg.setLocalScale(bulletSize);
bulletCollisionShape = new SphereCollisionShape(bulletSize);
RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10);
bulletNode.setCcdMotionThreshold(0.001f);
bulletNode.setLinearVelocity(cam.getDirection().mult(80));
bulletg.addControl(bulletNode);
rootNode.attachChild(bulletg);
getPhysicsSpace().add(bulletNode);
}
if (name.equals("boom") && !isPressed) {
Geometry bulletg = new Geometry("bullet", bullet);
bulletg.setMaterial(matBullet);
bulletg.setLocalTranslation(cam.getLocation());
bulletg.setLocalScale(bulletSize);
bulletCollisionShape = new SphereCollisionShape(bulletSize);
BombControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1);
bulletNode.setForceFactor(8);
bulletNode.setExplosionRadius(20);
bulletNode.setCcdMotionThreshold(0.001f);
bulletNode.setLinearVelocity(cam.getDirection().mult(180));
bulletg.addControl(bulletNode);
rootNode.attachChild(bulletg);
getPhysicsSpace().add(bulletNode);
}
}
}, "toggle", "shoot", "stop", "bullet+", "bullet-", "boom");
inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addMapping("boom", new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
inputManager.addMapping("stop", new KeyTrigger(KeyInput.KEY_H));
inputManager.addMapping("bullet-", new KeyTrigger(KeyInput.KEY_COMMA));
inputManager.addMapping("bullet+", new KeyTrigger(KeyInput.KEY_PERIOD));
}
private void setupLight() {
DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
rootNode.addLight(dl);
}
private PhysicsSpace getPhysicsSpace() {
return bulletAppState.getPhysicsSpace();
}
public void initMaterial() {
matBullet = 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);
matBullet.setTexture("ColorMap", tex2);
}
protected void initCrossHairs() {
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // crosshairs
ch.setLocalTranslation( // center
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}
public void collide(Bone bone, PhysicsCollisionObject object, PhysicsCollisionEvent event) {
if (object.getUserObject() != null && object.getUserObject() instanceof Geometry) {
Geometry geom = (Geometry) object.getUserObject();
if ("Floor".equals(geom.getName())) {
return;
}
}
ragdoll.setRagdollMode();
orc.setRagdollMode();
}
private void setupSinbad(KinematicRagdollControl ragdoll) {
ragdoll.addBoneName("Ulna.L");
ragdoll.addBoneName("Ulna.R");
ragdoll.addBoneName("Chest");
ragdoll.addBoneName("Foot.L");
ragdoll.addBoneName("Foot.R");
ragdoll.addBoneName("Hand.R");
ragdoll.addBoneName("Hand.L");
ragdoll.addBoneName("Neck");
ragdoll.addBoneName("Root");
ragdoll.addBoneName("Stomach");
ragdoll.addBoneName("Waist");
ragdoll.addBoneName("Humerus.L");
ragdoll.addBoneName("Humerus.R");
ragdoll.addBoneName("Thigh.L");
ragdoll.addBoneName("Thigh.R");
ragdoll.addBoneName("Calf.L");
ragdoll.addBoneName("Calf.R");
ragdoll.addBoneName("Clavicle.L");
ragdoll.addBoneName("Clavicle.R");
}
private void setupOrc(KinematicRagdollControl orc) {
orc.addBoneName("Ulna.L");
orc.addBoneName("Ulna.R");
orc.addBoneName("Chest");
orc.addBoneName("Foot.L");
orc.addBoneName("Foot.R");
orc.addBoneName("Hand.R");
orc.addBoneName("Hand.L");
orc.addBoneName("Neck");
orc.addBoneName("Root");
orc.addBoneName("Stomach");
orc.addBoneName("Waist");
orc.addBoneName("Humerus.L");
orc.addBoneName("Humerus.R");
orc.addBoneName("Thigh.L");
orc.addBoneName("Thigh.R");
orc.addBoneName("Calf.L");
orc.addBoneName("Calf.R");
orc.addBoneName("Clavicle.L");
orc.addBoneName("Clavicle.R");
}
float elTime = 0;
boolean forward = true;
AnimControl animControl;
AnimChannel animChannel;
AnimControl animControlX;
AnimChannel animChannelX;
Vector3f direction = new Vector3f(0, 0, 1);
Quaternion rotate = new Quaternion().fromAngleAxis(FastMath.PI / 8, Vector3f.UNIT_Y);
boolean dance = true;
@Override
public void simpleUpdate(float tpf) {
}
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
if (channel.getAnimationName().equals("StandUpBack") || channel.getAnimationName().equals("StandUpFront")) {
channel.setLoopMode(LoopMode.DontLoop);
channel.setAnim("IdleTop", 5);
channel.setLoopMode(LoopMode.Loop);
}
}
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
}
}