JME基础教程代码分析9 碰撞、刚体、场景加载
package com.hello;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
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.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.texture.Texture;
/**
* Example 9 - How to make walls and floors solid.
* This version uses Physics and a custom Action Listener.
* @author normen, with edits by Zathras
*/
public class HelloCollision extends SimpleApplication
implements ActionListener {
private Spatial sceneModel;
private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
private boolean isTrans = false;
private Geometry geom;
public static void main(String[] args) {
HelloCollision app = new HelloCollision();
app.start();
}
public void simpleInitApp() {
/** Set up Physics */
//设置物理状态,声明一个弹道应用状态
bulletAppState = new BulletAppState();
//将弹道应用状态附加给状态管理对象
stateManager.attach(bulletAppState);
Box b = new Box(new Vector3f(0f, 4f, 0f), 1, 1, 1);
geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key = new TextureKey("/zw.jpg");
key.setGenerateMips(true);
Texture tex = assetManager.loadTexture(key);
mat.setTexture("ColorMap", tex);
geom.setMaterial(mat);
rootNode.attachChild(geom);
// We re-use the flyby camera for rotation, while positioning is handled by physics
//为旋转视角再次使用飞行相机,它是通过物理方法定位的
//viewPort是视角范围,设置天空的颜色
viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1f));
//飞行相机的移动速度
flyCam.setMoveSpeed(100);
setUpKeys();
setUpLight();
// We load the scene from the zip file and adjust its size.
//加载场景文件,这里是个.zip文件,包含了场景模型所有文件
assetManager.registerLocator("town.zip", ZipLocator.class.getName());
//加载模型的起始文件名
sceneModel = assetManager.loadModel("main.scene");
sceneModel.setLocalScale(2f);
// We set up collision detection for the scene by creating a
// compound collision shape and a static physics node with mass zero.
//使用场景文件创建一个符合碰撞造型
CollisionShape sceneShape =
CollisionShapeFactory.createMeshShape((Node) sceneModel);
//刚体控制对象,第一个参数是要设置的刚体对象,第二个参数是他的质量,质量为零表示不受物理引力影响,呵呵,效果是悬浮着的
landscape = new RigidBodyControl(sceneShape, 0);
sceneModel.addControl(landscape);
// We set up collision detection for the player by creating
// a capsule collision shape and a physics character node.
// The physics character node offers extra settings for
// size, stepheight, jumping, falling, and gravity.
// We also put the player in its starting position.
//这段有点不好理解,可以说是一个胶囊形状的“人”,步幅高度是0.05f,跳跃速度是20,下落速度是30,所受重力是30,并设置了物理位置
//有一点必须注意,这个胶囊“人”没有被渲染,无论如何都无法被看到的。
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
player = new CharacterControl(capsuleShape, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(0, 10, 0));
// We attach the scene and the player to the rootnode and the physics space,
// to make them appear in the game world.
//附加场景模型到根节点,弹道物理应用状态加载空间对象和player对象到物理空间
rootNode.attachChild(sceneModel);
//加载顺序是无关紧要的,不会因为先加载player,就受重力影响而下落,但是y轴方向的加载位置比较重要,如果没有加载到空间刚体对象的上方,就会无奈的受到重力影响了。
bulletAppState.getPhysicsSpace().add(landscape);
bulletAppState.getPhysicsSpace().add(player);
}
private void setUpLight() {
// We add light so we see the scene
//加载两组光线,环境光,定向光
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
rootNode.addLight(al);
DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
rootNode.addLight(dl);
}
/** We over-write some navigational key mappings here, so we can
* add physics-controlled walking and jumping: */
private void setUpKeys() {
inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("Jumps", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("Scale", new KeyTrigger(KeyInput.KEY_C));
inputManager.addMapping("Min", new KeyTrigger(KeyInput.KEY_M));
inputManager.addListener(this, "Lefts");
inputManager.addListener(this, "Rights");
inputManager.addListener(this, "Ups");
inputManager.addListener(this, "Downs");
inputManager.addListener(this, "Jumps");
inputManager.addListener(this, "Scale");
inputManager.addListener(this, "Min");
}
/** These are our custom actions triggered by key presses.
* We do not walk yet, we just keep track of the direction the user pressed. */
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("Lefts")) {
left = value;
} else if (binding.equals("Rights")) {
right = value;
} else if (binding.equals("Ups")) {
up = value;
} else if (binding.equals("Downs")) {
down = value;
} else if (binding.equals("Jumps")) {
player.jump();
} else if (binding.equals("Scale")) {
isTrans = false;
transPic(geom.getMaterial());
geom.setLocalScale(2);
} else if (binding.equals("Min")) {
isTrans = true;
transPic(geom.getMaterial());
geom.setLocalScale(1);
}
}
/**
* This is the main event loop--walking happens here.
* We check in which direction the player is walking by interpreting
* the camera direction forward (camDir) and to the side (camLeft).
* The setWalkDirection() command is what lets a physics-controlled player walk.
* We also make sure here that the camera moves with player.
*/
@Override
public void simpleUpdate(float tpf) {
Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
walkDirection.set(0, 0, 0);
if (left) { walkDirection.addLocal(camLeft); }
if (right) { walkDirection.addLocal(camLeft.negate()); }
if (up) { walkDirection.addLocal(camDir); }
if (down) { walkDirection.addLocal(camDir.negate()); }
player.setWalkDirection(walkDirection);
cam.setLocation(player.getPhysicsLocation());
Quaternion qt = new Quaternion();
qt.fromAngles(0, FastMath.HALF_PI/4*tpf, 0);
geom.rotate(qt);
}
private Material transPic(Material src) {
String picname;
if(isTrans) {
picname = "/zw.jpg";
} else {
picname = "/mypic.jpg";
}
TextureKey key = new TextureKey(picname);
key.setGenerateMips(true);
Texture tex = assetManager.loadTexture(key);
src.setTexture("ColorMap", tex);
return src;
}
}
posted on 2011-08-12 11:30 苏桓(osbert) 阅读(839) 评论(0) 编辑 收藏 举报