📄 game.java
字号:
* Handles a keyboard event. This will result in different actions * being taken, depending on the key pressed. In some cases, other * events will be launched. This method is synchronized to avoid * race conditions with other asynchronous events (timer and * mouse). * * @param e the key event */ private synchronized void handleKeyEvent(KeyEvent e) { // Handle start, pause and resume if (e.getKeyCode() == KeyEvent.VK_P) { handleButtonPressed(); return; } // Don't proceed if stopped or paused if (figure == null || moveLock || thread.isPaused()) { return; } // Handle remaining key events switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: figure.moveLeft(); break; case KeyEvent.VK_RIGHT: figure.moveRight(); break; case KeyEvent.VK_DOWN: figure.moveAllWayDown(); moveLock = true; break; case KeyEvent.VK_UP: case KeyEvent.VK_SPACE: if (e.isControlDown()) { figure.rotateRandom(); } else if (e.isShiftDown()) { figure.rotateClockwise(); } else { figure.rotateCounterClockwise(); } break; case KeyEvent.VK_S: if (level < 9) { level++; handleLevelModification(); } break; case KeyEvent.VK_N: preview = !preview; if (preview && figure != nextFigure) { nextFigure.attach(previewBoard, true); nextFigure.detach(); } else { previewBoard.clear(); } break; } } /** * Returns a random figure. The figures come from the figures * array, and will not be initialized. * * @return a random figure */ private Figure randomFigure() { return figures[(int) (Math.random() * figures.length)]; } /** * The game time thread. This thread makes sure that the timer * events are launched appropriately, making the current figure * fall. This thread can be reused across games, but should be set * to paused state when no game is running. */ private class GameThread extends Thread { /** * The game pause flag. This flag is set to true while the * game should pause. */ private boolean paused = true; /** * The number of milliseconds to sleep before each automatic * move. This number will be lowered as the game progresses. */ private int sleepTime = 500; /** * Creates a new game thread with default values. */ public GameThread() { } /** * Resets the game thread. This will adjust the speed and * start the game thread if not previously started. */ public void reset() { adjustSpeed(); setPaused(false); if (!isAlive()) { this.start(); } } /** * Checks if the thread is paused. * * @return true if the thread is paused, or * false otherwise */ public boolean isPaused() { return paused; } /** * Sets the thread pause flag. * * @param paused the new paused flag value */ public void setPaused(boolean paused) { this.paused = paused; } /** * Adjusts the game speed according to the current level. The * sleeping time is calculated with a function making larger * steps initially an smaller as the level increases. A level * above ten (10) doesn't have any further effect. */ public void adjustSpeed() { sleepTime = 4500 / (level + 5) - 250; if (sleepTime < 50) { sleepTime = 50; } } /** * Runs the game. */ public void run() { while (thread == this) { // Make the time step handleTimer(); // Sleep for some time try { Thread.sleep(sleepTime); } catch (InterruptedException ignore) { // Do nothing } // Sleep if paused while (paused && thread == this) { try { Thread.sleep(1000); } catch (InterruptedException ignore) { // Do nothing } } } } } /** * A game panel component. Contains all the game components. */ private class GamePanel extends Container { /** * The component size. If the component has been resized, that * will be detected when the paint method executes. If this * value is set to null, the component dimensions are unknown. */ private Dimension size = null; /** * The score label. */ private Label scoreLabel = new Label("Score: 0"); /** * The level label. */ private Label levelLabel = new Label("Level: 1"); /** * The generic button. */ private Button button = new Button("Start"); /** * Creates a new game panel. All the components will * also be added to the panel. */ public GamePanel() { super(); initComponents(); } /** * Paints the game component. This method is overridden from * the default implementation in order to set the correct * background color. * * @param g the graphics context to use */ public void paint(Graphics g) { Rectangle rect = g.getClipBounds(); if (size == null || !size.equals(getSize())) { size = getSize(); resizeComponents(); } g.setColor(getBackground()); g.fillRect(rect.x, rect.y, rect.width, rect.height); super.paint(g); } /** * Initializes all the components, and places them in * the panel. */ private void initComponents() { GridBagConstraints c; // Set layout manager and background setLayout(new GridBagLayout()); setBackground(Configuration.getColor("background", "#d4d0c8")); // Add game board c = new GridBagConstraints(); c.gridx = 0; c.gridy = 0; c.gridheight = 4; c.weightx = 1.0; c.weighty = 1.0; c.fill = GridBagConstraints.BOTH; this.add(board.getComponent(), c); // Add next figure board c = new GridBagConstraints(); c.gridx = 1; c.gridy = 0; c.weightx = 0.2; c.weighty = 0.18; c.fill = GridBagConstraints.BOTH; c.insets = new Insets(15, 15, 0, 15); this.add(previewBoard.getComponent(), c); // Add score label scoreLabel.setForeground(Configuration.getColor("label", "#000000")); scoreLabel.setAlignment(Label.CENTER); c = new GridBagConstraints(); c.gridx = 1; c.gridy = 1; c.weightx = 0.3; c.weighty = 0.05; c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; c.insets = new Insets(0, 15, 0, 15); this.add(scoreLabel, c); // Add level label levelLabel.setForeground(Configuration.getColor("label", "#000000")); levelLabel.setAlignment(Label.CENTER); c = new GridBagConstraints(); c.gridx = 1; c.gridy = 2; c.weightx = 0.3; c.weighty = 0.05; c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; c.insets = new Insets(0, 15, 0, 15); this.add(levelLabel, c); // Add generic button button.setBackground(Configuration.getColor("button", "#d4d0c8")); c = new GridBagConstraints(); c.gridx = 1; c.gridy = 3; c.weightx = 0.3; c.weighty = 1.0; c.anchor = GridBagConstraints.NORTH; c.fill = GridBagConstraints.HORIZONTAL; c.insets = new Insets(15, 15, 15, 15); this.add(button, c); // Add event handling enableEvents(KeyEvent.KEY_EVENT_MASK); this.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { handleKeyEvent(e); } }); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleButtonPressed(); component.requestFocus(); } }); } /** * Resizes all the static components, and invalidates the * current layout. */ private void resizeComponents() { Dimension size = scoreLabel.getSize(); Font font; int unitSize; // Calculate the unit size size = board.getComponent().getSize(); size.width /= board.getBoardWidth(); size.height /= board.getBoardHeight(); if (size.width > size.height) { unitSize = size.height; } else { unitSize = size.width; } // Adjust font sizes font = new Font("SansSerif", Font.BOLD, 3 + (int) (unitSize / 1.8)); scoreLabel.setFont(font); levelLabel.setFont(font); font = new Font("SansSerif", Font.PLAIN, 2 + unitSize / 2); button.setFont(font); // Invalidate layout scoreLabel.invalidate(); levelLabel.invalidate(); button.invalidate(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -