質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

484閲覧

esc キーを押したときにポーズ画面を表示したい

RRk

総合スコア2

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

0クリップ

投稿2024/05/22 07:36

実現したいこと

プレイヤーがゲームをしている最中にescキーを押して、ゲームを一時停止できるようにしています。

getKeyCode() =KeyEvent.VK_ESCAPE の方で timerをストップさせ、そのあとにplaying = false にし,そのあともう一回 esc を押すと、timer がリスタートし、またゲームが再開するという仕組みになっています。リスタートする時には playing = true になっています。

そして、playing = false(一回だけ esc を押してポーズをしている状態)の時に、画面に 「PAUSED」という文字を表示させたいです。

発生している問題・分からないこと

esc キーでゲームの進行を止めることはできましたが、「PUASED」という文字の表示ができません。

該当のソースコード

board.java

1package breakout; 2 3import javax.swing.JPanel; 4 5 6 7import javax.swing.Timer; 8import java.awt.color.*; 9import java.awt.Font; 10import java.awt.Color; 11import java.awt.Dimension; 12import java.awt.FontMetrics; 13import java.awt.Graphics2D; 14import java.awt.Graphics; 15import java.awt.Point; 16import java.awt.RenderingHints; 17import java.awt.Toolkit; 18import java.awt.event.KeyEvent; 19import java.awt.event.ActionEvent; 20import java.awt.event.KeyAdapter; 21import java.awt.event.ActionListener; 22import java.awt.event.KeyListener; 23 24public class Board extends JPanel { 25 private Timer timer; 26 private String message = "GAME OVER"; 27 private ball Ball; 28 private Paddle paddle; 29 private Brick[] bricks; 30 private boolean Game = true;//run the game or not 31 private TAdapter keyAdapter; 32 private int score = 0; 33 private boolean playing = true; 34 35 36 public Board(){ 37 initBoard(); 38 39 } 40 41 private void initBoard() { 42 43 this.keyAdapter = new TAdapter(); 44 addKeyListener(this.keyAdapter); 45 setFocusable(true); 46 setPreferredSize(new Dimension (Commons.width, Commons.height)); 47 gameInit(); 48 } 49 50 private void gameInit() { 51 bricks = new Brick[Commons.totalBricks]; 52 Ball = new ball(); 53 paddle = new Paddle(); 54 55 int k = 0; 56 57 for (int i =0; i < 5; i++) { 58 for (int j = 0; j < 6; j++) { 59 bricks[k] = new Brick(j*60+30, i*25+80);//place the bricks on the panel 60 k++; 61 } 62 } 63 timer = new Timer(Commons.period, new GameCycle());//perform actions 64 timer.start(); 65 66 } 67 68 69 @Override 70 public void paintComponent(Graphics g) { 71 super.paintComponent(g); 72 73 var g2d = (Graphics2D) g; 74 75 76 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 77 g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 78 79 if(Game) { 80 drawObjects(g2d);//drawing all objects in the game 81 if(!playing) { 82 pausedScreen(g2d);//ここでポーズ画面を表示させたい 83 } 84 } 85 86 else { 87 gameFinished(g2d);//display result 88 } 89 90 91 Toolkit.getDefaultToolkit().sync(); 92 } 93 94 private void drawObjects(Graphics2D g2d) {//基本的なゲーム画面 95 g2d.drawImage(Ball.getImage(), Ball.getX(), Ball.getY(), Ball.getImageWidth(), Ball.getImageHeight(), this); 96 g2d.drawImage(paddle.getImage(), paddle.getX(), paddle.getY(), paddle.getImageWidth(), paddle.getImageHeight(), this); 97 98 g2d.setColor(Color.black); 99 g2d.setFont(new Font("Monospaced",Font.BOLD, 25)); 100 g2d.drawString("Score: "+score, 30,40); 101 102 for (int i =0; i<Commons.totalBricks; i++) { 103 104 if (!bricks[i].isDestroyed()) { 105 g2d.drawImage(bricks[i].getImage(), bricks[i].getX(), bricks[i].getY(), bricks[i].getImageWidth(), bricks[i].getImageHeight(), this); 106 107 } 108 } 109 110 } 111 112 private void pausedScreen(Graphics2D g2d) {//ポーズ画面 113 g2d.setColor(Color.black); 114 g2d.setFont(new Font("Monospaced",Font.BOLD,25)); 115 g2d.drawString("PAUSE",200,200); 116 } 117 118 119 private void gameFinished(Graphics2D g2d) { 120 //called when a player failed 121 var font = new Font("Verdana", Font.BOLD, 18); 122 FontMetrics fontMetrics = this.getFontMetrics(font); 123 124 String scoreMessage = "Score: "+score; 125 String restartMessage = "Press ENTER to restart"; 126 g2d.setColor(Color.black); 127 g2d.setFont(font); 128 129 g2d.drawString(message,(Commons.width - fontMetrics.stringWidth(message))/2, Commons.width/2); 130 g2d.drawString(scoreMessage, (Commons.width - fontMetrics.stringWidth(scoreMessage))/2,250); 131 g2d.drawString(restartMessage,(Commons.width - fontMetrics.stringWidth(restartMessage))/2,300); 132 133 addKeyListener(this.keyAdapter); 134 } 135 136 137 138 //key listeners 139 private class TAdapter extends KeyAdapter { 140 @Override 141 public void keyReleased(KeyEvent e) { 142 paddle.keyReleased(e);//perform when key released 143 } 144 145 @Override 146 public void keyPressed(KeyEvent e) { 147 if(e.getKeyCode()== KeyEvent.VK_ESCAPE){ 148 if(Game) { 149 if(playing) { 150 timer.stop(); 151 playing = false; 152 } 153 else if(!playing) { 154 timer.restart(); 155 playing =true; 156 } 157 158 } 159 } 160 paddle.keyPressed(e);//move the paddle when the key is pressed 161 162 //press enter to restart and initialize the score 163 if (e.getKeyCode() == KeyEvent.VK_ENTER) { 164 if (!Game) { 165 Game = true; 166 score = 0; 167 168 timer.setRepeats(false); 169 initBoard(); 170 } 171 172 } 173 174 } 175 } 176 177 private class GameCycle implements ActionListener{ 178 @Override 179 public void actionPerformed(ActionEvent e) { 180 doGameCycle(); 181 } 182 } 183 184 185 private void doGameCycle() { 186 187 //call all movements 188 Ball.ballmove(); 189 paddle.move(); 190 checkCollision(); 191 repaint(); 192 193 } 194 private void stopGame() { 195 //stop the game 196 Game = false; 197 timer.stop(); 198 199 } 200 201 private void checkCollision() { 202 if (Ball.getRect().getMaxY()>Commons.bottomEdge) { 203 //Game Over 204 stopGame(); 205 } 206 207 for (int i = 0,j = 0; i<Commons.totalBricks; i++) { 208 if (bricks[i].isDestroyed()) { 209 j++; 210 } 211 212 if (j==Commons.totalBricks) { 213 message = "Victory"; 214 stopGame(); 215 } 216 }

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果
  • keypressed は戻り値がないからreturnは使えない
  • Graphic2DのクラスはTAdaptor クラスでは呼べない
  • drawObjects の方に同じ if(!playing){... を書いてみたけれど、結果ポーズ画面は表示されなかった

補足

特になし

TN8001😄を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2024/05/22 07:54

全体的な話になりますが、そも Board クラスでゲーム自体からゲーム終了から途中停止まで全てやらないといけないのでしょうか。 例えば Board クラスでゲーム自体とし、ゲーム終了や一時停止はそれぞれ別の Panel にして Board クラスと随時差し替えるとかレイアウトによって上に重ねるとかする方法もあると思いますが。
RRk

2024/05/22 08:33

問題解決できました! ご回答ありがとうございました。
guest

回答2

0

ベストアンサー

Swing の表示は全て paintComponent で行います。
キー操作によって表示を変えるのなら、表示要因を変更したうえで repaint 等を呼んで Swing に表示を更新して貰う形になります。


質問へのコメントで提案させて頂きましたが、ゲームパネル・フィニッシュパネル・一時停止パネルを用意して重ねて置き、状況によって表示を切り替える形を作って見ました。
こうするとゲームパネルの paintComponent 等から全体の状況別の処理切替が無くなります。

一応ゲームパネルはそれっぽく動いている状態を見れるように、左上に (Timer が動いていることを示す)ランダムに動き続けるバーと、左右矢印キーで数値を増減できる数値の表示を置き、数値が 0 か 100 になったらフィニッシュとしてその数値をスコアとして表示するようにしてみました。
フィニッシュ後は ENTER で再スタート、ゲーム中は ESC で一時停止/復帰します。

PanelsFrame.java

java

1import java.awt.*; 2import java.awt.event.*; 3import java.util.Random; 4import java.util.function.BiConsumer; 5 6import javax.swing.*; 7 8public class PanelsFrame extends JFrame { 9 public static void main(String[] args) { 10 SwingUtilities.invokeLater(() -> new PanelsFrame().setVisible(true)); 11 } 12 13 PanelsFrame() { 14 super("PanelsFrame"); 15 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16 17 GamePanel gamePanel = new GamePanel(); 18 PausePanel pausePanel = new PausePanel(gamePanel::resume); //esc が押されたら gamePanel.resume() を呼ぶ 19 FinishedPanel finishedPanel = new FinishedPanel(gamePanel::start); //enter が押されたら gamePane.start() を呼ぶ 20 21 gamePanel.setPauseListener(pausePanel::showAndFocus); //esc が押されたら pausePanel.showAndFocus() を呼ぶ 22 gamePanel.setFinishedListener(finishedPanel::showAndFocus); //finish したら finishedPanel.showAndFocus(String,int) を呼ぶ 23 24 setLayout(new OverlayLayout(getContentPane())); //全てを重ねる 25 add(finishedPanel); //一番上 26 add(pausePanel); 27 add(gamePanel); //一番下 28 pack(); 29 30 gamePanel.start(); 31 } 32} 33 34class StringDrawer { 35 private Font font; 36 private FontMetrics fontMetrics; 37 38 StringDrawer(JComponent comp, Font font) { 39 this.font = font; 40 fontMetrics = comp.getFontMetrics(font); 41 } 42 void drawInCenter(Graphics g, String s, JComponent comp) { 43 int x = (comp.getWidth() - fontMetrics.stringWidth(s)) / 2; 44 int y = (comp.getHeight() - fontMetrics.getHeight()) / 2; 45 draw(g, s, x, y); 46 } 47 void draw(Graphics g, String s, int x, int y) { 48 g.setFont(font); 49 g.drawString(s, x, y + fontMetrics.getAscent()); 50 } 51} 52 53class GamePanel extends JPanel { 54 private BiConsumer<String,Integer> finishedListener; 55 private Runnable pauseListener; 56 private StringDrawer sd1, sd2; 57 private Timer timer; 58 private Random random = new Random(); 59 private int keycode, value, bar; 60 61 GamePanel() { 62 super(null); 63 setSize(400, 400); 64 setPreferredSize(getSize()); 65 setFocusable(true); 66 setBackground(Color.CYAN); //重なりを分かり易くするため色を付けてみる 67 68 sd1 = new StringDrawer(this, getFont()); 69 sd2 = new StringDrawer(this, getFont().deriveFont(Font.BOLD, 50f)); 70 71 addKeyListener(new KeyAdapter() { 72 @Override 73 public void keyPressed(KeyEvent e) { 74 int kc = e.getKeyCode(); 75 if(kc == KeyEvent.VK_LEFT || kc == KeyEvent.VK_RIGHT) keycode = kc; 76 } 77 @Override 78 public void keyReleased(KeyEvent e) { 79 int kc = e.getKeyCode(); 80 if(kc == KeyEvent.VK_ESCAPE) pause(); 81 if(kc == keycode) keycode = 0; 82 } 83 private void pause() { 84 timer.stop(); 85 keycode = 0; 86 if(pauseListener != null) pauseListener.run(); 87 } 88 }); 89 } 90 91 void setFinishedListener(BiConsumer<String,Integer> listener) { 92 finishedListener = listener; 93 } 94 void setPauseListener(Runnable listener) { 95 pauseListener = listener; 96 } 97 98 void start() { 99 keycode = 0; 100 value = 50; 101 resume(); 102 } 103 104 void resume() { 105 requestFocus(); 106 timer = new Timer(50, e -> { 107 if(value == 0 || value == 100) { //終わり判定 108 timer.stop(); 109 if(finishedListener != null) finishedListener.accept(value==0?"GAME OVER":"Victory", value); //テキトウに渡してみる 110 return; 111 } 112 if(keycode == KeyEvent.VK_LEFT) value -= 1; 113 if(keycode == KeyEvent.VK_RIGHT) value += 1; 114 bar = random.nextInt(10); //タイマーが動いているかを確認する為の表示 115 repaint(); 116 }); 117 timer.start(); 118 } 119 120 @Override 121 public void paintComponent(Graphics g) { 122 super.paintComponent(g); 123 124 sd1.draw(g, "=".repeat(bar), 10, 10); 125 sd2.drawInCenter(g, "← " + value + " →", this); 126 } 127} 128 129abstract class OverlapPanel extends JPanel { 130 OverlapPanel(Color bg) { 131 super(new GridBagLayout()); 132 setBackground(bg); 133 setFocusable(true); 134 setVisible(false); 135 } 136 137 void showAndFocus() { 138 setVisible(true); 139 requestFocus(); 140 } 141 142 protected JLabel addLabel(String text, Color fg, Font font, Object constraints) { 143 JLabel label = new JLabel(text); 144 label.setForeground(fg); 145 label.setFont(font); 146 add(label, constraints); 147 return label; 148 } 149 150 protected enum KeyAction { 151 PRESSED { 152 KeyListener createKeyListener(JComponent comp, int keyCode, Runnable listener) { 153 return new KeyAdapter() { 154 @Override 155 public void keyPressed(KeyEvent e) { if(e.getKeyCode() == keyCode) action(comp, listener); } 156 }; 157 } 158 }, 159 RELEASED { 160 KeyListener createKeyListener(JComponent comp, int keyCode, Runnable listener) { 161 return new KeyAdapter() { 162 @Override 163 public void keyReleased(KeyEvent e) { if(e.getKeyCode() == keyCode) action(comp, listener); } 164 }; 165 } 166 }; 167 168 abstract KeyListener createKeyListener(JComponent comp, int keyCode, Runnable listener); 169 private static void action(JComponent comp, Runnable listener) { 170 comp.setVisible(false); 171 listener.run(); 172 } 173 } 174 175 protected void addKeyEvent(int keyCode, KeyAction keyAction, Runnable listener) { 176 addKeyListener(keyAction.createKeyListener(this, keyCode, listener)); 177 } 178} 179 180class FinishedPanel extends OverlapPanel { 181 private JLabel messageLabel, scoreLabel; 182 183 FinishedPanel(Runnable restartListener) { 184 super(new Color(0,0,0,180)); //半透明 185 186 Font font = new Font("Verdana", Font.BOLD, 18); 187 188 GridBagConstraints gbc = new GridBagConstraints(); 189 gbc.gridx = 0; 190 191 messageLabel = addLabel(null, Color.WHITE, font, gbc); 192 add(Box.createVerticalStrut(50), gbc); 193 scoreLabel = addLabel(null, Color.WHITE, font, gbc); 194 add(Box.createVerticalStrut(30), gbc); 195 addLabel("Press ENTER to restart", Color.GREEN, font, gbc); 196 197 addKeyEvent(KeyEvent.VK_ENTER, KeyAction.PRESSED, restartListener); 198 } 199 200 void showAndFocus(String message, int score) { 201 messageLabel.setText(message); 202 scoreLabel.setText("Score: " + score); 203 showAndFocus(); 204 } 205} 206 207class PausePanel extends OverlapPanel { 208 PausePanel(Runnable resumeListener) { 209 super(new Color(100,100,100,180)); //白っぽい半透明 210 211 addLabel("PAUSE", Color.YELLOW, new Font("Monospaced", Font.BOLD, 25), null); 212 213 addKeyEvent(KeyEvent.VK_ESCAPE, KeyAction.RELEASED, resumeListener); 214 } 215}

一時停止時画面
フィニッシュ時画面(Victory)

投稿2024/05/22 08:15

編集2024/05/24 11:11
jimbe

総合スコア13170

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RRk

2024/05/22 08:33

回答ありがとうございます。 repaintを呼んだところ、問題が解決しました! ベストアンサーに選ばせていただきました。
RRk

2024/05/23 08:23

追加の回答ありがとうございます。 こちらのコードも参考にさせていただきます。
jimbe

2024/05/23 17:11

ちょっとコードを修正しました。 FinishedPanel と PausePanel から共通の OverlapPanel を抜き出したり等で動きは変わりません。 コードが減るかと思ったら増えてしまいました、 KeyAction がやり過ぎか…。
guest

0

解決済みですが...

前回(提示コード不足で)動かしていなかったので気が付きませんでしたが、リトライするたびにaddKeyListenerされていきますね(1回のキー操作で複数回keyPressedが呼ばれるようになる)

Timerも不要に複数個作っています(なんでtimer.setRepeats(false)しているのかと思いましたが今回の問題と同根です)

こんな感じがいいんじゃないかな?(BallPaddle等も作り直さなくてもいいかもしれないが)

java

1public class Board extends JPanel { 2 private final Timer timer; 3 private String message = "GAME OVER"; 4 private Ball ball; 5 private Paddle paddle; 6 private Brick[] bricks; 7 private boolean game; 8 private int score; 9 private boolean playing; 10 11 public Board() { 12 addKeyListener(new TAdapter()); 13 setFocusable(true); 14 setPreferredSize(new Dimension(Commons.width, Commons.height)); 15 timer = new Timer(Commons.period, new GameCycle()); 16 initBoard(); 17 } 18 19 private void initBoard() { 20 game = true; 21 score = 0; 22 playing = true; 23 bricks = new Brick[Commons.totalBricks]; 24 ball = new Ball(); 25 paddle = new Paddle(); 26 27 for (int i = 0, k = 0; i < 5; i++) { 28 for (int j = 0; j < 6; j++) { 29 bricks[k] = new Brick(j * 60 + 30, i * 25 + 80); 30 k++; 31 } 32 } 33 timer.start(); 34 }

投稿2024/05/22 10:16

TN8001

総合スコア9813

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RRk

2024/05/23 08:22

回答ありがとうございます。 addKeyListener は多分試行錯誤していた時の産物ですね。timer は指摘されるまで気づきませんでした。どちらも自分では気づかないところだったので、参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問