Java 如何使摄影机跟随2个对象?
我正在制作我的第一个3D游戏,这是一种街头斗士/铁拳游戏。我已经了解了一些相机模式的工作原理,如chasecam和camnode。我不知道的是如何让摄像机同时跟踪两名球员。我想让相机在玩家彼此靠近时放大,不靠近时缩小 如果您能提供任何想法或可能的解决方案,我将不胜感激Java 如何使摄影机跟随2个对象?,java,object,camera,jmonkeyengine,Java,Object,Camera,Jmonkeyengine,我正在制作我的第一个3D游戏,这是一种街头斗士/铁拳游戏。我已经了解了一些相机模式的工作原理,如chasecam和camnode。我不知道的是如何让摄像机同时跟踪两名球员。我想让相机在玩家彼此靠近时放大,不靠近时缩小 如果您能提供任何想法或可能的解决方案,我将不胜感激 感谢如果您知道两条信息,即您希望相机位于的位置和您希望它看起来的位置,您可以非常轻松地通过手动设置相机位置来实现这一点 相机应该看的地方 这是最容易确定的,相机应该在两个物体的中间位置。一旦您知道可以使用 Vector3f box
感谢如果您知道两条信息,即您希望相机位于的位置和您希望它看起来的位置,您可以非常轻松地通过手动设置相机位置来实现这一点 相机应该看的地方 这是最容易确定的,相机应该在两个物体的中间位置。一旦您知道可以使用
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;
}
}
}
import com.jme3.app.SimpleApplication;
导入com.jme3.material.material;
导入com.jme3.math.*;
导入com.jme3.renderer.RenderManager;
导入com.jme3.scene.Geometry;
导入com.jme3.scene.shape.Box;
公共类FightTest扩展了SimpleApplication{
几何框1;
几何框2;
公共静态void main(字符串[]args){
FightTest应用程序=新的FightTest();
app.start();
}
@凌驾
public void simpleInitApp(){
//放入一些参考框
对于(int i=-20;我感谢你的回答。在我等待的时候,我几乎用同样的方法做了,除了我制作了一个节点并用setControlDir(CameraControl.ControlDirection.SpatialToCamera)将camNode附加到节点上;然后使用node.setLocalTranslation(midwayDistance,“fixedYvalue”,midwayDistance+“fixedZvalue”)。不确定这是一个好方法,但它确实有效,尽管需要调整以使其更平滑。我将尝试您的解决方案,看看它是如何工作的。@Celina这也会起作用。希望我及时回答,以提供帮助!顺便问一下,initApp中的嵌套循环是用于什么的?哦,为什么“@Richard”不起作用为我工作???@Celina当我最初做这个的时候,你看不到相机在黑色背景下的自动旋转。这个循环只是把静止的红色立方体放进去,给人一种透视的感觉不是box1.setLocalTranslation(box1.getLocalTranslation().add(新向量3f(5f*tpf,0,0));
justbox1.move(5f*tpf,0,0);
?