第一人称视角相机位置不正确
First Person Camera is not on the correct position
我正在尝试基于绑定在 JavaFX 中创建第一人称相机。相机和实际位置都完美无缺。唯一的问题是它们不匹配!如图所示,实际位置(红框)是在圆圈中间,但是摄像头在外面。我该如何改变它?我做错了什么?
Player class 处理 PerspectiveCamera。
package game;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.PerspectiveCamera;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.robot.Robot;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
public class Player extends Character {
private static final Robot ROBOT = new Robot();
private DoubleProperty relativeCenterX = new SimpleDoubleProperty();
private DoubleProperty relativeCenterY = new SimpleDoubleProperty();
protected PerspectiveCamera camera = new PerspectiveCamera();
protected Rotate xAxis = new Rotate(0, 250, 0, 0, Rotate.Y_AXIS);
protected Rotate yAxis = new Rotate(0, 0, 250, 0, Rotate.X_AXIS);
protected Translate translate = new Translate();
protected DoubleProperty centerX = new SimpleDoubleProperty();
protected DoubleProperty centerY = new SimpleDoubleProperty();
@SuppressWarnings("exports")
public Player(Stage stage) {
camera.getTransforms().addAll(xAxis, yAxis);
centerX.bind(stage.widthProperty().divide(2));
centerY.bind(stage.heightProperty().divide(2));
relativeCenterX.bind(stage.xProperty().add(centerX));
relativeCenterY.bind(stage.yProperty().add(centerY));
camera.translateXProperty().bind(posX.subtract(centerX));
camera.translateYProperty().bind(posZ);
camera.translateZProperty().bind(posY.subtract(centerY));
xAxis.angleProperty().bind(viewX.subtract(90));
yAxis.angleProperty().bind(viewY);
translate.xProperty().bind(posX);
translate.zProperty().bind(posY);
translate.yProperty().bind(posZ);
}
@SuppressWarnings("exports")
public EventHandler<KeyEvent> getKeyHandle() {
return e -> {
switch (e.getCode()) {
case A:
view(-1, 0);
break;
case D:
view(1, 0);
break;
case W:
move(1, 1, 0);
break;
case S:
move(-1, -1, 0);
break;
case SPACE:
move(0, 0, 10);
break;
case F:
move(0, 0, -10);
break;
default:
break;
}
};
}
@SuppressWarnings("exports")
public EventHandler<MouseEvent> getMouseHandle() {
return e -> {
view(e.getSceneX() - centerX.doubleValue(), centerY.doubleValue() - e.getSceneY());
Platform.runLater(() -> {
ROBOT.mouseMove(relativeCenterX.intValue(), relativeCenterY.intValue());
});
};
}
@SuppressWarnings("exports")
public PerspectiveCamera getPespectiveCamera() {
return camera;
}
}
角色class计算位置和视角。
package game;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
public abstract class Character {
protected DoubleProperty posX = new SimpleDoubleProperty();
protected DoubleProperty posY = new SimpleDoubleProperty();
protected DoubleProperty posZ = new SimpleDoubleProperty();
protected DoubleProperty viewX = new SimpleDoubleProperty();
protected DoubleProperty viewY = new SimpleDoubleProperty();
protected DoubleProperty speed = new SimpleDoubleProperty(10);
public void move(double x, double y, double z) {
double fX = Math.cos(Math.toRadians(viewX.get()));
double fY = -Math.sin(Math.toRadians(viewX.get()));
double fZ = 1;
posX.set(posX.get() + fX * x * speed.get());
posY.set(posY.get() + fY * y * speed.get());
posZ.set(posZ.get() + fZ * z);
}
public void view(double x, double y) {
viewX.set(viewX.get() + x);
viewY.set(viewY.get() + y);
}
@SuppressWarnings("exports")
public DoubleProperty posXPorperty() {
return posX;
}
@SuppressWarnings("exports")
public DoubleProperty posYPorperty() {
return posY;
}
@SuppressWarnings("exports")
public DoubleProperty posZPorperty() {
return posZ;
}
@SuppressWarnings("exports")
public DoubleProperty viewXPorperty() {
return viewX;
}
@SuppressWarnings("exports")
public DoubleProperty viewYPorperty() {
return viewY;
}
}
我的应用程序,显示全部图形内容。
package graphics;
import game.Player;
import javafx.application.Application;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class GameStage extends Application implements Runnable {
@Override
public void run() {
launch();
}
@SuppressWarnings("exports")
@Override
public void start(Stage stage) throws Exception {
BorderPane pane = new BorderPane();
Scene scene = new Scene(pane, 500, 500);
Group content = new Group(), map = new Group();
ContentScene subscene = new ContentScene(content, map, 500, 500);
subscene.widthProperty().bind(scene.widthProperty());
subscene.heightProperty().bind(scene.heightProperty());
pane.getChildren().add(subscene);
pane.setBottom(map);
Player player = new Player(stage);
Box box = new Box(50, 50, 50);
box.translateXProperty().bind(player.posXPorperty());
box.translateYProperty().bind(player.posZPorperty());
box.translateZProperty().bind(player.posYPorperty());
box.rotateProperty().bind(player.viewXPorperty());
box.setMaterial(new PhongMaterial(Color.RED));
content.getChildren().add(box);
Rectangle rectangle = new Rectangle(5, 5);
rectangle.translateXProperty().bind(player.posXPorperty().divide(10));
rectangle.translateYProperty().bind(player.posYPorperty().divide(10));
rectangle.setFill(Color.RED);
map.getChildren().add(rectangle);
subscene.setCamera(player.getPespectiveCamera());
scene.addEventHandler(KeyEvent.KEY_PRESSED, player.getKeyHandle());
scene.addEventHandler(MouseEvent.MOUSE_MOVED, player.getMouseHandle());
scene.setFill(Color.BLACK);
Cursor cursor = Cursor.CROSSHAIR;
scene.setCursor(cursor);
stage.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
if (e.getCode() != KeyCode.F11) {
return;
}
if (stage.isFullScreen()) {
stage.setFullScreen(false);
} else {
stage.setFullScreen(true);
}
});
stage.setAlwaysOnTop(true);
stage.setScene(scene);
stage.show();
}
private class ContentScene extends SubScene {
public ContentScene(Group content, Group map, double width, double height) {
super(content, width, height, true, SceneAntialiasing.BALANCED);
PhongMaterial material = new PhongMaterial(Color.AQUA);
for (int v = 0; v < 3_600; v += 180) {
for (int y = 0; y < 500; y += 100) {
Box box = new Box(50, 50, 50);
box.setTranslateX(Math.sin(v / 10) * 1_000);
box.setTranslateY(y);
box.setTranslateZ(Math.cos(v / 10) * 1_000);
box.setMaterial(material);
content.getChildren().add(box);
Rectangle rectangle = new Rectangle(5, 5);
rectangle.translateXProperty().bind(box.translateXProperty().divide(10));
rectangle.translateYProperty().bind(box.translateZProperty().divide(10));
rectangle.setFill(Color.AQUA);
map.getChildren().add(rectangle);
}
}
}
}
}
多亏了 Thomas,我才得以解决问题。现在的代码是这样的:
package graphics;
import game.Player;
import javafx.application.Application;
import javafx.scene.AmbientLight;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class GameStage extends Application implements Runnable {
@Override
public void run() {
launch();
}
@SuppressWarnings("exports")
@Override
public void start(Stage stage) throws Exception {
// Parents
BorderPane pane = new BorderPane();
Group content = new Group(new AmbientLight()), map = new Group();
Pane stackpane = new Pane(map);
// Scenes
Scene scene = new Scene(pane, 500, 500);
SubScene contentSubscene = new SubScene(content, 500, 500, true, SceneAntialiasing.BALANCED);
contentSubscene.widthProperty().bind(scene.widthProperty());
contentSubscene.heightProperty().bind(scene.heightProperty());
SubScene minimapSubscene = new SubScene(stackpane, 256, 256);
minimapSubscene.setFill(Color.DARKGREY);
pane.getChildren().add(contentSubscene);
pane.setBottom(minimapSubscene);
// Create Player
Player player = new Player(stage);
Rectangle currentPosition = new Rectangle(5, 5);
currentPosition.layoutXProperty().bind(minimapSubscene.widthProperty().divide(2));
currentPosition.layoutYProperty().bind(minimapSubscene.heightProperty().divide(2));
currentPosition.setFill(Color.RED);
stackpane.getChildren().add(currentPosition);
map.layoutXProperty().bind(player.posXPorperty().divide(-10).add(minimapSubscene.widthProperty().divide(2)));
map.layoutYProperty().bind(player.posYPorperty().divide(-10).add(minimapSubscene.heightProperty().divide(2)));
// Create Box in
PhongMaterial material = new PhongMaterial(Color.AQUA);
for (int v = 0; v < 3_600; v += 180) {
for (int y = 0; y < 500; y += 100) {
Box box = new Box(50, 50, 50);
box.setTranslateX(Math.sin(v / 10) * 1_000);
box.setTranslateY(y);
box.setTranslateZ(Math.cos(v / 10) * 1_000);
box.setMaterial(material);
content.getChildren().add(box);
Rectangle boxPosition = new Rectangle(5, 5);
boxPosition.translateXProperty().bind(box.translateXProperty().divide(10));
boxPosition.translateYProperty().bind(box.translateZProperty().divide(10));
boxPosition.setFill(Color.AQUA);
map.getChildren().add(boxPosition);
}
}
contentSubscene.setCamera(player.getPespectiveCamera());
scene.addEventHandler(KeyEvent.KEY_PRESSED, player.getKeyHandle());
scene.addEventHandler(MouseEvent.MOUSE_MOVED, player.getMouseHandle());
scene.setCursor(Cursor.CROSSHAIR);
scene.setFill(Color.WHITE);
stage.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
if (e.getCode() != KeyCode.F11) {
return;
}
if (stage.isFullScreen()) {
stage.setFullScreen(false);
} else {
stage.setFullScreen(true);
}
});
stage.setAlwaysOnTop(true);
stage.setScene(scene);
stage.show();
}
}
package game;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
public abstract class Character {
protected DoubleProperty posX = new SimpleDoubleProperty();
protected DoubleProperty posY = new SimpleDoubleProperty();
protected DoubleProperty posZ = new SimpleDoubleProperty();
protected DoubleProperty viewX = new SimpleDoubleProperty();
protected DoubleProperty viewY = new SimpleDoubleProperty();
protected DoubleProperty speed = new SimpleDoubleProperty(10);
public void move(double x, double y, double z) {
double fX = Math.cos(Math.toRadians(viewX.get()));
double fY = -Math.sin(Math.toRadians(viewX.get()));
double fZ = 1;
posX.set(posX.get() + fX * x * speed.get());
posY.set(posY.get() + fY * y * speed.get());
posZ.set(posZ.get() + fZ * z);
}
public void view(double x, double y) {
viewX.set(viewX.get() + x);
viewY.set(viewY.get() + y);
}
@SuppressWarnings("exports")
public DoubleProperty posXPorperty() {
return posX;
}
@SuppressWarnings("exports")
public DoubleProperty posYPorperty() {
return posY;
}
@SuppressWarnings("exports")
public DoubleProperty posZPorperty() {
return posZ;
}
@SuppressWarnings("exports")
public DoubleProperty viewXPorperty() {
return viewX;
}
@SuppressWarnings("exports")
public DoubleProperty viewYPorperty() {
return viewY;
}
}
package game;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.PerspectiveCamera;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.robot.Robot;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
public class Player extends Character {
private static final Robot ROBOT = new Robot();
private DoubleProperty relativeCenterX = new SimpleDoubleProperty();
private DoubleProperty relativeCenterY = new SimpleDoubleProperty();
protected PerspectiveCamera camera = new PerspectiveCamera(true);
protected Rotate xAxis = new Rotate(0, 250, 0, 0, Rotate.Y_AXIS);
protected Rotate yAxis = new Rotate(0, 0, 250, 0, Rotate.X_AXIS);
protected DoubleProperty centerX = new SimpleDoubleProperty();
protected DoubleProperty centerY = new SimpleDoubleProperty();
@SuppressWarnings("exports")
public Player(Stage stage) {
camera.getTransforms().addAll(xAxis, yAxis);
camera.setFieldOfView((40 + 62) / 2);
camera.setNearClip(0.1);
camera.setFarClip(100000);
camera.setVerticalFieldOfView(true);
centerX.bind(stage.widthProperty().divide(2));
centerY.bind(stage.heightProperty().divide(2));
relativeCenterX.bind(stage.xProperty().add(centerX));
relativeCenterY.bind(stage.yProperty().add(centerY));
xAxis.angleProperty().bind(viewX.subtract(90));
yAxis.angleProperty().bind(viewY);
camera.translateXProperty().bind(posX);
camera.translateZProperty().bind(posY);
camera.translateYProperty().bind(posZ);
}
@SuppressWarnings("exports")
public EventHandler<KeyEvent> getKeyHandle() {
return e -> {
switch (e.getCode()) {
case A:
view(-1, 0);
break;
case D:
view(1, 0);
break;
case W:
move(1, 1, 0);
break;
case S:
move(-1, -1, 0);
break;
case SPACE:
move(0, 0, 10);
break;
case F:
move(0, 0, -10);
break;
default:
break;
}
};
}
@SuppressWarnings("exports")
public EventHandler<MouseEvent> getMouseHandle() {
return e -> {
view(e.getSceneX() - centerX.doubleValue(), centerY.doubleValue() - e.getSceneY());
Platform.runLater(() -> {
ROBOT.mouseMove(relativeCenterX.intValue(), relativeCenterY.intValue());
});
};
}
@SuppressWarnings("exports")
public PerspectiveCamera getPespectiveCamera() {
return camera;
}
}
我正在尝试基于绑定在 JavaFX 中创建第一人称相机。相机和实际位置都完美无缺。唯一的问题是它们不匹配!如图所示,实际位置(红框)是在圆圈中间,但是摄像头在外面。我该如何改变它?我做错了什么?
Player class 处理 PerspectiveCamera。
package game;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.PerspectiveCamera;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.robot.Robot;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
public class Player extends Character {
private static final Robot ROBOT = new Robot();
private DoubleProperty relativeCenterX = new SimpleDoubleProperty();
private DoubleProperty relativeCenterY = new SimpleDoubleProperty();
protected PerspectiveCamera camera = new PerspectiveCamera();
protected Rotate xAxis = new Rotate(0, 250, 0, 0, Rotate.Y_AXIS);
protected Rotate yAxis = new Rotate(0, 0, 250, 0, Rotate.X_AXIS);
protected Translate translate = new Translate();
protected DoubleProperty centerX = new SimpleDoubleProperty();
protected DoubleProperty centerY = new SimpleDoubleProperty();
@SuppressWarnings("exports")
public Player(Stage stage) {
camera.getTransforms().addAll(xAxis, yAxis);
centerX.bind(stage.widthProperty().divide(2));
centerY.bind(stage.heightProperty().divide(2));
relativeCenterX.bind(stage.xProperty().add(centerX));
relativeCenterY.bind(stage.yProperty().add(centerY));
camera.translateXProperty().bind(posX.subtract(centerX));
camera.translateYProperty().bind(posZ);
camera.translateZProperty().bind(posY.subtract(centerY));
xAxis.angleProperty().bind(viewX.subtract(90));
yAxis.angleProperty().bind(viewY);
translate.xProperty().bind(posX);
translate.zProperty().bind(posY);
translate.yProperty().bind(posZ);
}
@SuppressWarnings("exports")
public EventHandler<KeyEvent> getKeyHandle() {
return e -> {
switch (e.getCode()) {
case A:
view(-1, 0);
break;
case D:
view(1, 0);
break;
case W:
move(1, 1, 0);
break;
case S:
move(-1, -1, 0);
break;
case SPACE:
move(0, 0, 10);
break;
case F:
move(0, 0, -10);
break;
default:
break;
}
};
}
@SuppressWarnings("exports")
public EventHandler<MouseEvent> getMouseHandle() {
return e -> {
view(e.getSceneX() - centerX.doubleValue(), centerY.doubleValue() - e.getSceneY());
Platform.runLater(() -> {
ROBOT.mouseMove(relativeCenterX.intValue(), relativeCenterY.intValue());
});
};
}
@SuppressWarnings("exports")
public PerspectiveCamera getPespectiveCamera() {
return camera;
}
}
角色class计算位置和视角。
package game;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
public abstract class Character {
protected DoubleProperty posX = new SimpleDoubleProperty();
protected DoubleProperty posY = new SimpleDoubleProperty();
protected DoubleProperty posZ = new SimpleDoubleProperty();
protected DoubleProperty viewX = new SimpleDoubleProperty();
protected DoubleProperty viewY = new SimpleDoubleProperty();
protected DoubleProperty speed = new SimpleDoubleProperty(10);
public void move(double x, double y, double z) {
double fX = Math.cos(Math.toRadians(viewX.get()));
double fY = -Math.sin(Math.toRadians(viewX.get()));
double fZ = 1;
posX.set(posX.get() + fX * x * speed.get());
posY.set(posY.get() + fY * y * speed.get());
posZ.set(posZ.get() + fZ * z);
}
public void view(double x, double y) {
viewX.set(viewX.get() + x);
viewY.set(viewY.get() + y);
}
@SuppressWarnings("exports")
public DoubleProperty posXPorperty() {
return posX;
}
@SuppressWarnings("exports")
public DoubleProperty posYPorperty() {
return posY;
}
@SuppressWarnings("exports")
public DoubleProperty posZPorperty() {
return posZ;
}
@SuppressWarnings("exports")
public DoubleProperty viewXPorperty() {
return viewX;
}
@SuppressWarnings("exports")
public DoubleProperty viewYPorperty() {
return viewY;
}
}
我的应用程序,显示全部图形内容。
package graphics;
import game.Player;
import javafx.application.Application;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class GameStage extends Application implements Runnable {
@Override
public void run() {
launch();
}
@SuppressWarnings("exports")
@Override
public void start(Stage stage) throws Exception {
BorderPane pane = new BorderPane();
Scene scene = new Scene(pane, 500, 500);
Group content = new Group(), map = new Group();
ContentScene subscene = new ContentScene(content, map, 500, 500);
subscene.widthProperty().bind(scene.widthProperty());
subscene.heightProperty().bind(scene.heightProperty());
pane.getChildren().add(subscene);
pane.setBottom(map);
Player player = new Player(stage);
Box box = new Box(50, 50, 50);
box.translateXProperty().bind(player.posXPorperty());
box.translateYProperty().bind(player.posZPorperty());
box.translateZProperty().bind(player.posYPorperty());
box.rotateProperty().bind(player.viewXPorperty());
box.setMaterial(new PhongMaterial(Color.RED));
content.getChildren().add(box);
Rectangle rectangle = new Rectangle(5, 5);
rectangle.translateXProperty().bind(player.posXPorperty().divide(10));
rectangle.translateYProperty().bind(player.posYPorperty().divide(10));
rectangle.setFill(Color.RED);
map.getChildren().add(rectangle);
subscene.setCamera(player.getPespectiveCamera());
scene.addEventHandler(KeyEvent.KEY_PRESSED, player.getKeyHandle());
scene.addEventHandler(MouseEvent.MOUSE_MOVED, player.getMouseHandle());
scene.setFill(Color.BLACK);
Cursor cursor = Cursor.CROSSHAIR;
scene.setCursor(cursor);
stage.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
if (e.getCode() != KeyCode.F11) {
return;
}
if (stage.isFullScreen()) {
stage.setFullScreen(false);
} else {
stage.setFullScreen(true);
}
});
stage.setAlwaysOnTop(true);
stage.setScene(scene);
stage.show();
}
private class ContentScene extends SubScene {
public ContentScene(Group content, Group map, double width, double height) {
super(content, width, height, true, SceneAntialiasing.BALANCED);
PhongMaterial material = new PhongMaterial(Color.AQUA);
for (int v = 0; v < 3_600; v += 180) {
for (int y = 0; y < 500; y += 100) {
Box box = new Box(50, 50, 50);
box.setTranslateX(Math.sin(v / 10) * 1_000);
box.setTranslateY(y);
box.setTranslateZ(Math.cos(v / 10) * 1_000);
box.setMaterial(material);
content.getChildren().add(box);
Rectangle rectangle = new Rectangle(5, 5);
rectangle.translateXProperty().bind(box.translateXProperty().divide(10));
rectangle.translateYProperty().bind(box.translateZProperty().divide(10));
rectangle.setFill(Color.AQUA);
map.getChildren().add(rectangle);
}
}
}
}
}
多亏了 Thomas,我才得以解决问题。现在的代码是这样的:
package graphics;
import game.Player;
import javafx.application.Application;
import javafx.scene.AmbientLight;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class GameStage extends Application implements Runnable {
@Override
public void run() {
launch();
}
@SuppressWarnings("exports")
@Override
public void start(Stage stage) throws Exception {
// Parents
BorderPane pane = new BorderPane();
Group content = new Group(new AmbientLight()), map = new Group();
Pane stackpane = new Pane(map);
// Scenes
Scene scene = new Scene(pane, 500, 500);
SubScene contentSubscene = new SubScene(content, 500, 500, true, SceneAntialiasing.BALANCED);
contentSubscene.widthProperty().bind(scene.widthProperty());
contentSubscene.heightProperty().bind(scene.heightProperty());
SubScene minimapSubscene = new SubScene(stackpane, 256, 256);
minimapSubscene.setFill(Color.DARKGREY);
pane.getChildren().add(contentSubscene);
pane.setBottom(minimapSubscene);
// Create Player
Player player = new Player(stage);
Rectangle currentPosition = new Rectangle(5, 5);
currentPosition.layoutXProperty().bind(minimapSubscene.widthProperty().divide(2));
currentPosition.layoutYProperty().bind(minimapSubscene.heightProperty().divide(2));
currentPosition.setFill(Color.RED);
stackpane.getChildren().add(currentPosition);
map.layoutXProperty().bind(player.posXPorperty().divide(-10).add(minimapSubscene.widthProperty().divide(2)));
map.layoutYProperty().bind(player.posYPorperty().divide(-10).add(minimapSubscene.heightProperty().divide(2)));
// Create Box in
PhongMaterial material = new PhongMaterial(Color.AQUA);
for (int v = 0; v < 3_600; v += 180) {
for (int y = 0; y < 500; y += 100) {
Box box = new Box(50, 50, 50);
box.setTranslateX(Math.sin(v / 10) * 1_000);
box.setTranslateY(y);
box.setTranslateZ(Math.cos(v / 10) * 1_000);
box.setMaterial(material);
content.getChildren().add(box);
Rectangle boxPosition = new Rectangle(5, 5);
boxPosition.translateXProperty().bind(box.translateXProperty().divide(10));
boxPosition.translateYProperty().bind(box.translateZProperty().divide(10));
boxPosition.setFill(Color.AQUA);
map.getChildren().add(boxPosition);
}
}
contentSubscene.setCamera(player.getPespectiveCamera());
scene.addEventHandler(KeyEvent.KEY_PRESSED, player.getKeyHandle());
scene.addEventHandler(MouseEvent.MOUSE_MOVED, player.getMouseHandle());
scene.setCursor(Cursor.CROSSHAIR);
scene.setFill(Color.WHITE);
stage.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
if (e.getCode() != KeyCode.F11) {
return;
}
if (stage.isFullScreen()) {
stage.setFullScreen(false);
} else {
stage.setFullScreen(true);
}
});
stage.setAlwaysOnTop(true);
stage.setScene(scene);
stage.show();
}
}
package game;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
public abstract class Character {
protected DoubleProperty posX = new SimpleDoubleProperty();
protected DoubleProperty posY = new SimpleDoubleProperty();
protected DoubleProperty posZ = new SimpleDoubleProperty();
protected DoubleProperty viewX = new SimpleDoubleProperty();
protected DoubleProperty viewY = new SimpleDoubleProperty();
protected DoubleProperty speed = new SimpleDoubleProperty(10);
public void move(double x, double y, double z) {
double fX = Math.cos(Math.toRadians(viewX.get()));
double fY = -Math.sin(Math.toRadians(viewX.get()));
double fZ = 1;
posX.set(posX.get() + fX * x * speed.get());
posY.set(posY.get() + fY * y * speed.get());
posZ.set(posZ.get() + fZ * z);
}
public void view(double x, double y) {
viewX.set(viewX.get() + x);
viewY.set(viewY.get() + y);
}
@SuppressWarnings("exports")
public DoubleProperty posXPorperty() {
return posX;
}
@SuppressWarnings("exports")
public DoubleProperty posYPorperty() {
return posY;
}
@SuppressWarnings("exports")
public DoubleProperty posZPorperty() {
return posZ;
}
@SuppressWarnings("exports")
public DoubleProperty viewXPorperty() {
return viewX;
}
@SuppressWarnings("exports")
public DoubleProperty viewYPorperty() {
return viewY;
}
}
package game;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.PerspectiveCamera;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.robot.Robot;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
public class Player extends Character {
private static final Robot ROBOT = new Robot();
private DoubleProperty relativeCenterX = new SimpleDoubleProperty();
private DoubleProperty relativeCenterY = new SimpleDoubleProperty();
protected PerspectiveCamera camera = new PerspectiveCamera(true);
protected Rotate xAxis = new Rotate(0, 250, 0, 0, Rotate.Y_AXIS);
protected Rotate yAxis = new Rotate(0, 0, 250, 0, Rotate.X_AXIS);
protected DoubleProperty centerX = new SimpleDoubleProperty();
protected DoubleProperty centerY = new SimpleDoubleProperty();
@SuppressWarnings("exports")
public Player(Stage stage) {
camera.getTransforms().addAll(xAxis, yAxis);
camera.setFieldOfView((40 + 62) / 2);
camera.setNearClip(0.1);
camera.setFarClip(100000);
camera.setVerticalFieldOfView(true);
centerX.bind(stage.widthProperty().divide(2));
centerY.bind(stage.heightProperty().divide(2));
relativeCenterX.bind(stage.xProperty().add(centerX));
relativeCenterY.bind(stage.yProperty().add(centerY));
xAxis.angleProperty().bind(viewX.subtract(90));
yAxis.angleProperty().bind(viewY);
camera.translateXProperty().bind(posX);
camera.translateZProperty().bind(posY);
camera.translateYProperty().bind(posZ);
}
@SuppressWarnings("exports")
public EventHandler<KeyEvent> getKeyHandle() {
return e -> {
switch (e.getCode()) {
case A:
view(-1, 0);
break;
case D:
view(1, 0);
break;
case W:
move(1, 1, 0);
break;
case S:
move(-1, -1, 0);
break;
case SPACE:
move(0, 0, 10);
break;
case F:
move(0, 0, -10);
break;
default:
break;
}
};
}
@SuppressWarnings("exports")
public EventHandler<MouseEvent> getMouseHandle() {
return e -> {
view(e.getSceneX() - centerX.doubleValue(), centerY.doubleValue() - e.getSceneY());
Platform.runLater(() -> {
ROBOT.mouseMove(relativeCenterX.intValue(), relativeCenterY.intValue());
});
};
}
@SuppressWarnings("exports")
public PerspectiveCamera getPespectiveCamera() {
return camera;
}
}