Sabtu, 02 Mei 2026

JAVA - Quadcopter Game 2

 




/*

 * 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 quadcoptergame;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

import java.util.ArrayList;

import java.util.HashSet;

import java.util.Set;


public class QuadcopterGame extends JPanel implements ActionListener {

    // Positioning and Physics

    private double x = 300, y = 300;

    private double angle = 0;

    private final double speed = 4.0;

    private final double rotationSpeed = 0.15;

    

    // Missile Management

    private class Missile {

        double mx, my;

        Missile(double x, double y) { this.mx = x; this.my = y; }

        void update() { my -= 10; } // Move upward

    }

    private ArrayList<Missile> missiles = new ArrayList<>();

    

    // Key Handling

    private final Set<Integer> activeKeys = new HashSet<>();

    private Timer timer;


    public QuadcopterGame() {

        setFocusable(true);

        // Standard Timer for 60 FPS (approx 16ms delay)

        timer = new Timer(16, this);

        timer.start();


        addKeyListener(new KeyAdapter() {

            @Override

            public void keyPressed(KeyEvent e) { activeKeys.add(e.getKeyCode()); }

            @Override

            public void keyReleased(KeyEvent e) { activeKeys.remove(e.getKeyCode()); }

        });

    }


    private void updateLogic() {

        if (activeKeys.contains(KeyEvent.VK_W)) y -= speed;

        if (activeKeys.contains(KeyEvent.VK_S)) y += speed;

        if (activeKeys.contains(KeyEvent.VK_A)) x -= speed;

        if (activeKeys.contains(KeyEvent.VK_D)) x += speed;

        

        if (activeKeys.contains(KeyEvent.VK_SPACE)) {

            missiles.add(new Missile(x + 20, y));

            activeKeys.remove(KeyEvent.VK_SPACE); // Fire once per press

        }


        // Update spokes rotation and missiles

        angle += rotationSpeed;

        missiles.forEach(Missile::update);

        missiles.removeIf(m -> m.my < 0); // Clean up off-screen missiles

    }


    @Override

    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

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


        // Draw Missiles

        g2d.setColor(Color.RED);

        for (Missile m : missiles) g2d.fillRect((int)m.mx, (int)m.my, 5, 15);


        // Draw Quadcopter Body

        g2d.setColor(Color.ORANGE);

        g2d.fillRect((int)x, (int)y, 40, 40);


        // Draw 4 Rotating Spokes

        g2d.setColor(Color.BLACK);

        drawRotor(g2d, x, y);           // Top Left

        drawRotor(g2d, x + 40, y);      // Top Right

        drawRotor(g2d, x, y + 40);      // Bottom Left

        drawRotor(g2d, x + 40, y + 40); // Bottom Right

    }


    private void drawRotor(Graphics2D g2d, double rx, double ry) {

        AffineTransform old = g2d.getTransform();

        g2d.translate(rx, ry);

        g2d.rotate(angle);

        g2d.draw(new Line2D.Double(-15, 0, 15, 0));

        g2d.draw(new Line2D.Double(0, -15, 0, 15));

        g2d.drawOval(-15, -15, 30, 30);

        g2d.setTransform(old);

    }


    @Override

    public void actionPerformed(ActionEvent e) {

        updateLogic();

        repaint();

    }


    public static void main(String[] args) {

        JFrame frame = new JFrame("Java Quadcopter Sim");

        frame.add(new QuadcopterGame());

        frame.setSize(800, 600);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setLocationRelativeTo(null);

        frame.setVisible(true);

    }

}

Tidak ada komentar: