I try to write a game of Air Hockey, I think the essence of the game is clear. I have three classes, this is the main window, the playing field and the statistical field. The movement of the puck begins after pressing the button from the Statistical field, is carried out by redrawing in the timer handler.
Question one: Before pressing this button, players can move (in the main class), but not simultaneously. I understand the problem in the streams (
Question two: After pressing the button, the puck begins its movement and the players no longer move. Here, as I understand it, the problem is also in the streams (I canβt understand how to do it right. Like everything here, I'm just learning, don't strictly judge the code.
Main class:
package com.company; import javax.swing.*; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import static java.awt.event.KeyEvent.*; public class MainWindow { public MainWindow() { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); // ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΡΠ΅ΠΉΠΌΠ° JFrame jFrame = new JFrame(); jFrame.setLocation(screenSize.width / 2 - (StatisticField.STATISTIC_FIELD_W + GameField.GAME_FIELD_W) / 2, screenSize.height / 2 - StatisticField.STATISTIC_FIELD_H / 2); jFrame.setTitle("Air Hockey"); jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); jFrame.setVisible(true); jFrame.setLayout(new FlowLayout()); jFrame.setResizable(false); jFrame.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); if (e.getKeyCode() == VK_UP) { GameField.setPlayer2Y(GameField.getPlayer2Y() - 5); jFrame.repaint(5); } if (e.getKeyCode() == VK_DOWN) { GameField.setPlayer2Y(GameField.getPlayer2Y() + 5); jFrame.repaint(5); } if (e.getKeyCode() == VK_W) { GameField.setPlayer1Y(GameField.getPlayer1Y() - 5); jFrame.repaint(5); } if (e.getKeyCode() == VK_S) { GameField.setPlayer1Y(GameField.getPlayer1Y() + 5); jFrame.repaint(5); } } }); // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈΠ³ΡΠΎΠ²ΠΎΠ³ΠΎ ΠΈ ΡΡΠ°ΡΠΈΡΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΠΎΠ»Ρ StatisticField statisticField = new StatisticField(); GameField gameField = new GameField(); statisticField.setPreferredSize(new Dimension(StatisticField.STATISTIC_FIELD_W, StatisticField.STATISTIC_FIELD_H)); gameField.setPreferredSize(new Dimension(GameField.GAME_FIELD_W, GameField.GAME_FIELD_H)); jFrame.add(gameField); jFrame.add(statisticField); jFrame.pack(); } public static void main(String[] args) { MainWindow mainWindow = new MainWindow(); } } Playground class:
package com.company; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.Ellipse2D; import java.awt.geom.Rectangle2D; public class GameField extends JPanel implements ActionListener { public static final int WIN_POINTS = 7; // ΠΡΠΊΠΎΠ² Π΄Π»Ρ ΠΏΠΎΠ±Π΅Π΄Ρ public static int GAME_FIELD_H = 400; // ΠΡΡΠΎΡΠ° ΠΈΠ³ΡΠΎΠ²ΠΎΠ³ΠΎ ΠΏΠΎΠ»Ρ public final static int GAME_FIELD_W = 700; // Π¨ΠΈΡΠΈΠ½Π° ΠΈΠ³ΡΠΎΠ²ΠΎΠ³ΠΎ ΠΏΠΎΠ»Ρ private final static int PUCK_SIZE = 20; // Π Π°Π·ΠΌΠ΅Ρ ΡΠ°ΠΉΠ±Ρ private final static int PLAYER_HEIGHT = 100; // ΠΡΡΠΎΡΠ° ΠΈΠ³ΡΠΎΠΊΠΎΠ² private final static int PLAYER_WIDTH = 15; // Π¨ΠΈΡΠΈΠ½Π° ΠΈΠ³ΡΠΎΠΊΠΎΠ² private int puckX; // Π₯-ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ° ΡΠ°ΠΉΠ±Ρ private int puckY; // Π£-ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ° ΡΠ°ΠΉΠ±Ρ private static int player1X; // Π₯-ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ° 1-Π³ΠΎ ΠΈΠ³ΡΠΎΠΊΠ° private static int player1Y; // Π£-ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ° 1-Π³ΠΎ ΠΈΠ³ΡΠΎΠΊΠ° private static int player2X; // Π₯-ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ° 2-Π³ΠΎ ΠΈΠ³ΡΠΎΠΊΠ° private static int player2Y; // Π£-ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠ° 2-Π³ΠΎ ΠΈΠ³ΡΠΎΠΊΠ° private static int player1Points; // ΠΡΠΊΠΈ 1-Π³ΠΎ ΠΈΠ³ΡΠΎΠΊΠ° private static int player2Points; // ΠΡΠΊΠΈ 2-Π³ΠΎ ΠΈΠ³ΡΠΎΠΊΠ° private Timer timerPuck; // ΠΡΠ΅ΠΌΡ ΠΏΠ΅ΡΠ΅ΡΠΈΡΠΎΠ²ΠΊΠΈ private boolean puckUp; // ΠΠ°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ ΡΠ°ΠΉΠ±Ρ private boolean puckDown; private boolean puckLeft; private boolean puckRight; private static boolean player1Up = false; // ΠΠ°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ ΠΈΠ³ΡΠΎΠΊΠΎΠ² private static boolean player1Down = false; private static boolean player2Up = false; private static boolean player2Down = false; private static boolean inGame = false; private int route; // ΠΠ°ΡΠ°Π»ΡΠ½ΠΎΠ΅ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ ΡΠ°ΠΉΠ±Ρ public static int getPlayer1Y() { return player1Y; } public static void setPlayer1Y(int player1Y) { GameField.player1Y = player1Y; } public static int getPlayer2Y() { return player2Y; } public static void setPlayer2Y(int player2Y) { GameField.player2Y = player2Y; } public static boolean isInGame() { return inGame; } public static void setInGame(boolean inGame) { GameField.inGame = inGame; } // ΠΡΡΠΈΡΠΎΠ²ΠΊΠ° ΡΠ°ΠΉΠ±Ρ ΠΈ ΠΈΠ³ΡΠΎΠΊΠΎΠ² @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; Rectangle2D player1 = new Rectangle2D.Double(player1X, player1Y, PLAYER_WIDTH, PLAYER_HEIGHT); Rectangle2D player2 = new Rectangle2D.Double(player2X, player2Y, PLAYER_WIDTH, PLAYER_HEIGHT); Ellipse2D puck = new Ellipse2D.Double(puckX, puckY, PUCK_SIZE, PUCK_SIZE); g2.setColor(Color.RED); g2.fill(puck); g2.setColor(Color.BLACK); g2.fill(player1); g2.fill(player2); } // ΠΠ²ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΡΠ°ΠΉΠ±Ρ public void movePuck() { if(puckUp) puckY -= 1; if(puckDown) puckY += 1; if(puckLeft) puckX -= 1; if(puckRight) puckX += 1; } // ΠΡΠ±ΠΎΡ Π½Π°ΡΠ°Π»ΡΠ½ΠΎΠ³ΠΎ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ ΡΠ°ΠΉΠ±Ρ public void choiceOfDirection(){ route = (int)(Math.random() * 3); if (route == 0) { puckRight = true; puckUp = true; puckLeft = false; puckDown = false; } if (route == 1) { puckRight = false; puckUp = true; puckLeft = true; puckDown = false; } if (route == 2) { puckRight = false; puckUp = false; puckLeft = true; puckDown = true; } if (route == 3) { puckRight = true; puckUp = false; puckLeft = false; puckDown = true; } } // ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΈΠ³ΡΡ public void initGame(){ player1Points = 0; player2Points = 0; choiceOfDirection(); // ΠΠ°ΡΠ°Π»ΡΠ½ΡΠ΅ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΡ ΡΠ°ΠΉΠ±Ρ ΠΈ ΠΈΠ³ΡΠΎΠΊΠΎΠ² puckX = GAME_FIELD_W/2 - PUCK_SIZE/2; puckY = GAME_FIELD_H/2 - PUCK_SIZE/2; player1X = 0; player1Y = GAME_FIELD_H/2 - PLAYER_HEIGHT/2; player2X = GAME_FIELD_W - PLAYER_WIDTH; player2Y = GAME_FIELD_H/2 - PLAYER_HEIGHT/2; timerPuck = new Timer(1, this); timerPuck.start(); } public GameField() { // Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΠ°ΠΌΠΊΠΈ setBorder(BorderFactory.createCompoundBorder( BorderFactory.createRaisedBevelBorder(), BorderFactory.createLoweredBevelBorder())); // ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΈΠ³ΡΡ Π² ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ΅ initGame(); setFocusable(true); } public void playerWin(Label player){ JOptionPane.showMessageDialog( this, player.getText() + " WIN!!!", "Congratulations", JOptionPane.PLAIN_MESSAGE); StatisticField.getStart().setLabel("Start Game"); initGame(); StatisticField.getPoint1().setText("0"); StatisticField.getPoint2().setText("0"); } // ΠΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° ΡΡΠΎΠ»ΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΠ΅ ΡΠ°ΠΉΠ±Ρ Ρ Π±ΠΎΡΡΠ°ΠΌΠΈ ΠΈ Π½Π° Π³ΠΎΠ» public void checkBorder(){ if(puckY == 0){ puckDown = true; puckUp = false; } if(puckY == GAME_FIELD_H - PUCK_SIZE){ puckDown = false; puckUp = true; } if(puckX == PLAYER_WIDTH && puckY + PUCK_SIZE/2 >= player1Y && puckY + PUCK_SIZE/2 <= player1Y + PLAYER_HEIGHT){ puckRight = true; puckLeft = false; } if(puckX == -PUCK_SIZE){ player2Points++; inGame = false; choiceOfDirection(); puckX = GAME_FIELD_W/2 - PUCK_SIZE/2; puckY = GAME_FIELD_H/2 - PUCK_SIZE/2; StatisticField.getPoint2().setText("" + player2Points); if(player2Points == WIN_POINTS){ playerWin(StatisticField.getPlayer2Name()); } } if(puckX == GAME_FIELD_W - PUCK_SIZE - PLAYER_WIDTH && puckY + PUCK_SIZE/2 >= player2Y && puckY + PUCK_SIZE/2 <= player2Y + PLAYER_HEIGHT){ puckLeft = true; puckRight = false; } if(puckX == GAME_FIELD_W + PUCK_SIZE){ player1Points++; inGame = false; choiceOfDirection(); puckX = GAME_FIELD_W/2 - PUCK_SIZE/2; puckY = GAME_FIELD_H/2 - PUCK_SIZE/2; StatisticField.getPoint1().setText("" + player1Points); if(player1Points == WIN_POINTS){ playerWin(StatisticField.getPlayer1Name()); } } } // Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΡΠ°ΠΉΠΌΠ΅ΡΠ° @Override public void actionPerformed(ActionEvent e) { if(inGame) { movePuck(); checkBorder(); repaint(); } } } Class statistical field:
package com.company; import javax.swing.*; import javax.swing.border.Border; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class StatisticField extends JPanel { public final static int STATISTIC_FIELD_H = 400; // ΠΡΡΠΎΡΠ° ΡΡΠ°ΡΠΈΡΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΠΎΠ»Ρ public final static int STATISTIC_FIELD_W = 200; // Π¨ΠΈΡΠΈΠ½Π° ΡΡΠ°ΡΠΈΡΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΠΎΠ»Ρ // ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ private static Label player1Name = new Label("Player 1", Label.CENTER); private static Label player2Name = new Label("Player 2", Label.CENTER); private TextField player1NameTextField = new TextField(); private TextField player2NameTextField = new TextField(); private static Label point1 = new Label("0", Label.CENTER); private static Label point2 = new Label("0", Label.CENTER); private static Button start = new Button("Start Game"); public static Label getPoint1() { return point1; } public static Label getPoint2() { return point2; } public static Label getPlayer1Name() { return player1Name; } public static Label getPlayer2Name() { return player2Name; } public static Button getStart() { return start; } public StatisticField(){ // Π¨ΡΠΈΡΡ ΡΡΠ΅ΡΠ° Font font = new Font("TimesRoman", Font.BOLD, 100); // ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ JPanel settingPanel = new JPanel(); JPanel setting1player = new JPanel(); JPanel setting2player = new JPanel(); JPanel points = new JPanel(); Label colon = new Label(":", Label.CENTER); Border border = BorderFactory.createCompoundBorder( BorderFactory.createRaisedBevelBorder(), BorderFactory.createLoweredBevelBorder()); Label setting1Up = new Label("\"W\" - UP", Label.CENTER); Label setting2Up = new Label("\"UP\" - UP", Label.CENTER); Label setting1Down = new Label("\"S\" - DOWN", Label.CENTER); Label setting2Down = new Label("\"DOWN\" - DOWN", Label.CENTER); Button renamePlayer1 = new Button("Rename"); Button renamePlayer2 = new Button("Rename"); // Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅ΡΠΎΠ² ΠΊΠΎΠΌΠΏΠ°Π½ΠΎΠ²ΠΊΠΈ setLayout(new GridLayout(3, 1)); setting1player.setLayout(new GridLayout(5, 1)); setting2player.setLayout(new GridLayout(5, 1)); settingPanel.setLayout(new GridLayout(1, 2)); points.setLayout(new GridLayout(1, 3)); // Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΠ°ΠΌΠΎΠΊ settingPanel.setBorder(border); points.setBorder(border); // Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΡΠΈΡΡΠ° point1.setFont(font); point2.setFont(font); colon.setFont(font); // ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ°Π½Π΅Π»Ρ points points.add(point1); points.add(colon); points.add(point2); // ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ°Π½Π΅Π»Ρ setting1player setting1player.add(player1Name); setting1player.add(setting1Up); setting1player.add(setting1Down); setting1player.add(player1NameTextField); setting1player.add(renamePlayer1); // ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ°Π½Π΅Π»Ρ setting2player setting2player.add(player2Name); setting2player.add(setting2Up); setting2player.add(setting2Down); setting2player.add(player2NameTextField); setting2player.add(renamePlayer2); // ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ°Π½Π΅Π»Ρ settingPanel settingPanel.add(setting1player); settingPanel.add(setting2player); // ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΡΡΠ°ΡΠΈΡΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΠΏΠΎΠ»Π΅ add(points); add(settingPanel); add(start); // ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΊΠ½ΠΎΠΏΠΊΠΈ start start.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { start.setLabel("Continue Game"); GameField.setInGame(true); } }); // ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΊΠ½ΠΎΠΏΠΊΠΈ renamePlayer1 renamePlayer1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if(!player1NameTextField.getText().equals("")) { player1Name.setText(player1NameTextField.getText()); player1NameTextField.setText(""); } } }); // ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΊΠ½ΠΎΠΏΠΊΠΈ renamePlayer2 renamePlayer2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if(!player2NameTextField.getText().equals("")) { player2Name.setText(player2NameTextField.getText()); player2NameTextField.setText(""); } } }); } }
MVCpattern. - Drakonoved