Код IT
← Каталог

Объектно-ориентированное программирование в Java — Ещё один пример

Фрагмент из «Объектно-ориентированное программирование в Java»: Ещё один пример.

Java main.java
package com.test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class SpaceInvaders extends JPanel implements ActionListener, KeyListener {
    private static final int BOARD_WIDTH = 800;
    private static final int BOARD_HEIGHT = 600;
    private static final int PLAYER_WIDTH = 40;
    private static final int PLAYER_HEIGHT = 20;
    private static final int ENEMY_ROWS = 5;
    private static final int ENEMY_COLS = 10;
    private static final int ENEMY_WIDTH = 30;
    private static final int ENEMY_HEIGHT = 20;
    private static final int BULLET_SIZE = 4;

    private Timer timer;
    private Player player;
    private List<Enemy> enemies;
    private List<Bullet> bullets;
    private boolean[] keys = new boolean[256];
    private int score = 0;
    private int lives = 3;
    private boolean gameOver = false;
    private boolean gameWon = false;
    private int enemyDirection = 1; // 1 — right, -1 — left
    private int enemyStepDown = 0;

    public SpaceInvaders() {
        setPreferredSize(new Dimension(BOARD_WIDTH, BOARD_HEIGHT));
        setBackground(Color.BLACK);
        setFocusable(true);
        addKeyListener(this);

        initGame();
        timer = new Timer(20, this); // ~50 FPS
        timer.start();
    }

    private void initGame() {
        player = new Player(BOARD_WIDTH / 2 - PLAYER_WIDTH / 2, BOARD_HEIGHT - 40);
        enemies = new ArrayList<>();
        bullets = new ArrayList<>();

        for (int row = 0; row < ENEMY_ROWS; row++) {
            for (int col = 0; col < ENEMY_COLS; col++) {
                int x = 100 + col * (ENEMY_WIDTH + 10);
                int y = 50 + row * (ENEMY_HEIGHT + 10);
                enemies.add(new Enemy(x, y));
            }
        }

        score = 0;
        lives = 3;
        gameOver = false;
        gameWon = false;
        enemyDirection = 1;
        enemyStepDown = 0;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (gameOver) {
            drawGameOver(g);
        } else if (gameWon) {
            drawGameWon(g);
        } else {
            drawPlayer(g);
            drawEnemies(g);
            drawBullets(g);
            drawHUD(g);
        }
    }

    private void drawPlayer(Graphics g) {
        g.setColor(Color.GREEN);
        g.fillRect(player.x, player.y, PLAYER_WIDTH, PLAYER_HEIGHT);
    }

    private void drawEnemies(Graphics g) {
        g.setColor(Color.RED);
        for (Enemy e : enemies) {
            g.fillRect(e.x, e.y, ENEMY_WIDTH, ENEMY_HEIGHT);
        }
    }

    private void drawBullets(Graphics g) {
        g.setColor(Color.WHITE);
        for (Bullet b : bullets) {
            g.fillRect(b.x, b.y, BULLET_SIZE, BULLET_SIZE);
        }
    }

    private void drawHUD(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.PLAIN, 16));
        g.drawString("Score: " + score, 10, 20);
        g.drawString("Lives: " + lives, BOARD_WIDTH - 100, 20);
    }

    private void drawGameOver(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 40));
        FontMetrics fm = g.getFontMetrics();
        String text = "GAME OVER";
        int x = (BOARD_WIDTH - fm.stringWidth(text)) / 2;
        int y = BOARD_HEIGHT / 2;
        g.drawString(text, x, y);
        g.setFont(new Font("Arial", Font.PLAIN, 20));
        g.drawString("Press R to restart", x + 80, y + 40);
    }

    private void drawGameWon(Graphics g) {
        g.setColor(Color.CYAN);
        g.setFont(new Font("Arial", Font.BOLD, 40));
        FontMetrics fm = g.getFontMetrics();
        String text = "YOU WIN!";
        int x = (BOARD_WIDTH - fm.stringWidth(text)) / 2;
        int y = BOARD_HEIGHT / 2;
        g.drawString(text, x, y);
        g.setFont(new Font("Arial", Font.PLAIN, 20));
        g.drawString("Press R to restart", x + 70, y + 40);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (!gameOver && !gameWon) {
            updatePlayer();
            updateBullets();
            updateEnemies();
            checkCollisions();
            checkWinOrLose();
        }
        repaint();
    }

    private void updatePlayer() {
        if (keys[KeyEvent.VK_LEFT] && player.x > 0) {
            player.x -= 5;
        }
        if (keys[KeyEvent.VK_RIGHT] && player.x < BOARD_WIDTH - PLAYER_WIDTH) {
            player.x += 5;
        }
        if (keys[KeyEvent.VK_SPACE]) {
            shoot();
            keys[KeyEvent.VK_SPACE] = false;
        }
    }

    private void shoot() {
        bullets.add(new Bullet(player.x + PLAYER_WIDTH / 2 - BULLET_SIZE / 2, player.y));
    }

    private void updateBullets() {
        bullets.removeIf(b -> b.y < 0);
        for (Bullet b : bullets) {
            b.y -= 7;
        }
    }

    private void updateEnemies() {
        boolean moveDown = false;
        for (Enemy e : enemies) {
            if ((enemyDirection == 1 && e.x + ENEMY_WIDTH >= BOARD_WIDTH - 10) ||
                    (enemyDirection == -1 && e.x <= 10)) {
                moveDown = true;
                break;
            }
        }

        if (moveDown) {
            enemyDirection *= -1;
            for (Enemy e : enemies) {
                e.y += 20;
            }
        } else {
            for (Enemy e : enemies) {
                e.x += 2 * enemyDirection;
            }
        }
    }

    private void checkCollisions() {
        List<Bullet> bulletsToRemove = new ArrayList<>();
        List<Enemy> enemiesToRemove = new ArrayList<>();

        for (Bullet b : bullets) {
            for (Enemy e : enemies) {
                if (b.x < e.x + ENEMY_WIDTH &&
                        b.x + BULLET_SIZE > e.x &&
                        b.y < e.y + ENEMY_HEIGHT &&
                        b.y + BULLET_SIZE > e.y) {
                    bulletsToRemove.add(b);
                    enemiesToRemove.add(e);
                    score += 10;
                    break;
                }
            }
        }

        bullets.removeAll(bulletsToRemove);
        enemies.removeAll(enemiesToRemove);

        for (Enemy e : enemies) {
            if (e.y + ENEMY_HEIGHT >= player.y) {
                lives = 0;
                break;
            }
        }
    }

    private void checkWinOrLose() {
        if (enemies.isEmpty()) {
            gameWon = true;
        }
        if (lives <= 0) {
            gameOver = true;
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        keys[e.getKeyCode()] = true;
        if (e.getKeyCode() == KeyEvent.VK_R && (gameOver || gameWon)) {
            initGame();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() != KeyEvent.VK_SPACE) {
            keys[e.getKeyCode()] = false;
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    private static class Player {
        int x, y;
        Player(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    private static class Enemy {
        int x, y;
        Enemy(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    private static class Bullet {
        int x, y;
        Bullet(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Space Invaders");
        SpaceInvaders game = new SpaceInvaders();
        frame.add(game);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
package com.test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class SpaceInvaders extends JPanel implements ActionListener, KeyListener {
    private static final int BOARD_WIDTH = 800;
    private static final int BOARD_HEIGHT = 600;
    private static final int PLAYER_WIDTH = 40;
    private static final int PLAYER_HEIGHT = 20;
    private static final int ENEMY_ROWS = 5;
    private static final int ENEMY_COLS = 10;
    private static final int ENEMY_WIDTH = 30;
    private static final int ENEMY_HEIGHT = 20;
    private static final int BULLET_SIZE = 4;

    private Timer timer;
    private Player player;
    private List<Enemy> enemies;
    private List<Bullet> bullets;
    private boolean[] keys = new boolean[256];
    private int score = 0;
    private int lives = 3;
    private boolean gameOver = false;
    private boolean gameWon = false;
    private int enemyDirection = 1; // 1 — right, -1 — left
    private int enemyStepDown = 0;

    public SpaceInvaders() {
        setPreferredSize(new Dimension(BOARD_WIDTH, BOARD_HEIGHT));
        setBackground(Color.BLACK);
        setFocusable(true);
        addKeyListener(this);

        initGame();
        timer = new Timer(20, this); // ~50 FPS
        timer.start();
    }

    private void initGame() {
        player = new Player(BOARD_WIDTH / 2 - PLAYER_WIDTH / 2, BOARD_HEIGHT - 40);
        enemies = new ArrayList<>();
        bullets = new ArrayList<>();

        for (int row = 0; row < ENEMY_ROWS; row++) {
            for (int col = 0; col < ENEMY_COLS; col++) {
                int x = 100 + col * (ENEMY_WIDTH + 10);
                int y = 50 + row * (ENEMY_HEIGHT + 10);
                enemies.add(new Enemy(x, y));
            }
        }

        score = 0;
        lives = 3;
        gameOver = false;
        gameWon = false;
        enemyDirection = 1;
        enemyStepDown = 0;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (gameOver) {
            drawGameOver(g);
        } else if (gameWon) {
            drawGameWon(g);
        } else {
            drawPlayer(g);
            drawEnemies(g);
            drawBullets(g);
            drawHUD(g);
        }
    }

    private void drawPlayer(Graphics g) {
        g.setColor(Color.GREEN);
        g.fillRect(player.x, player.y, PLAYER_WIDTH, PLAYER_HEIGHT);
    }

    private void drawEnemies(Graphics g) {
        g.setColor(Color.RED);
        for (Enemy e : enemies) {
            g.fillRect(e.x, e.y, ENEMY_WIDTH, ENEMY_HEIGHT);
        }
    }

    private void drawBullets(Graphics g) {
        g.setColor(Color.WHITE);
        for (Bullet b : bullets) {
            g.fillRect(b.x, b.y, BULLET_SIZE, BULLET_SIZE);
        }
    }

    private void drawHUD(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.PLAIN, 16));
        g.drawString("Score: " + score, 10, 20);
        g.drawString("Lives: " + lives, BOARD_WIDTH - 100, 20);
    }

    private void drawGameOver(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 40));
        FontMetrics fm = g.getFontMetrics();
        String text = "GAME OVER";
        int x = (BOARD_WIDTH - fm.stringWidth(text)) / 2;
        int y = BOARD_HEIGHT / 2;
        g.drawString(text, x, y);
        g.setFont(new Font("Arial", Font.PLAIN, 20));
        g.drawString("Press R to restart", x + 80, y + 40);
    }

    private void drawGameWon(Graphics g) {
        g.setColor(Color.CYAN);
        g.setFont(new Font("Arial", Font.BOLD, 40));
        FontMetrics fm = g.getFontMetrics();
        String text = "YOU WIN!";
        int x = (BOARD_WIDTH - fm.stringWidth(text)) / 2;
        int y = BOARD_HEIGHT / 2;
        g.drawString(text, x, y);
        g.setFont(new Font("Arial", Font.PLAIN, 20));
        g.drawString("Press R to restart", x + 70, y + 40);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (!gameOver && !gameWon) {
            updatePlayer();
            updateBullets();
            updateEnemies();
            checkCollisions();
            checkWinOrLose();
        }
        repaint();
    }

    private void updatePlayer() {
        if (keys[KeyEvent.VK_LEFT] && player.x > 0) {
            player.x -= 5;
        }
        if (keys[KeyEvent.VK_RIGHT] && player.x < BOARD_WIDTH - PLAYER_WIDTH) {
            player.x += 5;
        }
        if (keys[KeyEvent.VK_SPACE]) {
            shoot();
            keys[KeyEvent.VK_SPACE] = false;
        }
    }

    private void shoot() {
        bullets.add(new Bullet(player.x + PLAYER_WIDTH / 2 - BULLET_SIZE / 2, player.y));
    }

    private void updateBullets() {
        bullets.removeIf(b -> b.y < 0);
        for (Bullet b : bullets) {
            b.y -= 7;
        }
    }

    private void updateEnemies() {
        boolean moveDown = false;
        for (Enemy e : enemies) {
            if ((enemyDirection == 1 && e.x + ENEMY_WIDTH >= BOARD_WIDTH - 10) ||
                    (enemyDirection == -1 && e.x <= 10)) {
                moveDown = true;
                break;
            }
        }

        if (moveDown) {
            enemyDirection *= -1;
            for (Enemy e : enemies) {
                e.y += 20;
            }
        } else {
            for (Enemy e : enemies) {
                e.x += 2 * enemyDirection;
            }
        }
    }

    private void checkCollisions() {
        List<Bullet> bulletsToRemove = new ArrayList<>();
        List<Enemy> enemiesToRemove = new ArrayList<>();

        for (Bullet b : bullets) {
            for (Enemy e : enemies) {
                if (b.x < e.x + ENEMY_WIDTH &&
                        b.x + BULLET_SIZE > e.x &&
                        b.y < e.y + ENEMY_HEIGHT &&
                        b.y + BULLET_SIZE > e.y) {
                    bulletsToRemove.add(b);
                    enemiesToRemove.add(e);
                    score += 10;
                    break;
                }
            }
        }

        bullets.removeAll(bulletsToRemove);
        enemies.removeAll(enemiesToRemove);

        for (Enemy e : enemies) {
            if (e.y + ENEMY_HEIGHT >= player.y) {
                lives = 0;
                break;
            }
        }
    }

    private void checkWinOrLose() {
        if (enemies.isEmpty()) {
            gameWon = true;
        }
        if (lives <= 0) {
            gameOver = true;
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        keys[e.getKeyCode()] = true;
        if (e.getKeyCode() == KeyEvent.VK_R && (gameOver || gameWon)) {
            initGame();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() != KeyEvent.VK_SPACE) {
            keys[e.getKeyCode()] = false;
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    private static class Player {
        int x, y;
        Player(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    private static class Enemy {
        int x, y;
        Enemy(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    private static class Bullet {
        int x, y;
        Bullet(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Space Invaders");
        SpaceInvaders game = new SpaceInvaders();
        frame.add(game);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}