Untitled

mail@pastecode.io avatar
unknown
java
2 years ago
19 kB
5
Indexable
Never
package com.company;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.plaf.nimbus.State;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

class GeometryUtils {
    static boolean areRectsIntersecting(Rectangle2D a, Rectangle2D b) {
        return (a.getX() <= b.getX() + b.getWidth()) && (a.getX() + a.getWidth() >= b.getX()) &&
                (a.getY() <= b.getY() + b.getHeight()) && (a.getY() + a.getHeight() >= b.getY());
    }

    static Rectangle2D getRectsIntersection(Rectangle2D a, Rectangle2D b) {
        double x = Math.max(a.getX(), b.getX());
        double y = Math.max(a.getY(), b.getY());

        double width = Math.min(a.getX() + a.getWidth(), b.getX() + b.getWidth()) - Math.max(a.getX(), b.getX());
        double height = Math.min(a.getY() + a.getHeight(), b.getY() + b.getHeight()) - Math.max(a.getY(), b.getY());

        return new Rectangle2D.Double(x, y, width, height);
    }

    static float distanceBetween(GameObject a, GameObject b) {
        return (float)Math.sqrt((a.getX() - b.getX()) * (a.getX() - b.getX()) +
                (a.getY() - b.getY()) * (a.getY() - b.getY()));
    }
}

class ResourcesManager {
    private static ResourcesManager resourcesManager = new ResourcesManager();

    private Map<String, Image> imagesMap = new HashMap<>();

    public static ResourcesManager getInstance() {
        return resourcesManager;
    }

    private ResourcesManager() {

    }

    public Image loadImage(String path) {
        if (imagesMap.containsKey(path)) {
            return imagesMap.get(path);
        }

        try {
            Image image = ImageIO.read(new File(path));
            imagesMap.put(path, image);

            return image;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

class GameObject {
    private float x;
    private float y;

    private float width;
    private float height;

    private boolean isStatic = false;

    GameObject() {

    }

    public boolean isStatic() {
        return isStatic;
    }

    public void setStatic(boolean isStatic) {
        this.isStatic = isStatic;
    }

    public void setPosition(float x, float y) {
        setX(x);
        setY(y);
    }

    public void move(float x, float y) {
        if (isStatic()) {
            throw new RuntimeException();
        }

        this.x += x;
        this.y += y;
    }

    public void setSize(float width, float height) {
        setWidth(width);
        setHeight(height);
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }

    public float getWidth() {
        return width;
    }

    public void setWidth(float width) {
        this.width = width;
    }

    public float getHeight() {
        return height;
    }

    public void setHeight(float height) {
        this.height = height;
    }

    public Rectangle2D getRect() {
        return new Rectangle2D.Float(getX(), getY(), getWidth(), getHeight());
    }

    public void update(float delta) {

    }

    public void render(Graphics2D g) {

    }

    public void handleKeyPress(char keyChar) {

    }

    public void handleKeyRelease(char keyChar) {

    }
}

class TexturedBlock extends GameObject {
    private Image image;

    TexturedBlock(Image image) {
        this.image = image;
    }

    @Override
    public void render(Graphics2D g) {
        g.drawImage(image, (int) getX(), (int) getY(), (int) getWidth(), (int) getHeight(), null);

        g.setColor(Color.BLACK);
//        g.drawRect((int) getX(), (int) getY(), (int) getWidth(), (int) getHeight());
    }

    public Image getImage() {
        return image;
    }

    public void setImage(Image image) {
        this.image = image;
    }
}

enum PlayerState {
    Jump,
    OnPlatform,
    Falling,
    NotAlive
}

class Player extends TexturedBlock {
    private float direction = 0.0f;

    private final float acceleration = 50.8f;
    private float velocity = 0.0f;

    PlayerState state = PlayerState.Falling;

    private int scores = 0;

    private ArrayList<Platform> platforms;

    Player(ArrayList<Platform> platforms) {
        super(ResourcesManager.getInstance().loadImage("C:\\Users\\nikolai\\IdeaProjects\\untitled\\assets\\png\\player.png"));
        this.platforms = platforms;
    }

    boolean isOnPlatform() {
        return state == PlayerState.OnPlatform;
    }

    void setAlive(boolean alive) {
        if (alive) {
            state = PlayerState.Falling;
        } else {
            state = PlayerState.NotAlive;
        }
    }

    boolean isAlive() {
        return state != PlayerState.NotAlive;
    }

    void setScores(int scores) {
        this.scores = scores;
    }

    int getScores() {
        return scores;
    }

    void increaseScores(int increase) {
        scores += increase;
    }

    @Override
    public void update(float delta) {
        float speed = 300.0f;
        move(delta * speed * direction, 0);

        if (state != PlayerState.OnPlatform) {
            velocity += acceleration * delta;
            move(0, velocity);
        }

//        if (state == PlayerState.Falling) {
//            state = PlayerState.Falling;
////            velocity = acceleration * 1.5f;
//        }

        boolean somePlatformIsFound = false;

        for (Platform platform : platforms) {
            if (GeometryUtils.areRectsIntersecting(getRect(), platform.getRect())) {
                Rectangle2D intersection = GeometryUtils.getRectsIntersection(getRect(), platform.getRect());

                if (intersection.getWidth() < intersection.getHeight()) {
                    move(-direction * (float) intersection.getWidth(), 0);
                } else {
                    int pushingDirection = -1;

                    if (getY() < platform.getY() + platform.getHeight() && getY() > platform.getY()) {
                        pushingDirection = 1;
                    }

                    move(0, (float) intersection.getHeight() * pushingDirection);
                }

                if (intersection.getWidth() > 10) {
                    if (intersection.getY() + intersection.getHeight() < getY() + getHeight() / 2.0f) {
                        velocity = 0;
                    } else {
                        state = PlayerState.OnPlatform;
                        velocity = 0;
                        somePlatformIsFound = true;
                    }
                }
            }
        }

        if (!somePlatformIsFound) {
            if (state == PlayerState.OnPlatform) {
                state = PlayerState.Falling;
            }
        }
    }

    @Override
    public void handleKeyPress(char keyChar) {
        // w a s d

        if (keyChar == 'd') {
            direction = 1.0f;
        } else if (keyChar == 'a') {
            direction = -1.0f;
        } else if (keyChar == ' ') {
            if (state == PlayerState.OnPlatform) {
                velocity = -acceleration * 0.4f;
                state = PlayerState.Falling;
            }
        }
    }

    @Override
    public void handleKeyRelease(char keyChar) {
        if (keyChar == 'd' || keyChar == 'a') {
            direction = 0.0f;
        }
    }
}

enum PlatformType {
    Grass,
    Wood
}


class Platform extends TexturedBlock {
    Platform(PlatformType type) {
        super(null);

        Image image = null;

        if (type == PlatformType.Grass) {
            image = ResourcesManager.getInstance().loadImage("C:\\Users\\nikolai\\IdeaProjects\\untitled\\assets\\grass_flat.png");
        } else if (type == PlatformType.Wood) {
            image = ResourcesManager.getInstance().loadImage("C:\\Users\\nikolai\\IdeaProjects\\untitled\\assets\\wood.png");
        }

        setImage(image);
    }

    @Override
    public void update(float delta) {

    }
}

class Coin extends TexturedBlock {
    Coin() {
        super(ResourcesManager.getInstance().loadImage("C:\\Users\\nikolai\\IdeaProjects\\untitled\\assets\\coin.png"));
    }
}

class Spike extends TexturedBlock {
    Spike() {
        super(ResourcesManager.getInstance().loadImage("C:\\Users\\nikolai\\IdeaProjects\\untitled\\assets\\spike_2.png"));
    }

    void setTriggered(boolean triggered) {
        if (triggered) {
            setImage(ResourcesManager.getInstance().loadImage("C:\\Users\\nikolai\\IdeaProjects\\untitled\\assets\\spike_1.png"));
        }
        else {
            setImage(ResourcesManager.getInstance().loadImage("C:\\Users\\nikolai\\IdeaProjects\\untitled\\assets\\spike_2.png"));
        }
    }
}


enum GameState {
    Loading,
    GameActive,
    GameOver,
    GameWin
}

class Viewport extends JPanel {
    private JFrame window;

    private Random random = new Random();
    private final ArrayList<GameObject> gameObjects = new ArrayList<>();

    private final ArrayList<Platform> platforms = new ArrayList<>();
    private final ArrayList<Coin> coins = new ArrayList<>();
    private final ArrayList<Spike> spikes = new ArrayList<>();

    private Player player;

    private GameState gameState = GameState.Loading;
    private Font gameWinFont = new Font("TimesRoman", Font.PLAIN, 82);
    private Font gameOverFont = new Font("TimesRoman", Font.PLAIN, 82);
    private Font restartFont = new Font("TimesRoman", Font.PLAIN, 30);
    private Font scoresFont = new Font("TimesRoman", Font.PLAIN, 24);

    public Viewport(JFrame window) {
        this.window = window;
    }

    public void initializeGame() {
        TexturedBlock background = new TexturedBlock(ResourcesManager.getInstance().loadImage("C:\\Users\\nikolai\\IdeaProjects\\untitled\\assets\\cloudy2.jpg"));
        background.setPosition(0, 0);
        background.setSize(getWidth(), getHeight());
        background.setStatic(true);

        gameObjects.add(background);

        player = new Player(platforms);
        player.setPosition(0.0f, 0.0f);
        player.setSize(50.0f, 75.0f);

        gameObjects.add(player);

//        addPlatform(PlatformType.Grass, 10, 50, 50, 50);
//        addPlatform(PlatformType.Grass, 10 + 50 * 1, 50, 50, 50);
//        addPlatform(PlatformType.Grass, 10 + 50 * 2, 50, 50, 50);
//        addPlatform(PlatformType.Grass, 10 + 50 * 3, 50, 50, 50);

        addPlatform(PlatformType.Grass, 10, 200, 50, 50);
        addPlatform(PlatformType.Grass, 10 + 50 * 1, 200, 50, 50);
        addPlatform(PlatformType.Grass, 10 + 50 * 2, 200, 50, 50);
        addPlatform(PlatformType.Grass, 10 + 50 * 3, 200, 50, 50);

        addPlatform(PlatformType.Grass, 300, 100, 50, 50);
        addPlatform(PlatformType.Grass, 300 + 50 * 1, 100, 50, 50);
        addPlatform(PlatformType.Grass, 300 + 50 * 2, 100, 50, 50);
        addPlatform(PlatformType.Grass, 300 + 50 * 3, 100, 50, 50);

        for (int index = 0; index < 50; index++) {
            addPlatform(PlatformType.Grass, 500 + 50 * index, 100, 50, 50);
        }

        addPlatform(PlatformType.Grass, 10 + 50 * 4, 200 + 70 * 1, 50, 50);
        addPlatform(PlatformType.Grass, 10 + 50 * 5, 200 + 70 * 1, 50, 50);
        addPlatform(PlatformType.Grass, 10 + 50 * 6, 200 + 70 * 1, 50, 50);

        addPlatform(PlatformType.Grass, 10 + 50 * 7, 200 + 70 * 2, 50, 50);
        addPlatform(PlatformType.Grass, 10 + 50 * 8, 200 + 70 * 2, 50, 50);

        addCoin(10 + 50 * 7 + 20, 200 + 70 * 2 - 50, 25, 25);
        addCoin(10 + 50 * 7 + 100, 200 + 70 * 2 - 50, 25, 25);
        addCoin(10 + 50 * 7 + 150, 200 + 70 * 2 - 50, 25, 25);

        addCoin(300 + 20, 100 - 45, 25, 25);
        addCoin(300 + 70, 100 - 45, 25, 25);

        addSpike(10 + 50 * 7 + 20, 200 + 70 * 2 - 25, 50, 25);
        addSpike(400 + 50 * 2, 100 - 25, 50, 25);
        addSpike(400 + 50 * 4, 100 - 25, 50, 25);
        addSpike(400 + 50 * 7, 100 - 25, 50, 25);

        gameState = GameState.GameActive;
    }

    public void deinitializeGame() {
        player = null;
        platforms.clear();
        coins.clear();
        spikes.clear();
        gameObjects.clear();
    }

    private void locateObject(GameObject object, float x, float y, float width, float height) {
        object.setPosition(x, y);
        object.setSize(width, height);
    }

    private void addPlatform(PlatformType platformType, float x, float y, float width, float height) {
        Platform platform = new Platform(platformType);
        locateObject(platform, x, y, width, height);

        gameObjects.add(platform);
        platforms.add(platform);
    }

    private void addCoin(float x, float y, float width, float height) {
        Coin coin = new Coin();
        locateObject(coin, x, y, width, height);
        gameObjects.add(coin);
        coins.add(coin);
    }

    private void addSpike(float x, float y, float width, float height) {
        Spike spike = new Spike();
        locateObject(spike, x, y, width, height);
        gameObjects.add(spike);
        spikes.add(spike);
    }

    public void handleKeyPress(KeyEvent event) {
        if (gameState == GameState.GameOver || gameState == GameState.GameWin) {
            switch (event.getExtendedKeyCode()) {
                case KeyEvent.VK_ESCAPE:
                    deinitializeGame();
                    window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING));
                    break;
                case KeyEvent.VK_R:
                    deinitializeGame();
                    initializeGame();
                    gameState = GameState.GameActive;
                    break;

                default:
                    break;
            }
        } else {
            for (GameObject object : gameObjects) {
                object.handleKeyPress(event.getKeyChar());
            }
        }

        repaint();
    }

    public void handleKeyRelease(KeyEvent event) {
        for (GameObject object : gameObjects) {
            object.handleKeyRelease(event.getKeyChar());
        }

        repaint();
    }

    public void updateGame(float delta) {
        if (gameState == GameState.Loading) {
            return;
        }

        if (gameState == GameState.GameActive) {
            for (GameObject object : gameObjects) {
                object.update(delta);
            }
        }

        // Сборка монет
        ArrayList<Coin> coinsToRemove = new ArrayList<>();

        for (Coin coin : coins) {
            if (GeometryUtils.areRectsIntersecting(player.getRect(), coin.getRect())) {
                coinsToRemove.add(coin);
                player.increaseScores(1);
            }
        }

        for (Coin coin : coinsToRemove) {
            coins.remove(coin);
            gameObjects.remove(coin);
        }

        if (player.isOnPlatform()) {
            for (Spike spike : spikes) {
                spike.setTriggered(GeometryUtils.distanceBetween(player, spike) < 200.0f);

                if (GeometryUtils.areRectsIntersecting(player.getRect(), spike.getRect())) {
                    player.setAlive(false);
                    break;
                }
            }
        }

        if (player.getY() > getHeight()) {
            player.setAlive(false);
        }

        if (player.isAlive()) {
            if (player.getX() < getWidth() / 4.0f || player.getX() + player.getWidth() >= getWidth() * (3.0f / 4.0f)) {
                float movement = player.getX() < getWidth() / 4.0f ? getWidth() / 4.0f - player.getX() :
                        (getWidth() * (3.0f / 4.0f) - (player.getX() + player.getWidth()));

                for (GameObject object : gameObjects) {
                    if (!object.isStatic()) {
                        object.move(movement, 0.0f);
                    }
                }
            }
        }

        if (!player.isAlive()) {
            gameState = GameState.GameOver;
        } else {
            if (coins.isEmpty()) {
                gameState = GameState.GameWin;
            }
        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        if (gameState == GameState.Loading) {
            return;
        }

        g.setColor(Color.BLACK);
        g.fillRect(0, 0, getWidth(), getHeight());

        for (GameObject object : gameObjects) {
            object.render((Graphics2D) g);
        }

        // Рисуем GUI
        if (gameState == GameState.GameOver) {
            g.setFont(gameOverFont);
            g.drawString("Game over!", 100, 100);

            g.setFont(restartFont);
            g.drawString("Press R to restart", 100, 150);
            g.drawString("Press ESC to exit", 100, 180);
        } else if (gameState == GameState.GameWin) {
            g.setColor(Color.GREEN);
            g.setFont(gameWinFont);
            g.drawString("Winning!", 100, 100);

            g.setColor(Color.BLACK);
            g.setFont(restartFont);
            g.drawString("Press R to restart", 100, 150);
            g.drawString("Press ESC to exit", 100, 180);
        } else {
            g.setColor(Color.YELLOW);
            g.setFont(scoresFont);
            g.drawString("Scores: " + player.getScores(), 10, 40);
        }
    }
}

class GraphicsWindow extends JFrame {
    private final Viewport viewport;

    public GraphicsWindow(String title, int width, int height) throws IOException {
        super(title);

        viewport = new Viewport(this);
        add(viewport);
        pack();
        setSize(width, height);
        setResizable(false);
        setFocusable(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

        viewport.initializeGame();

        addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent event) {
                event.consume();
                viewport.handleKeyPress(event);
            }

            public void keyReleased(KeyEvent event) {
                event.consume();
                viewport.handleKeyRelease(event);
            }
        });

        Timer timer = new Timer(33, new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                long time = System.currentTimeMillis();

                viewport.updateGame(33.0f / 1000.0f);
                viewport.repaint();
            }
        });

        timer.start();
    }

    public Viewport getViewport() {
        return viewport;
    }
}


public class Main {
    public static void main(String[] args) throws IOException {
        new GraphicsWindow("Asteroids game", 640, 480);
    }
}