Используя JavaFX SplitPane, как вы можете заставить две панели отражать друг друга?
Я разрабатываю 2D-игру, и мне нужно сделать ее многопользовательской с разделенным экраном. Я хочу, чтобы содержимое второй панели прокрутки отражало первую, но содержимое отображается только на второй панели.
package sample;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.*;
import javafx.scene.layout.Background;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javafx.animation.AnimationTimer;
import javafx.geometry.Point2D;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
Приложение начинается здесь!
public class Main extends Application {
// Initialize background media
private Media media = new Media(new File("/Users/hashimjacobs/IdeaProjects/TankGame/src/sample/sprites/ZHU-Nero-Dreams(Tank Trim).wav").toURI().toString());
private MediaPlayer mp = new MediaPlayer(media);
// Horizontal box. Child nodes will be laid out horizontally (side by side)
private HBox box = new HBox();
// Two anchor panes for bases of split screens
private SplitPane splitScreen = new SplitPane();
private AnchorPane basePane;
private AnchorPane screen1base;
private AnchorPane screen2base;
ScrollPane screen1;
ScrollPane screen2;
// Two scroll panes to enable scrolling for each anchor pane
private AnchorPane base = new AnchorPane();
private AnchorPane base2 = new AnchorPane();
// Define dynamic lists necessary for controlling multiple objects on screen
private List<GameObject> bullets = new ArrayList<>();
private List<GameObject> enemies = new ArrayList<>();
private List<Tank> players = new ArrayList<>();
private List<GameObject> walls = new ArrayList<>();
private List<GameObject> walls2 = new ArrayList<>();
private List<PowerUp> powerups = new ArrayList<>();
// Naming player tanks
private Tank tank1,tank2;
// Window height and width
private static final double H = 864;
private static final double W = 992;
/**
*
*/
// Plays media
private static void playMedia(MediaPlayer mp){
mp.setAutoPlay(true);
mp.play();
}
Вот где я считаю, что проблема.
// Creates all static content to be displayed on both screens
private Parent createContent(){
base.setPrefSize(W,H);
base.setMaxSize(W,H);
base2.setPrefSize(W,H);
base2.setMaxSize(W,H);
box.setPrefSize(W,H);
BackgroundImage bi = new BackgroundImage(new Image("sample/sprites/grass_5.png",W,H,false,true),BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT,
BackgroundSize.DEFAULT);
base.setBackground(new Background(bi));
base2.setBackground(new Background(bi));
/**
Set up viewports for scroll panes. This way, the players can be centered on their respective screens as they scroll around the map.
* */
/**
* buildMap lays out all walls, pentagon, and tanks on top of the background
*
* **/
buildMap();
initPlayers();
// Add labels to health bar
Text player1 = new Text(10,15,"Player 1"); player1.setFont(Font.font("Ariel",FontWeight.BOLD,20)); player1.setFill(Color.DARKVIOLET);
Text player1lives = new Text(10,55,"Lives: " + tank1.getLives()); player1lives.setFont(Font.font("Times New Roman", FontWeight.EXTRA_BOLD,15));player1lives.setFill(Color.WHITE);
Text player2 = new Text(870,15,"Player 2"); player2.setFont(Font.font("Ariel",FontWeight.BOLD,20)); player2.setFill(Color.DARKVIOLET);
Text player2lives = new Text(870,55,"Lives: " + tank2.getLives()); player2lives.setFont(Font.font("Times New Roman", FontWeight.EXTRA_BOLD,15));player2lives.setFill(Color.WHITE);
Я думал, что должен добавить каждый узел к каждой области прокрутки, с которой я начал экспериментировать ниже.
base.getChildren().add(player1); base.getChildren().add(player2);
base.getChildren().add(player1lives); base.getChildren().add(player2lives);
base2.getChildren().add(player1); base2.getChildren().add(player2);
base2.getChildren().add(player1lives); base2.getChildren().add(player2lives);
addGameObject(tank1.getHealthBar(),10,20); addGameObject(tank2.getHealthBar(),870,20);
После создания двух разных панелей привязки, base и base2, я наконец-то увидел фон, отображаемый на обеих панелях.
screen1 = new ScrollPane(base);
screen2 = new ScrollPane(base2);
Высота обеих панелей по-прежнему не распространяется на нижний край окна.
// Set layout of each screen
screen1.setPrefSize(W/2,H/2);
screen2.setMaxSize(W/2,H/2);
screen1.setPrefViewportWidth(W/2); screen1.setPrefViewportHeight(H);
screen2.setPrefViewportWidth(W/2); screen2.setPrefViewportHeight(H);
screen1.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); screen1.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
screen2.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); screen2.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
screen1base = new AnchorPane(screen1);
screen2base = new AnchorPane(screen2);
screen1base.setPrefSize(W/2,H);
screen2base.setPrefSize(W/2,H);
splitScreen.getItems().addAll(screen1base,screen2base);
basePane = new AnchorPane(splitScreen);
// Game Loop
AnimationTimer timer = new AnimationTimer() {
//@Override
public void handle(long now){
onUpdate();
}
};
timer.start();
return basePane;
}
// Updates the board by eliminating any dead objects due to collision and also adds enemies to the board at random
private void onUpdate(){
// Bullet collision
for (GameObject bullet : bullets) {
for (GameObject enemy : enemies) {
if (bullet.isColliding(enemy)) {
bullet.setDead(true);
enemy.setDead(true);
base.getChildren().removeAll(bullet.getView(), enemy.getView());
base2.getChildren().removeAll(bullet.getView(), enemy.getView());
}
}
for (GameObject wall : walls){
if (bullet.isColliding(wall)){
bullet.setDead(true);
if (wall.getClass().isInstance(new BreakableWall(null))){
double newHealth = wall.getHealth() - 1;
if(newHealth == 0) {
wall.setDead(true);
base.getChildren().remove(wall.getView());
base2.getChildren().remove(wall.getView());
playMedia(new MediaPlayer(new Media(new File("/Users/hashimjacobs/IdeaProjects/TankGame/src/sample/sprites/Wet Fart Squish-SoundBible.com-332766022.wav").toURI().toString())));
}
else {
wall.setHealth(newHealth);
}
}
base.getChildren().remove(bullet.getView());
base2.getChildren().remove(bullet.getView());
}
}
for (Tank tank : players){
if (bullet.isColliding(tank)){
bullet.setDead(true);
double newHealth = tank.getHealth()-10;
tank.getHealthBar().setBar(newHealth);
if(newHealth==0){
tank.setLives(tank.getLives()-1);
if (tank.getLives() == 0){
tank.setDead(true);
playMedia(new MediaPlayer(new Media(new File("/Users/hashimjacobs/IdeaProjects/TankGame/src/sample/sprites/TITANIC-FLUTE-FAIL-Sound-Effect-Best-Sound-Effects-TV.wav").toURI().toString())));
base.getChildren().remove(tank.getView());
base2.getChildren().remove(tank.getView());
Text theEnd = new Text(base.getPrefWidth()/2,base.getPrefHeight()/2,"You is Dead...");
theEnd.setFont(Font.font("Comic Sans",FontWeight.EXTRA_BOLD,40));
base.getChildren().add(theEnd);
}
else {
resetPlayer(tank);
}
}
}
}
for (GameObject bull : bullets){
if (bullet.isColliding(bull)){
bullet.setDead(true); bull.setDead(true);
base.getChildren().remove(bull.getView());
base2.getChildren().remove(bull.getView());
}
}
}
// handle tank collision
for (GameObject tank : players){
for (GameObject wall : walls){
if (tank.isColliding(wall)){
tank.setVelocity(tank.getFormerVelocity());
tank.setVelocity(new Point2D(0,0));
}
}
}
bullets.removeIf(GameObject::isDead);
enemies.removeIf(GameObject::isDead);
walls.removeIf(GameObject::isDead);
bullets.forEach(GameObject::update);
enemies.forEach(GameObject::update);
walls.forEach(GameObject::update);
for (GameObject tank : players) {
tank.update();
}
}
@Override
public void start(Stage primaryStage) {
// Background Music
playMedia(mp);
Scene scene = new Scene(createContent(),992,864, Color.GREEN);
primaryStage.setTitle("Ratchet Tank Pew Pew");
primaryStage.setScene(scene);
primaryStage.setResizable(false);
// Movement Controls
primaryStage.getScene().setOnKeyPressed((KeyEvent e) -> {
tank1.setFormerVelocity(tank1.getVelocity());
tank2.setFormerVelocity(tank2.getVelocity());
if (e.getCode() == KeyCode.UP) {
tank2.moveForwards();
}
if (e.getCode() == KeyCode.DOWN){
tank2.moveBackwards();
}
if (e.getCode() == KeyCode.LEFT) {
tank2.rotateLeft();
}
if (e.getCode() == KeyCode.RIGHT) {
tank2.rotateRight();
}
if (e.getCode() == KeyCode.W) {
tank1.moveForwards();
}
if (e.getCode() == KeyCode.S){
tank1.moveBackwards();
}
if (e.getCode() == KeyCode.A) {
tank1.rotateLeft();
}
if (e.getCode() == KeyCode.D){
tank1.rotateRight();
}
if (e.getCode() == KeyCode.COMMA) {
Bullet bullet = new Bullet(new ImageView(new Image("sample/sprites/pewpew.png", 20, 20, true, true)));
shoot(tank2,bullet,tank2.getRVelocity());
playMedia(new MediaPlayer(new Media(new File("/Users/hashimjacobs/IdeaProjects/TankGame/src/sample/sprites/shottyToDaBody.wav").toURI().toString())));
}
if (e.getCode() == KeyCode.SHIFT) {
Bullet bullet = new Bullet(new ImageView(new Image("sample/sprites/pewpew.png", 20, 20, true, true)));
shoot(tank1,bullet,tank1.getRVelocity());
playMedia(new MediaPlayer(new Media(new File("/Users/hashimjacobs/IdeaProjects/TankGame/src/sample/sprites/shottyToDaBody.wav").toURI().toString())));
}
});
primaryStage.getScene().setOnKeyReleased((KeyEvent e) -> {
if (e.getCode() == KeyCode.LEFT)
tank2.setVelocity(new Point2D(0,0));
if (e.getCode() == KeyCode.RIGHT)
tank2.setVelocity(new Point2D(0,0));
if (e.getCode() == KeyCode.A)
tank1.setVelocity(new Point2D(0,0));
if (e.getCode() == KeyCode.D)
tank1.setVelocity(new Point2D(0,0));
if (e.getCode() == KeyCode.W)
tank1.setVelocity(new Point2D(0,0));
if (e.getCode() == KeyCode.S)
tank1.setVelocity(new Point2D(0,0));
if (e.getCode() == KeyCode.UP)
tank2.setVelocity(new Point2D(0,0));
if (e.getCode() == KeyCode.DOWN)
tank2.setVelocity(new Point2D(0,0));
});
// Movement Controls END
primaryStage.show();
}
// Instantiates player tank objects, set initial velocity, and add to map
private void initPlayers() {
tank1 = new Tank(new ImageView(new Image("sample/sprites/sickTank.png", 80, 80, true, false)));
tank2 = new Tank(new ImageView(new Image("sample/sprites/sickTank2.png", 80, 80, true, false)));
tank1.setVelocity(new Point2D(0,0));
tank2.setVelocity(new Point2D(0,0));
players.add(tank1);
players.add(tank2);
tank1.setInitPos(300,400);
tank2.setInitPos(650,400);
addGameObject(tank1, tank1.getInitX(),tank1.getInitY());
addGameObject(tank2, tank2.getInitX(),tank2.getInitY());
}
private void resetPlayer(Tank tank){
base.getChildren().remove(tank.getView());
base2.getChildren().remove(tank.getView());
tank.getView().setTranslateX(tank.getInitX());
tank.getView().setTranslateY(tank.getInitY());
}
// Adds a bullet object to the scene
protected void shoot(Tank tank,GameObject bullet, Point2D point){
bullets.add(bullet);
if (tank.getVelocity() == tank.getFormerVelocity()) {
bullet.setVelocity(tank.getVelocity());
addGameObject(bullet,tank.getView().getTranslateX(),tank.getView().getTranslateY());
bullet.moveForwards();
}
else {
bullet.setVelocity(new Point2D(tank.getView().getTranslateX(),tank.getView().getTranslateY()).normalize().multiply(3));
addGameObject(bullet,tank.getView().getTranslateX(),tank.getView().getTranslateY());
}
}
// Adds an enemy to the scene
private void spawnEnemy(){
Enemy enemy = new Enemy(new ImageView(new Image("sample/sprites/aNuttaSickTank.png",30,30,true,true)));
enemies.add(enemy);
if (Math.random()+1 < .001){
addGameObject(enemy, base.getPrefWidth(), 864);
}
}
// Adds a game object to the scene
private Node addGameObject(GameObject object, double x, double y) {
object.getView().setTranslateX(x);
object.getView().setTranslateY(y);
return object.getView();
//base.getChildren().add(object.getView());
//base2.getChildren().add(object.getView());
}
// Sets walls and 'Nexus'
private void buildMap(){
int map[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,1,1,1,1,0,0,1,0,0,0,0,2,2,2,2,2,0,0,1,1,1,0,0,1,1,1,1,
1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,6,1,
1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,
1,0,0,0,1,0,0,2,2,1,1,1,1,1,1,1,1,0,0,0,0,2,2,2,2,0,0,1,0,0,1,
0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,
0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,
0,0,0,0,1,0,0,1,0,0,2,2,2,2,2,2,2,0,0,1,0,0,0,0,1,0,0,2,0,0,1,
1,0,0,0,1,0,0,1,0,0,2,3,0,0,0,0,2,0,0,1,0,0,0,0,1,0,0,2,0,0,1,
1,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,0,0,1,0,0,0,0,1,0,0,1,0,0,1,
1,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,0,0,1,0,0,0,0,1,0,0,1,0,0,1,
1,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,0,0,1,0,0,0,0,1,0,0,1,0,0,1,
0,0,0,0,2,0,0,1,0,0,2,0,0,0,0,0,2,0,0,1,0,0,0,0,1,0,0,1,0,0,1,
0,0,0,0,2,0,0,1,0,0,2,2,2,2,2,2,2,0,0,1,0,0,0,0,1,0,0,1,0,0,1,
0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,
1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,
1,0,0,0,1,2,2,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,
1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,0,0,0,0,1,2,2,1,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,
1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,
1,0,0,0,1,0,0,1,1,1,1,1,1,1,1,2,2,2,1,1,0,0,2,1,1,0,0,1,4,0,1,
1,0,0,0,1,0,0,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,
1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,
1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
// Loops through map array to add walls and 'Nexus' to scene
for (int i = 0;i<31;i++){
for (int j = i; j<837;j+=31){
int index = map[j];
int x_pixel = i*32;
int y_pixel = (j/31)*32;
switch (index) {
case 1: Wall unwall = new UnbreakableWall(new ImageView(new Image("sample/sprites/unbreakablewall.jpg",32,32,false,true)));
Wall unwall2 = new UnbreakableWall(new ImageView(new Image("sample/sprites/unbreakablewall.jpg",32,32,false,true)));
walls.add(unwall);
walls2.add(unwall2);
base.getChildren().add(addGameObject(unwall,x_pixel,y_pixel));
base2.getChildren().add(addGameObject(unwall2,x_pixel,y_pixel));
break;
case 2:
Wall wall = new BreakableWall(new ImageView(new Image("sample/sprites/breakablewall.jpg",32,32,false,true)));
walls.add(wall);
addGameObject(wall,x_pixel,y_pixel);
break;
case 3:
Pentagon pentagon = new Pentagon(new ImageView(new Image("sample/sprites/PentagonUpgrade.png",100,100,true,true)));
addGameObject(pentagon,x_pixel,y_pixel);
break;
case 4:
PowerUp missile = new PowerUp(new ImageView(new Image("sample/sprites/missile.png",40,40,false,true)));
powerups.add(missile);
addGameObject(missile,x_pixel,y_pixel);
break;
case 5:
PowerUp shield = new PowerUp(new ImageView(new Image("sample/sprites/shield.png",40,40,false,true)));
powerups.add(shield);
addGameObject(shield,x_pixel,y_pixel);
break;
case 6:
PowerUp crack = new PowerUp(new ImageView(new Image("sample/sprites/redbull.png",50,50,true,true)));
powerups.add(crack);
addGameObject(crack,x_pixel,y_pixel);
break;
}
}
}
}
public static void main(String[] args) {
launch(args);
}
}