問題の概要
JavaFXを使ってSnake Gameを作っているのですが、突然画面更新が止まります。
色々試してみたのですが特に決まった発生条件は特定出来ませんでした。
描画以外の処理はちゃんと実行されているようで、ウィンドウだけ固まってる感じです。
エラーメッセージなどは出ません。
対処法がありましたらご教授ください。
よろしくお願いします。
該当のソースコード
Java
1//package,import等省略 2public class Runner extends Application { 3 static ResourceBundle rb = ResourceBundle.getBundle("settings"); 4 5 final int WIDTH = Integer.parseInt(rb.getString("width")); 6 final int HEIGHT = Integer.parseInt(rb.getString("height")); 7 final int plus = (Integer.parseInt(rb.getString("plus")))*10; 8 int cw = WIDTH; 9 int ch = HEIGHT; 10 int size = Integer.parseInt(rb.getString("size")); 11 int speed = Integer.parseInt(rb.getString("speed")); 12 boolean grid = Boolean.parseBoolean(rb.getString("grid")); 13 boolean grad = Boolean.parseBoolean(rb.getString("color")); 14 boolean debug = Boolean.parseBoolean(rb.getString("debug")); 15 String mode = rb.getString("gameMode"); 16 17 int cx = 0; // マークの座標 18 int cy = 0; 19 int dx = size; // マークの進む量 20 int dy = 0; 21 int length = 1; //蛇の長さ 22 int data[][] = new int[WIDTH][HEIGHT]; 23 int point = 0; 24 25 Random o = new Random(); 26 int fx = ((WIDTH/size)/2)-2; 27 int fy = ((HEIGHT/size)/2)-2;//餌の座標 28 29 Alert dlg = new Alert(AlertType.INFORMATION); 30 31 public static void main(String[] args) { 32 launch(args); 33 } 34 35 @Override 36 public void start(Stage stage) throws Exception { 37 stage.setTitle("Snake Game in Java FX!!"); 38 stage.setWidth(WIDTH); 39 stage.setHeight(HEIGHT); 40 stage.initStyle(StageStyle.UTILITY); 41 stage.centerOnScreen(); 42 stage.setResizable(false); 43 44 Group root = new Group(); 45 46 final Canvas canvas = new Canvas(WIDTH, HEIGHT); 47 GraphicsContext gc = canvas.getGraphicsContext2D(); 48 49 canvas.setOnKeyPressed(event -> onKeyPressed(event)); 50 canvas.setFocusTraversable(true); 51 52 root.getChildren().add(canvas); 53 54 stage.setScene(new Scene(root)); 55 stage.show(); 56 57 // クライアント領域の幅と高さ 58 ch = (int) stage.getScene().getHeight(); 59 cw = (int) stage.getScene().getWidth(); 60 // スタート時の座標 61 cx = cw / 2; 62 cy = ch / 2; 63 if(mode.equals("time")) { 64 point+=1; 65 } 66 67 Timer timer = new Timer(); 68 class GameTask extends TimerTask { 69 70 private BooleanProperty gameover = 71 new SimpleBooleanProperty(this, "gameover", false); 72 73 public ReadOnlyBooleanProperty gameoverProperty() { 74 return gameover; 75 } 76 private void setGameover(boolean value) { 77 gameover.set(value); 78 } 79 80 @Override 81 public void run() { 82 gc.setFill(Color.WHITE); 83 gc.fillRect(0,0,cw,ch); 84 gc.setStroke(Color.GRAY); 85 cx += dx; 86 cy += dy; 87 try { 88 System.out.println("(dx,dy,data[cx][cy]):("+dx+","+dy+","+data[cx][cy]+")"); 89 }catch(Exception e) {} 90 if (isTheGameOver()) { 91 Toolkit.getDefaultToolkit().beep(); 92 Platform.runLater(new Runnable() { 93 @Override 94 public void run() { 95 if(debug) { 96 System.out.println("(cx,cy,cw,ch):("+cx+","+cy+","+cw+","+ch+")"); 97 98 } 99 setGameover(true); 100 } 101 }); 102 this.cancel(); 103 }//ゲームオーバーかどうか(行く先が安全かどうか)確認 104 gc.setFill(Color.BLACK); 105 gc.fillRect(cx, cy, size, size); 106 try { 107 data[cx][cy] = length; 108 }catch(Exception e) {} 109 //先端に描画 110 if(cx==((cw/2)%size)+(fx*size) && cy==((ch/2)%size)+(fy*size)) { 111 length++; 112 fx = o.nextInt((cw/size)-4)+2; 113 fy = o.nextInt((ch/size)-4)+2; 114 if(mode.equals("feed"))point += plus; 115 }//食餌判定 116 //すべてのマスについてデータを-1 117 for(int x=(cw / 2)%size;x<WIDTH;x+=size) { 118 for(int y=(ch / 2)%size;y<HEIGHT;y+=size) { 119 data[x][y]--; 120 if(data[x][y]<0) { 121 data[x][y]=0; 122 //gc.setFill(Color.WHITE); 123 //gc.fillRect(x, y, size, size); 124 if(grid) { 125 gc.strokeRect(x, y, size, size); 126 } 127 }else if(data[x][y]!=length-1 && grad){ 128 gc.setFill(Color.color(0.15,0.15,0.15)); 129 gc.fillRect(x, y, size, size); 130 } 131 if(debug) { 132 gc.strokeText(String.valueOf(data[x][y]), x, y+10); 133 } 134 if(x==((cw/2)%size)+(fx*size) && y==((ch/2)%size)+(fy*size)) { 135 gc.setFill(Color.BLUE); 136 gc.fillRect(x, y, size, size); 137 } 138 } 139 } 140 if(mode.equals("time"))point += plus; 141 gc.setStroke(Color.BLACK); 142 gc.strokeText(String.valueOf(point)+"point", 20+size,20+size); 143 } 144 boolean isTheGameOver(){ 145 if (cx < 0) return true; 146 if (cy < 0) return true; 147 if (cx > cw) return true; 148 if (cy > ch-2) return true; 149 if (data[cx][cy] > 0) return true; 150 return false; 151 } 152 } 153 154 GameTask task = new GameTask(); 155 stage.setOnCloseRequest(event -> { 156 if (task != null) 157 task.cancel(); 158 if (timer != null) 159 timer.cancel(); 160 }); 161 timer.schedule(task, 1000, speed); 162 163 task.gameoverProperty().addListener(new ChangeListener<Boolean>() { 164 @Override 165 public void changed(ObservableValue<? extends Boolean> arg0, 166 Boolean arg1, Boolean arg2) { 167 if (task.gameoverProperty().get()) 168 gameOver(); 169 } 170 }); 171 } 172 173 // キーが押された時の処理 174 void onKeyPressed(KeyEvent event) 175 { 176 if (event.getCode() == KeyCode.UP) { dx = 0; dy = -size;} 177 if (event.getCode() == KeyCode.DOWN) { dx = 0; dy = size;} 178 if (event.getCode() == KeyCode.RIGHT) { dx = size; dy = 0;} 179 if (event.getCode() == KeyCode.LEFT) { dx =- size; dy = 0;} 180 } 181 182 // ゲームオーバーになった時の処理 183 void gameOver() 184 { 185 dlg.setTitle("ゲームオーバー"); 186 dlg.setHeaderText(String.format("ゲームオーバー : 得点 : %d", point)); 187 dlg.showAndWait(); 188 Platform.exit(); 189 System.exit(0); 190 } 191}
試したこと
各種変数の追跡など(異常なし)
いろいろな箇所でログを出力(こちらも異常なし)
補足情報
実行環境はJavaSE-9(Java9)です。
settings.propertiesという名前のファイルでコンフィグを設定出来るようにしてあり、内容は以下に示します。
#ver 0.0.2 width = 1200 height = 700 !画面の縦、横の長さをピクセル単位で指定します。 !一般的に、縦横比は16:9程度がちょうどいいです。 speed = 100 !1フレームの長さをミリ秒単位で指定します。 !数値が小さすぎると動作が不安定になります。 !一般的に、50~300程度がちょうどいいです。 size = 40 !ゲームの単位となる正方形の一辺の長さを指定します。 !一般的に、widthの1/30程度がちょうどいいです。 gameMode = feed !ゲームモードを指定します。 !v1.0.2現在、"feed","time"の二つが指定出来ます。 !"feed"モードでは、餌を食べただけポイントが増えます。 !"time"モードでは、生き残った時間だけポイントが増えます。 !なお、"time"モードでは得点の下一桁が'1'となります。 plus = 2 !ポイントの増え幅です。 !実際はここに入力した整数値の10倍のポイントとなります。 grid = true !グリッド線の表示/非表示切り替え。 !true/falseで設定します。 color = true !蛇の先端とそれ以外で色分けをするかどうかをtrue/falseで設定します。 !表示がちょっと不安定。 debug = true !デバッグモードです。 !開発者向け。めちゃくちゃ重くなります。 #
###追記(2018/02/19)
部室のそこそこ高性能なPCで動かしたところ問題なく動いたのですが、マス目の数を増やして負荷をかけていくと固まりました。
処理が追い付いていないと考えられます。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/20 13:31