Using setViewDirection can change direction
Using setWalkDirection can move
but On the move and swerve ,They’re all going on at the same time
The movement and swerve of the model is very not smoothness
How to correctly turn first in moving
This question is translated by translator
If you are willing to answer my question but don’t understand it, please point out the sentences you don’t understand
thanks
package net.jmecn;
import com.jme3.scene.debug.Arrow;
import com.jme3.input.ChaseCamera;
import com.jme3.anim.AnimComposer;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.collision.shapes.HullCollisionShape;
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.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
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;
import com.jme3.scene.control.CameraControl.ControlDirection;
import com.jme3.scene.CameraNode;
/**
* 按键发射小球轰击砖墙。
*
* @author yanmaoyuan
*
*/
public class HelloPhysics extends SimpleApplication implements ActionListener {
/**
* 开火,发射小球。鼠标左键触发。
*/
public final static String FIRE = "fire";
public final static String FORWARD = "forward";
public final static String BACKWARD = "backward";
public final static String LEFT = "left";
public final static String RIGHT = "right";
public final static String JUMP = "jump";
//方向控制器
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private Vector3f walkDirectioni = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
/**
* 显示或隐藏BulletAppState的debug形状。按空格键触发。
*/
public final static String DEBUG = "debug";
// 临时变量,用于保存摄像机的方向。避免在simpleUpdate中重复创建对象。
private Vector3f camDir = new Vector3f();
private Vector3f camLeft = new Vector3f();
/** 砖块的尺寸 */
private static final float brickLength = 0.48f;
private static final float brickWidth = 0.24f;
private static final float brickHeight = 0.12f;
private AnimComposer control;
private BulletAppState bulletAppState;
private Node character;
private ChaseCamera chaseCam;
@Override
public void simpleInitApp() {
createArrow(new Vector3f(5, 0, 0), ColorRGBA.Green);
createArrow(new Vector3f(0, 5, 0), ColorRGBA.Red);
createArrow(new Vector3f(0, 0, 5), ColorRGBA.Blue);
// cam.setLocation(new Vector3f(0, 4f, 6f));
// cam.lookAt(new Vector3f(2, 2, 0), Vector3f.UNIT_Y);
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
bulletAppState.setDebugEnabled(true);
// 初始化按键
initKeys();
// 初始化光照
initLight();
// 初始化场景
initScene();
}
/**
* 创建一个箭头
*
* @param vec3 箭头向量
* @param color 箭头颜色
*/
private void createArrow(Vector3f vec3, ColorRGBA color) {
// 创建材质,设定箭头的颜色
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", color);
// 创建几何物体,应用箭头网格。
Geometry geom = new Geometry("arrow", new Arrow(vec3));
geom.setMaterial(mat);
// 添加到场景中
rootNode.attachChild(geom);
}
@Override
public void onAction(String name, boolean isPressed, float tpf) {
// if (isPressed) {
// if (FIRE.equals(name)) {
// shootBall();
// } else if (DEBUG.equals(name)) {
// boolean debugEnabled = bulletAppState.isDebugEnabled();
// bulletAppState.setDebugEnabled(!debugEnabled);
// }
// }
if (DEBUG.equals(name) && isPressed) {
boolean debugEnabled = bulletAppState.isDebugEnabled();
bulletAppState.setDebugEnabled(!debugEnabled);
} else if (LEFT.equals(name)) {
left = isPressed;
} else if (RIGHT.equals(name)) {
right = isPressed;
} else if (FORWARD.equals(name)) {
up = isPressed;
} else if (BACKWARD.equals(name)) {
down = isPressed;
} else if (JUMP.equals(name) && isPressed) {
player.jump();
}
}
/**
* 初始化按键输入
*/
private void initKeys() {
inputManager.addMapping(FIRE, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addMapping(DEBUG, new KeyTrigger(KeyInput.KEY_F1));
inputManager.addMapping(LEFT, new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping(RIGHT, new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping(FORWARD, new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping(BACKWARD, new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping(JUMP, new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(this, FIRE, DEBUG,LEFT,RIGHT,FORWARD,BACKWARD,JUMP);
}
/**
* 初始化光照
*/
private void initLight() {
// 环境光
AmbientLight ambient = new AmbientLight();
ambient.setColor(new ColorRGBA(0.3f, 0.3f, 0.3f, 1f));
// 阳光
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-1, -2, -3).normalizeLocal());
rootNode.addLight(ambient);
rootNode.addLight(sun);
}
/**
* 初始化场景
*/
private void initScene() {
model();
makeFloor();
//makeWall();
}
/**
* 制作地板
*/
private void makeFloor() {
// 网格
float radius = 100f;// 胶囊半径0.3米
float height = 0.1f;// 胶囊身高1.8米
float stepHeight = 100f;// 角色步高0.5米
Box floor = new Box(radius, height, stepHeight);
floor.scaleTextureCoordinates(new Vector2f(3, 6));
// 材质
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
Texture tex = assetManager.loadTexture("Interface/pic.png");
tex.setWrap(WrapMode.Repeat);
mat.setTexture("ColorMap", tex);
// 几何体
Geometry geom = new Geometry("floor", floor);
geom.setMaterial(mat);
geom.setLocalTranslation(0, -1.8f, 0);// 将地板下移一定距离,让表面和xoz平面重合。
// 刚体
RigidBodyControl rigidBody = new RigidBodyControl(0);
geom.addControl(rigidBody);
rigidBody.setCollisionShape(new BoxCollisionShape(new Vector3f(radius, height, stepHeight)));
rootNode.attachChild(geom);
bulletAppState.getPhysicsSpace().add(rigidBody);
}
/**
* 建造一堵墙
*/
private void makeWall() {
// 利用for循环生成一堵由众多砖块组成的墙体。
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;
}
}
private void model() {
float radius = 0.5f;// 胶囊半径0.3米
float height = 3.3f;// 胶囊身高1.8米
float stepHeight = 0.5f;// 角色步高0.5米
//模型
character = new Node("Character");
Node model = (Node)assetManager.loadModel("Textures/jisi/Test/hecheng.j3o");
model.move(0, -(height/2+radius), 0);
//model.scale(1.8f);
character.attachChild(model);// 挂到角色根节点下
rootNode.attachChild(character);
control = model.getControl(AnimComposer.class);
control.setCurrentAction("walk");
control.setGlobalSpeed(2f);
// Geometry submesh = (Geometry) model.getChild("ç½æ ¼.003_4");
// HullCollisionShape hullCollisionShape = new HullCollisionShape(submesh.getMesh());
// //刚体
// RigidBodyControl rigidBody = new RigidBodyControl(hullCollisionShape,0f);
// rigidBody.setCollisionShape(new BoxCollisionShape(new Vector3f(10f, 0.1f, 5f)));
// bulletAppState.getPhysicsSpace().add(rigidBody);
// 使用胶囊体作为玩家的碰撞形状
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(radius, height, 1);
// 使用CharacterControl来控制玩家物体
player = new CharacterControl(capsuleShape, stepHeight);
player.setJumpSpeed(10);// 起跳速度
player.setFallSpeed(55);// 坠落速度
player.setGravity(9.8f * 3);// 重力加速度
player.setPhysicsLocation(new Vector3f(10f, 10f, 0));// 位置
character.addControl(player);
bulletAppState.getPhysicsSpace().add(player);
// Disable the default flyby cam
// Disable the default flyby cam
flyCam.setEnabled(false);
// Enable a chase cam for this target (typically the player).
chaseCam = new ChaseCamera(cam, model, inputManager);
System.err.println(cam.getLocation());
chaseCam.setSmoothMotion(false);
chaseCam.setTrailingEnabled(true);
// Disable the default flyby cam
// flyCam.setEnabled(false);
// //create the camera Node
// CameraNode camNode = new CameraNode("CamNode", cam);
// //This mode means that camera copies the movements of the target:
// camNode.setControlDir(ControlDirection.SpatialToCamera);
// //Attach the camNode to the target:
// character.attachChild(camNode);
// //Move camNode, e.g. behind and above the target:
// camNode.setLocalTranslation(new Vector3f(10, 5, -5));
// //Rotate the camNode to look at the target:
// camNode.lookAt(model.getLocalTranslation(), Vector3f.UNIT_Y);
}
@Override
public void simpleUpdate(float tpf) {
camDir.set(cam.getDirection()).multLocal(0.7f);
camLeft.set(cam.getLeft()).multLocal(0.3f);
walkDirection.set(0, 0, 0);
// 计算运动方向
boolean changed = false;
if (left) {
walkDirectioni.addLocal(camLeft);
walkDirection.addLocal(camLeft);
changed = true;
}
if (right) {
walkDirectioni.addLocal(camLeft.negate());
walkDirection.addLocal(camLeft.negate());
changed = true;
}
if (up) {
walkDirectioni.addLocal(camDir);
walkDirection.addLocal(camDir);
changed = true;
}
if (down) {
walkDirectioni.addLocal(camDir.negate());
walkDirection.addLocal(camDir.negate());
changed = true;
}
if (changed) {
walkDirection.y = 0;// 将行走速度的方向限制在水平面上。
walkDirection.normalizeLocal();// 单位化
walkDirection.multLocal(0.3f);// 改变速率
walkDirectioni.y = 0;// 将行走速度的方向限制在水平面上。
walkDirectioni.normalizeLocal();// 单位化
walkDirectioni.multLocal(10f);// 改变速率
}
// System.err.println(walkDirectioni);
player.setWalkDirection(walkDirection);
player.setViewDirection(walkDirectioni);
// cam.setLocation(player.getPhysicsLocation());
}
/**
* 在指定位置放置一个物理砖块
*
* @param loc
* 砖块的位置
*/
private void makeBrick(Vector3f loc) {
// 网格
Box box = new Box(brickLength, brickHeight, brickWidth);
box.scaleTextureCoordinates(new Vector2f(1f, .5f));
// 材质
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
Texture tex = assetManager.loadTexture("Interface/pic.png");
mat.setTexture("ColorMap", tex);
// 几何体
Geometry geom = new Geometry("brick", box);
geom.setMaterial(mat);
geom.setLocalTranslation(loc);// 把砖块放在指定位置
// 刚体
RigidBodyControl rigidBody = new RigidBodyControl(2f);
geom.addControl(rigidBody);
rigidBody.setCollisionShape(new BoxCollisionShape(new Vector3f(brickLength, brickHeight, brickWidth)));
rootNode.attachChild(geom);
bulletAppState.getPhysicsSpace().add(rigidBody);
}
/**
* 从摄像机所在位置发射一个小球,初速度方向与摄像机方向一致。
*/
private void shootBall() {
// 网格
Sphere sphere = new Sphere(32, 32, 0.4f, true, false);
sphere.setTextureMode(TextureMode.Projected);
// 材质
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
Texture tex = assetManager.loadTexture("Interface/pic.png");
mat.setTexture("ColorMap", tex);
// 几何体
Geometry geom = new Geometry("cannon ball", sphere);
geom.setMaterial(mat);
// 刚体
RigidBodyControl rigidBody = new RigidBodyControl(1f);
geom.addControl(rigidBody);
rigidBody.setCollisionShape(new SphereCollisionShape(0.5f));
rigidBody.setPhysicsLocation(cam.getLocation());// 位置
rigidBody.setLinearVelocity(cam.getDirection().mult(50));// 初速度
rootNode.attachChild(geom);
bulletAppState.getPhysicsSpace().add(rigidBody);
}
public static void main(String[] args) {
HelloPhysics app = new HelloPhysics();
app.start();
}
}