2017-01-28 98 views
0

我工作的一個學院項目在JavaFX的:像太空Invaders.I一個遊戲試圖讓每個OVNI的一個ParallelTransition動畫,營造出的TimeLine動畫並將其添加到每個人的ParallelTransition中,爲每個人管理一個EventHandler,以便將ovni移動到X位置並在Y到達窗口的左邊界時移動。問題是當我在播放動畫時,只有第一行在x位置正確移動,但其他行不是。換句話說,當其他行在x位置上移動一段距離時,它們不會在邊界上移動,而是移動到Y位置。結果如下:運動問題8

這是方法第二,我已經爲ovnis聲明瞭兩個矩陣:一個用於Panes的矩陣,它將包含每個ovni的形狀;和其他將包含ovni對象。

public Juego(){ 
    lab=new Label(); 
    transicionEnY=new ParallelTransition(); 
    dir=new File(Constantes.GAME_BACKGROUND); 
    Pane navePane=new Pane(); 
    paneOvnis=new Pane[3][6]; //the panes for each ovni´s shape 
    nave=new Nave(navePane); 
    gameContainer=new Pane(); 
    gameContainer.getChildren().addAll(navePane); 
    background=new Image(dir.toURI().toString()); 
    pane=new BorderPane(); 
    pane.setCenter(gameContainer); 
    pane.setBackground(new Background(new BackgroundImage(background,null,null,null,new BackgroundSize(Constantes.MAXIMUM_WIDHT,Constantes.MAXIMUM_HEIGTH,false,false,false,true)))); 
    //playMusic(); 
    agregarOvnis(); 
    moverOvnis(); 
    pane.setBottom(lab); 
} 

來填充每個矩陣的方法:

public void agregarOvnis(){ 
    this.ovnis=new Ovni[paneOvnis.length][paneOvnis[0].length]; 
    for(int i=0;i<paneOvnis.length;i++){ 
     for(int j=0;j<paneOvnis[0].length;j++){  
      Pane paneOvni=new Pane(); 
      Ovni ovni=new OvniGris(paneOvni); 
      ovni.setLocation(Constantes.POS_OVNI_X+Constantes.OVNI_SPACING_X*j,Constantes.POS_OVNI_Y+Constantes.OVNI_SPACING_Y*i); 
      this.gameContainer.getChildren().add(paneOvni); 
      this.paneOvnis[i][j]=paneOvni; 
      this.ovnis[i][j]=ovni; 
     } 
    } 
} 

,使聲明ParallelTransition和使時間軸動畫每個OVNI的方法:

public void moverOvnis(){ 
    ParallelTransition animaciones=new ParallelTransition(); 
    for(int i=0;i<ovnis.length;i++){ 
     for(int j=0;j<ovnis[i].length;j++){ 
      Timeline animacionOvnis=new Timeline(); 
      KeyFrame kf=new KeyFrame(Duration.millis(900),new ManejadorMovimientos(i,j)); 
      animacionOvnis.getKeyFrames().add(kf); 
      animacionOvnis.setCycleCount(Timeline.INDEFINITE); 
      animacionOvnis.setAutoReverse(false); 
      animaciones.getChildren().add(animacionOvnis); 
     } 
    } 
    animaciones.play(); 
} 

最後,這是在時間軸事件處理程序類以使每個ovni的ovni運動:

private class ManejadorMovimientos implements EventHandler<ActionEvent>{ 

    int i; 
    int j; 
    int orientacion=1; 

    public ManejadorMovimientos(int i, int j){ 
     this.i=i; 
     this.j=j; 
    } 

    @Override 
    public void handle(ActionEvent event) { 
     double distanciaMaxDer=maxDistanceRight(); 
     double distanciaMaxIzq=maxDistanceLeft(); 
     lab.setText(""+distanciaMaxDer+","+ovnis[0][5].getXLocation()); 
     if(orientacion==1) 
      if(distanciaMaxDer-30>0){ 
      ovnis[i][j].setLocation(ovnis[i][j].getXLocation()+30,ovnis[i][j].getYLocation()); 
      } 
      else{ 
      ovnis[i][j].setLocation(ovnis[i][j].getXLocation(),ovnis[i][j].getYLocation()+20); 
      orientacion=-1;     
      } 
     else{ 
      if(distanciaMaxIzq-30>30){ 
      ovnis[i][j].setLocation(ovnis[i][j].getXLocation()-30,ovnis[i][j].getYLocation()); 
      } 
      else{ 
      ovnis[i][j].setLocation(ovnis[i][j].getXLocation(),ovnis[i][j].getYLocation()+20); 
      orientacion=1; 
      } 
     } 

    } 

    private double maxDistanceRight(){ 
     int j=ovnis[0].length-1; 
     while(j>=0){ 
      for(int i=0;i<ovnis.length;i++){ 
       if(ovnis[i][j]!=null){ 
        return 1.25*Constantes.MAXIMUM_WIDHT-ovnis[i][j].getXLocation(); 
       } 
      } 
      j--; 
     } 
     return -1; 
    } 

    private double maxDistanceLeft(){ 
     int j=0; 
     while(j<ovnis[0].length){ 
      for(int i=0;i<ovnis.length;i++){ 
       if(ovnis[i][j]!=null){ 
        return ovnis[i][j].getXLocation()-30; 
       } 
      } 
      j++; 
     } 
     return -1; 
    } 

} 

我分別離開這裏的常量,OVNI和遊戲類,以瞭解更多信息(在西班牙語對不起,有些話,我的it's項目的requeriments的一部分。)

常量類

public class Constantes { 

//PARAMETROS GENERALES DEL JUEGO 
public static final double MENU_HEIGTH= 600; 
public static final double MENU_WIDTH= 500; 
public static final double MAXIMUM_HEIGTH = 800; 
public static final double MAXIMUM_WIDHT= 640; 
public static final String MAIN_LOGO="src/backgrounds/logo.png"; 
public static final String MAIN_BACKGROUND="src/backgrounds/mainbackground2.jpg"; 
public static final String GAME_BACKGROUND="src/backgrounds/gamebackground2.jpg"; 
public static final String GAME_BACKGROUND_MUSIC="src/sounds/game.mp3"; 
public static final String MAIN_BACKGROUND_MUSIC="src/sounds/main.mp3"; 

//PARAMETROS DE CONSTRUCCION DE LA NAVE 
public static final double POS_NAVE_X=MAXIMUM_WIDHT/2; 
public static final double POS_NAVE_Y=MAXIMUM_HEIGTH-295; 
public static final double ANCHO_REC_A=50; 
public static final double ALTO_REC_A=18; 
public static final double POS_REC_A_X=(POS_NAVE_X/4)-(ANCHO_REC_A/2); 
public static final double POS_REC_A_Y=POS_NAVE_Y-400; 
public static final double ANCHO_REC_B=ANCHO_REC_A*0.66667; 
public static final double ALTO_REC_B=10; 
public static final double POS_REC_B_X=POS_REC_A_X+ANCHO_REC_B/4; 
public static final double POS_REC_B_Y=POS_NAVE_Y-405; 
public static final double ANCHO_REC_C=ANCHO_REC_B*0.225; 
public static final double ALTO_REC_C=10; 
public static final double POS_REC_C_X=POS_REC_B_X+ANCHO_REC_B/2; 
public static final double POS_REC_C_Y=POS_REC_B_Y; 
public static final double ANCHO_REC_D=ANCHO_REC_C*0.45; 
public static final double ALTO_REC_D=10; 
public static final double POS_REC_D_X=POS_REC_C_X-1; 
public static final double POS_REC_D_Y=POS_REC_C_Y-ALTO_REC_C-ALTO_REC_D+ALTO_REC_C/2; 


//PARAMETROS DE CONSTRUCCION DEL OVNI 
public static final double POS_OVNI_X=70; 
public static final double POS_OVNI_Y=40; 
public static final double POS_CUERPO_OVNI_X=0; 
public static final double POS_CUERPO_OVNI_Y=0; 
public static final double ANCHO_CUERPO_OVNI=23; 
public static final double ALTO_CUERPO_OVNI=15; 
public static final double ANCHO_ARC_IZQ=ANCHO_CUERPO_OVNI*0.22; 
public static final double ALTO_ARC_IZQ=ALTO_CUERPO_OVNI*0.55; 
public static final double POS_ARC_IZQ_X=POS_CUERPO_OVNI_X - ANCHO_CUERPO_OVNI * 0.80 + ANCHO_ARC_IZQ/2; 
public static final double POS_ARC_IZQ_Y=POS_CUERPO_OVNI_Y; 
public static final double ANCHO_ARC_CTR=ANCHO_CUERPO_OVNI*0.35; 
public static final double ALTO_ARC_CTR=ALTO_CUERPO_OVNI*0.30; 
public static final double POS_ARC_CTR_X=POS_CUERPO_OVNI_X; 
public static final double POS_ARC_CTR_Y=POS_CUERPO_OVNI_Y; 
public static final double ANCHO_ARC_DER=ANCHO_CUERPO_OVNI*0.22; 
public static final double ALTO_ARC_DER=ALTO_CUERPO_OVNI*0.55; 
public static final double POS_ARC_DER_X=POS_CUERPO_OVNI_X + ANCHO_CUERPO_OVNI * 0.60 + ANCHO_ARC_DER/2; 
public static final double POS_ARC_DER_Y=POS_CUERPO_OVNI_Y; 
public static final double POS_OVNI_WINDOW_X=POS_CUERPO_OVNI_X - ANCHO_CUERPO_OVNI * 0.80; 
public static final double POS_OVNI_WINDOW_Y=POS_CUERPO_OVNI_Y - ANCHO_CUERPO_OVNI/2; 
public static final double OVNI_SPACING_X=70; 
public static final double OVNI_SPACING_Y=30; 

//PARAMETROS DE MOVIMIENTO NAVE 
public static final double MOVIMIENTO_NAVE=2; 

//PARAMETROS DE MOVIMIENTO OVNI 

}

OVNI類

public abstract class Ovni { 
protected Shape ovni; 

public Ovni(Pane pane){ 
    ovni=buildOvni(); 
    pane.getChildren().add(ovni); 
} 

public void setLocation(double x,double y){ 
    ovni.setLayoutX(x); 
    ovni.setLayoutY(y); 
} 

public double getXLocation(){ 
    return ovni.getLayoutX(); 
} 

public double getYLocation(){ 
    return ovni.getLayoutY(); 
} 

public Shape getOvni() { 
    return ovni; 
} 

public void setOvni(Shape ovni) { 
    this.ovni = ovni; 
} 

public Shape buildOvni(){ 
    Arc arcCuerpo=new Arc(Constantes.POS_CUERPO_OVNI_X,Constantes.POS_CUERPO_OVNI_Y,Constantes.ANCHO_CUERPO_OVNI,Constantes.ALTO_CUERPO_OVNI,0,180); 
    Arc arcL=new Arc(Constantes.POS_ARC_IZQ_X,Constantes.POS_ARC_IZQ_Y,Constantes.ANCHO_ARC_IZQ,Constantes.ALTO_ARC_IZQ,180,180); 
    Arc arcCentro=new Arc(Constantes.POS_ARC_CTR_X,Constantes.POS_ARC_CTR_Y,Constantes.ANCHO_ARC_CTR,Constantes.ALTO_ARC_CTR,180,180); 
    Arc arcD=new Arc(Constantes.POS_ARC_DER_X,Constantes.POS_ARC_DER_Y,Constantes.ANCHO_ARC_DER,Constantes.ALTO_ARC_DER,180,180); 
    Shape union1=Shape.union(arcCuerpo, arcL); 
    Shape union2=Shape.union(union1, arcCentro); 
    Shape union3=Shape.union(union2, arcD); 

    return union3; 
} 

}

GAME類

public class Juego { 
private BorderPane pane; 
private Pane gameContainer; 
private File dir; 
private Image background; 
private MediaPlayer player; 
private Nave nave; 
private Pane[][] paneOvnis; 
private Ovni[][] ovnis; 
private final ParallelTransition transicionEnY; 
Label lab; 
/** 
* 
*/ 
public Juego(){ 
    lab=new Label(); 
    transicionEnY=new ParallelTransition(); 
    dir=new File(Constantes.GAME_BACKGROUND); 
    Pane navePane=new Pane(); 
    paneOvnis=new Pane[3][6]; 
    nave=new Nave(navePane); 
    gameContainer=new Pane(); 
    gameContainer.getChildren().addAll(navePane); 
    background=new Image(dir.toURI().toString()); 
    pane=new BorderPane(); 
    pane.setCenter(gameContainer); 
    pane.setBackground(new Background(new BackgroundImage(background,null,null,null,new BackgroundSize(Constantes.MAXIMUM_WIDHT,Constantes.MAXIMUM_HEIGTH,false,false,false,true)))); 
    //playMusic(); 
    agregarOvnis(); 
    moverOvnis(); 
    pane.setBottom(lab); 
} 

/** 
* 
* @return 
*/ 
public BorderPane getRoot(){ 
    return pane; 
} 

/** 
* 
*/ 
public void playMusic(){ 
    File dir=new File(Constantes.GAME_BACKGROUND_MUSIC); 
    Media music=new Media(dir.toURI().toString()); 
    player=new MediaPlayer(music); 
    player.setOnEndOfMedia(new Runnable() { 
    @Override 
     public void run() { 
      player.seek(Duration.ZERO); 
     } 
    }); 
    player.play(); 
} 

public void agregarOvnis(){ 
    this.ovnis=new Ovni[paneOvnis.length][paneOvnis[0].length]; 
    for(int i=0;i<paneOvnis.length;i++){ 
     for(int j=0;j<paneOvnis[0].length;j++){  
      Pane paneOvni=new Pane(); 
      Ovni ovni=new OvniGris(paneOvni); 
      ovni.setLocation(Constantes.POS_OVNI_X+Constantes.OVNI_SPACING_X*j,Constantes.POS_OVNI_Y+Constantes.OVNI_SPACING_Y*i); 
      this.gameContainer.getChildren().add(paneOvni); 
      this.paneOvnis[i][j]=paneOvni; 
      this.ovnis[i][j]=ovni; 
     } 
    } 
} 

/** 
* 
* @param e 
*/ 
public void moverNave(Event e){ 
    ManejadorTeclas manager=new ManejadorTeclas(); 
    manager.handle((KeyEvent) e); 
} 

public void moverOvnis(){ 
    ParallelTransition animaciones=new ParallelTransition(); 
    for(int i=0;i<ovnis.length;i++){ 
     for(int j=0;j<ovnis[i].length;j++){ 
      Timeline animacionOvnis=new Timeline(); 
      KeyFrame kf=new KeyFrame(Duration.millis(900),new ManejadorMovimientos(i,j)); 
      animacionOvnis.getKeyFrames().add(kf); 
      animacionOvnis.setCycleCount(Timeline.INDEFINITE); 
      animacionOvnis.setAutoReverse(false); 
      animaciones.getChildren().add(animacionOvnis); 
     } 
    } 
    animaciones.play(); 
} 

private class ManejadorTeclas implements EventHandler<KeyEvent>{ 

    @Override 
    public void handle(KeyEvent event) { 
     double movimiento=Constantes.MOVIMIENTO_NAVE; 
     if(event.getCode()==KeyCode.RIGHT && nave.getLocationX()+Constantes.MOVIMIENTO_NAVE<Constantes.MAXIMUM_WIDHT) 
      nave.setLocationX(nave.getLocationX()+3); 
     else if(event.getCode()==KeyCode.LEFT && nave.getLocationX()-Constantes.MOVIMIENTO_NAVE>0) 
      nave.setLocationX(nave.getLocationX()-3); 
     else if(event.getCode()==KeyCode.ESCAPE){ 
      pane.getScene().getWindow().hide(); 
     } 
    } 
} 

private class ManejadorMovimientos implements EventHandler<ActionEvent>{ 

    int i; 
    int j; 
    int orientacion=1; 

    public ManejadorMovimientos(int i, int j){ 
     this.i=i; 
     this.j=j; 
    } 

    @Override 
    public void handle(ActionEvent event) { 
     double distanciaMaxDer=maxDistanceRight(); 
     double distanciaMaxIzq=maxDistanceLeft(); 
     lab.setText(""+distanciaMaxDer+","+ovnis[0][5].getXLocation()); 
     if(orientacion==1) 
      if(distanciaMaxDer-30>0){ 
      ovnis[i][j].setLocation(ovnis[i][j].getXLocation()+30,ovnis[i][j].getYLocation()); 
      } 
      else{ 
      ovnis[i][j].setLocation(ovnis[i][j].getXLocation(),ovnis[i][j].getYLocation()+20); 
      orientacion=-1;     
      } 
     else{ 
      if(distanciaMaxIzq-30>30){ 
      ovnis[i][j].setLocation(ovnis[i][j].getXLocation()-30,ovnis[i][j].getYLocation()); 
      } 
      else{ 
      ovnis[i][j].setLocation(ovnis[i][j].getXLocation(),ovnis[i][j].getYLocation()+20); 
      orientacion=1; 
      } 
     } 

    } 

    private double maxDistanceRight(){ 
     int j=ovnis[0].length-1; 
     while(j>=0){ 
      for(int i=0;i<ovnis.length;i++){ 
       if(ovnis[i][j]!=null){ 
        return 1.25*Constantes.MAXIMUM_WIDHT-ovnis[i][j].getXLocation(); 
       } 
      } 
      j--; 
     } 
     return -1; 
    } 

    private double maxDistanceLeft(){ 
     int j=0; 
     while(j<ovnis[0].length){ 
      for(int i=0;i<ovnis.length;i++){ 
       if(ovnis[i][j]!=null){ 
        return ovnis[i][j].getXLocation()-30; 
       } 
      } 
      j++; 
     } 
     return -1; 
    } 

} 

}

+0

這是它的結果: http://imgur.com/a/jFObp –

+1

請閱讀如何創建[MCVE] – miken32

回答

0

你更新由線的位置線,每次重新計算最右邊的位置。在您將Timeline s添加到ParallelTransition的順序中,右上角的ouvi在更新下ouvis之前更新,這意味着ouvis會考慮在最上面的ouvis之前的一個「幀」之前到達最右邊的位置,問題。

其他備註:

在這種情況下使用ParallelTransition是不必要/低效的,因爲單個Timeline可以處理所有的KeyFrame秒。此外,即使多個KeyFrame是不必要的,因爲ouvis全部在同一時間被更新,並且甚至一些值應該被重用。

下面的例子到處移動簡單的對象:

private Rectangle[][] rects = new Rectangle[3][3]; 

private void moveDown() { 
    for (Rectangle[] column : rects) { 
     for (Rectangle r : column) { 
      if (r != null) { 
       r.setY(r.getY() + 5); 
      } 
     } 
    } 
} 

@Override 
public void start(Stage primaryStage) { 
    Pane root = new Pane(); 
    for (int j = 0; j < rects.length; j++) { 
     Rectangle[] column = rects[j]; 
     for (int i = 0; i < column.length; i++) { 
      Rectangle rect = new Rectangle(20, 20); 
      rect.setX(j * 25); 
      rect.setY(i * 25); 
      root.getChildren().add(rect); 
      column[i] = rect; 
     } 
    } 
    Timeline timeline = new Timeline(new KeyFrame(Duration.millis(500), new EventHandler<ActionEvent>() { 

     boolean movingRight = true; 

     @Override 
     public void handle(ActionEvent event) { 
      double maxX = Double.NEGATIVE_INFINITY; 
      double minX = Double.POSITIVE_INFINITY; 
      outer: 
      for (int i = rects.length - 1; i >= 0; i--) { 
       for (Rectangle r : rects[i]) { 
        if (r != null) { 
         maxX = r.getX() + r.getWidth(); 
         break outer; 
        } 
       } 
      } 
      outer: 
      for (Rectangle[] col : rects) { 
       for (Rectangle r : col) { 
        if (r != null) { 
         minX = r.getX(); 
         break outer; 
        } 
       } 
      } 
      if (movingRight) { 
       if (maxX + 5 > 150) { 
        moveDown(); 
        movingRight = false; 
        return; 
       } 
      } else { 
       if (minX - 5 < 0) { 
        moveDown(); 
        movingRight = true; 
        return; 
       } 
      } 
      double dx = movingRight ? 5 : -5; 
      for (Rectangle[] column : rects) { 
       for (Rectangle r : column) { 
        if (r != null) { 
         r.setX(r.getX() + dx); 
        } 
       } 
      } 
     } 

    })); 
    timeline.setCycleCount(Animation.INDEFINITE); 
    timeline.play(); 

    Scene scene = new Scene(root, 150, 600); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 
+0

謝謝很多幫助我!!!!!這個例子適用於我的項目。 –