Sabtu, 02 Mei 2026

JAVA - Quadcopter Game 3

 





/*

 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license

 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Main.java to edit this template

 */

package quadcoptergame4;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

import java.util.ArrayList;

import java.util.Random;


public class QuadcopterGame4 extends JPanel implements ActionListener, KeyListener {

    // Game Constants

    private final int WIDTH = 800;

    private final int HEIGHT = 600;

    private Timer timer;

    private int score = 0;

    private boolean gameOver = false;


    // Player Properties

    private double playerX = 400, playerY = 300;

    private double playerSpeed = 5;

    private double rotorAngle = 0;

    

    // Game Entities

    private ArrayList<Point2D.Double> playerMissiles = new ArrayList<>();

    private ArrayList<Enemy> enemies = new ArrayList<>();

    private ArrayList<Point2D.Double> enemyMissiles = new ArrayList<>();

    private Random rand = new Random();


    public QuadcopterGame4() {

        setPreferredSize(new Dimension(WIDTH, HEIGHT));

        setBackground(Color.BLACK);

        setFocusable(true);

        addKeyListener(this);


        // Initialize 20 enemies

        for (int i = 0; i < 20; i++) {

            enemies.add(new Enemy(rand.nextInt(WIDTH), rand.nextInt(HEIGHT)));

        }


        // Game Loop (approx 60 FPS)

        timer = new Timer(16, this);

        timer.start();


        // Enemy firing timer (every 2 seconds)

        Timer fireTimer = new Timer(2000, e -> {

            if (!enemies.isEmpty() && !gameOver) {

                Enemy shooter = enemies.get(rand.nextInt(enemies.size()));

                enemyMissiles.add(new Point2D.Double(shooter.x, shooter.y));

            }

        });

        fireTimer.start();

    }


    @Override

    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);


        if (gameOver) {

            g2.setColor(Color.RED);

            g2.setFont(new Font("Arial", Font.BOLD, 50));

            g2.drawString("GAME OVER", WIDTH/2 - 150, HEIGHT/2);

            g2.setFont(new Font("Arial", Font.PLAIN, 20));

            g2.drawString("Final Score: " + score, WIDTH/2 - 60, HEIGHT/2 + 40);

            return;

        }


        // Draw Score

        g2.setColor(Color.WHITE);

        g2.drawString("Score: " + score, 20, 30);


        // Draw Player (Quadcopter)

        drawQuadcopter(g2, playerX, playerY);


        // Draw Player Missiles

        g2.setColor(Color.YELLOW);

        for (Point2D.Double m : playerMissiles) g2.fill(new Ellipse2D.Double(m.x, m.y, 5, 5));


        // Draw Enemies

        g2.setColor(Color.RED);

        for (Enemy e : enemies) g2.fill(new Rectangle2D.Double(e.x, e.y, 20, 20));


        // Draw Enemy Missiles

        g2.setColor(Color.ORANGE);

        for (Point2D.Double m : enemyMissiles) g2.fill(new Ellipse2D.Double(m.x, m.y, 8, 8));

    }


    private void drawQuadcopter(Graphics2D g2, double x, double y) {

        g2.setColor(Color.CYAN);

        rotorAngle += 0.5; // Spin speed


        // Draw 4 Spokes and Rotors

        int[][] offsets = {{-20,-20}, {20,-20}, {-20,20}, {20,20}};

        for (int[] offset : offsets) {

            double rx = x + offset[0];

            double ry = y + offset[1];

            g2.draw(new Line2D.Double(x, y, rx, ry));

            

            // Spinning rotor effect

            AffineTransform old = g2.getTransform();

            g2.translate(rx, ry);

            g2.rotate(rotorAngle);

            g2.draw(new Ellipse2D.Double(-10, -10, 20, 20));

            g2.draw(new Line2D.Double(-10, 0, 10, 0)); // Spoke inside rotor

            g2.setTransform(old);

        }

        g2.fill(new Ellipse2D.Double(x-10, y-10, 20, 20)); // Body

    }


    @Override

    public void actionPerformed(ActionEvent e) {

        if (gameOver) return;


        // Move Player Missiles

        for (int i = 0; i < playerMissiles.size(); i++) {

            playerMissiles.get(i).y -= 10;

            if (playerMissiles.get(i).y < 0) playerMissiles.remove(i);

        }


        // Move Enemy Missiles

        for (int i = 0; i < enemyMissiles.size(); i++) {

            enemyMissiles.get(i).y += 5;

            // Check Collision with Player

            if (enemyMissiles.get(i).distance(playerX, playerY) < 20) gameOver = true;

            if (enemyMissiles.get(i).y > HEIGHT) enemyMissiles.remove(i);

        }


        // Move Enemies and Check Collision

        for (int i = 0; i < enemies.size(); i++) {

            Enemy en = enemies.get(i);

            en.update();


            // Check Player Missile hit Enemy

            for (int j = 0; j < playerMissiles.size(); j++) {

                if (playerMissiles.get(j).distance(en.x, en.y) < 20) {

                    enemies.remove(i);

                    playerMissiles.remove(j);

                    score += 10;

                    break;

                }

            }

        }

        repaint();

    }


    // Controls

    @Override

    public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_W) playerY -= playerSpeed;

        if (key == KeyEvent.VK_S) playerY += playerSpeed;

        if (key == KeyEvent.VK_A) playerX -= playerSpeed;

        if (key == KeyEvent.VK_D) playerX += playerSpeed;

        if (key == KeyEvent.VK_SPACE) playerMissiles.add(new Point2D.Double(playerX, playerY));

    }


    // Inner class for Enemy behavior

    class Enemy {

        double x, y, dx, dy;

        Enemy(double x, double y) {

            this.x = x; this.y = y;

            this.dx = (rand.nextDouble() - 0.5) * 4;

            this.dy = (rand.nextDouble() - 0.5) * 4;

        }

        void update() {

            x += dx; y += dy;

            if (x < 0 || x > WIDTH) dx *= -1;

            if (y < 0 || y > HEIGHT) dy *= -1;

        }

    }


    // Boilers

    @Override public void keyReleased(KeyEvent e) {}

    @Override public void keyTyped(KeyEvent e) {}


    public static void main(String[] args) {

        JFrame frame = new JFrame("Quadcopter Combat");

        QuadcopterGame4 game = new QuadcopterGame4();

        frame.add(game);

        frame.pack();

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setLocationRelativeTo(null);

        frame.setVisible(true);

    }

}

Tidak ada komentar: