我正在制作我的第一款3D游戏,这是一种街头霸王/铁拳游戏。我已经看到了一些相机模式的工作原理,即。 chasecam和camnode。我不知道的是如何使相机同时跟随两个玩家。我希望相机在玩家彼此靠近时放大,并在没有玩家时放大。
我很感激任何有关想法或可能的解决方案的帮助。
由于
答案 0 :(得分:1)
如果您知道两条信息,您希望相机在哪里以及您希望它看起来在哪里,您可以非常轻松地手动设置相机位置。
这是最容易确定的事情,相机应该看着两个物体的中间位置。一旦您知道可以使用
设置相机的位置Vector3f boxsCentre=box1.getWorldTranslation().add(box2.getWorldTranslation()).mult(0.5f);
cam.lookAt(boxsCentre, Vector3f.UNIT_Y);
相机应该更加棘手。你知道它应该在线的某个地方,从两个物体的中心沿垂直于这两个物体之间的线的方向延伸。谢天谢地,十字架产品给了我们这个。我们希望相机始终与物体处于同一水平,因此通过直接向上的矢量穿过分离矢量,我们得到垂直线
Vector3f seperationVector=box2.getWorldTranslation().subtract(box1.getWorldTranslation());
Vector3f perpendicularFromTheAction= seperationVector.cross(Vector3f.UNIT_Y);
perpendicularFromTheAction.normalizeLocal();
所以,这给了我们一条线,但我们应该把相机放在哪里。我只是玩弄了这个,发现两次物体之间的距离很好看,所以
float distance=2*seperationVector.length();
Vector3f newCameraLocation=boxsCentre.add(perpendicularFromTheAction.mult(distance));
然后您可以设置摄像机位置
cam.setLocation(newCameraLocation);
我已经将这个代码与两个正在循环移动的盒子一起使用来演示这个,因为你可以看到你得到你想要的效果
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.*;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
public class FightTest extends SimpleApplication {
Geometry box1;
Geometry box2;
public static void main(String[] args) {
FightTest app = new FightTest();
app.start();
}
@Override
public void simpleInitApp() {
//put in some reference boxes
for(int i=-20;i<=20;i+=20){
for(int j=-20;j<=20;j+=20){
if (j!=0||i!=0){
Geometry referenceBox = createBox(ColorRGBA.Red);
referenceBox.setLocalTranslation(i, 0, j);
rootNode.attachChild(referenceBox);
}
}
}
//put in our two players
box1 = createBox(ColorRGBA.Blue);
box1.setLocalTranslation(5, 0, 0);
box2 = createBox(ColorRGBA.Green);
rootNode.attachChild(box1);
rootNode.attachChild(box2);
}
private Geometry createBox(ColorRGBA color){
Box b = new Box(Vector3f.ZERO, 1, 1, 1);
Geometry box = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", color);
box.setMaterial(mat);
return box;
}
@Override
public void simpleUpdate(float tpf) {
adjustCam();
movePlayers(tpf);
}
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
private void adjustCam(){
//we want our camera to look at the centre of the boxes
Vector3f boxsCentre=box1.getWorldTranslation().add(box2.getWorldTranslation()).mult(0.5f);
cam.lookAt(boxsCentre, Vector3f.UNIT_Y);
//we also want our camera to move closer/further away as the boxes seperate.
//and move around so its always parallel to the action
//parallel to the action means on the line given by the cross product of the
//box seperation and the upwards vector
Vector3f seperationVector=box2.getWorldTranslation().subtract(box1.getWorldTranslation());
Vector3f perpendicularFromTheAction= seperationVector.cross(Vector3f.UNIT_Y);
perpendicularFromTheAction.normalizeLocal();
//we could (and you should) get complicated on exactly how far the camera should
//move backwards, but I'm just going to make the camera twice as far away as the
//objects are seperated
float distance=2*seperationVector.length();
Vector3f newCameraLocation=boxsCentre.add(perpendicularFromTheAction.mult(distance));
cam.setLocation(newCameraLocation);
}
float timeAccumulator=0;
private void movePlayers(float tpf){
//basic movement, just for demo
timeAccumulator+=tpf;
if (timeAccumulator<2){
box1.move(new Vector3f(5f*tpf,0,0));
box2.move(new Vector3f(0,0,5f*tpf));
}else if (timeAccumulator<4){
box1.move(new Vector3f(-5f*tpf,0,0));
box2.move(new Vector3f(0,0,-5f*tpf));
}else{
timeAccumulator=0;
}
}
}