2016-12-22 2 views
0

뱀 게임을하고 있지만 draw() 메서드로 캔버스를 업데이트하려고 할 때마다 새로운 뱀이 그려지지 않습니다. run 스레드를 그립니다. 여러 가지 시도를 해봤지만 작동시킬 수는 없습니다.그래픽 콘텍스트는 하나의 스레드에만 그려집니다

수입 :

import javafx.application.Application; 
import javafx.event.*; 
import javafx.scene.*; 
import javafx.stage.*; 
import javafx.scene.control.*; 
import javafx.scene.layout.*; 
import javafx.geometry.*; 
import java.io.*; 
import java.util.*; 
import javafx.scene.input.KeyEvent; 
import javafx.event.EventHandler; 
import javafx.scene.text.Text; 
import javafx.scene.text.Font; 
import javafx.scene.text.*; 
import javafx.scene.paint.*; 
import javafx.scene.canvas.*; 

실제 클래스 : 당신은 자바 FX에서 그래픽을 그릴 수있는 더 좋은 방법을 알고있는 경우

public class Snake extends Application implements Runnable 
{ 
    //Snake parts and locations 
    boolean dead; 
    int headX=0; 
    int headY=0; 
    // for the game 
    Group root = new Group(); 
    Scene snakeG = new Scene(root, 550, 550,Color.BLACK); 
    final Canvas canvas = new Canvas(550,550); 
    GraphicsContext gc = canvas.getGraphicsContext2D(); 
    //Start Game 
    VBox newGame = new VBox(3); 
    Scene startC = new Scene(newGame, 200, 200); 
    Label info = new Label("Snake Game \nCreated by: Austin James"); 
    Label rules = new Label("Rules\n1.) If you hit the edge you die\n2.) If you touch your snake you die\n3.)Collect fruit to increase your snakes size"); 
    Button startBut = new Button("Start Game"); 
    Stage startS; 

    public static void main (String[] args) 
    { 
     launch(args); 
    } 

    @Override 
    public void start (Stage primaryStage)throws Exception 
    { 
     startS=primaryStage; 
     startS.setTitle("Snake"); 
     newGame.getChildren().addAll(info,rules,startBut); 
     newGame.setAlignment(Pos.CENTER); 
     startS.setScene(startC); 
     startS.show(); 

     startBut.setOnAction(e -> 
     { 
      startGame(); 
     }); 
    } 

    public void startGame() 
    { 
     System.out.println("Success"); 
     headX=275; 
     headY=275; 
     dead = false; 
     gc.clearRect(0,0,800,800); 
     startS.setScene(snakeG); 
     gc.setFill(Color.GREEN); 
     gc.fillRect(headX,headY,10,10); 
     root.getChildren().add(canvas); 
     (new Thread (new Snake())).start();  
    } 

    public void run() 
    { 
     draw(); 
    } 

    // draws the snake 
    public void draw() 
    { 
     System.out.println("DRAW STARTED"); 
     gc.setFill(Color.GREEN); 
     gc.fillRect(50,50,10,10); 
    } 
} 

말해주십시오. 이것이 제가하는 일에서 찾을 수있는 유일한 방법입니다.

답변

3

접근 방법에 몇 가지 문제가 있습니다.

  1. 나만의 스레드가 필요하지 않습니다.
  2. JavaFX 스레드를 사용하여 활성 장면 그래프 (캔버스 포함)를 수정할 수만 있습니다. 하는 자바 FX 애플리케이션의 그래픽 사용자 인터페이스를 나타내는 스레드 안전하지 않고 단지 접근 또한 자바 FX 애플리케이션 쓰레드로 알려진 UI 스레드에서 수정 될 수

    자바 FX 장면 그래프, 상기 JavaFX concurrency documentation을 읽는다.

  3. 기본 응용 프로그램 클래스는 Runnable을 구현하면 안됩니다.

제안 :

  1. 당신은 쉽게 게임 객체가 아닌 Canvas에 대한 SceneGraph 노드를 사용하여 찾을 수 있지만, 하나가 작동합니다.
  2. game loopAnimationTimerdemoed here으로 사용하여 구현할 수 있습니다.
  3. 다음은 using an AnimationTimer for display의 샘플입니다.
+0

자체 스레드에서'GraphicsContext2d'를 사용해 본 적이 한번도 없었습니다. 모든 그리기 작업을 UI 스레드에서 호출 할 수 있다고 생각합니다. 나는 또한 소스를 쳐다 보면서 Platform.isFxApplicationThread'에 대한 검사가 없다()' – brian

+0

GraphicsContext 자바 독은 명확하게 나중에 캔버스 노드의 이미지에 의해에 렌더링 될 위치를 __Each 호출이 버퍼 에 필요한 매개 변수를 밀어 상태 끝의 렌더링 스레드. 펄스 .__ 따라서 완전히 스레드 독립적입니다. – Mordechai

+0

@MouseEvent 그러면 스레드가 안전하지 않습니다. 버퍼에 동기화가 없으므로 백그라운드 스레드에서 수정하면 모든 종류의 위험을 감수합니다 : FX 응용 프로그램 스레드가 펄스를 렌더링하는 동안 버퍼를 변경할 수 있습니다. 즉, FX 응용 프로그램 스레드가 잠재적으로 다른 것을 볼 수 있습니다 단일 펄스 동안 버퍼의 상태가 일치하지 않습니다. (생명과 같은 다른 위험 요소도 있습니다.) –

관련 문제