import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Game1 extends JPanel implements KeyListener {
    private Player player;
    private Monster monster;
    private Portal portal;
    private Random random = new Random();
    private JButton attackButton;
    private JButton skillButton;
    private int playerHP = 100;
    private int monsterHP = 100;
    private int portalCount = 0; // 포탈을 통과한 횟수
    private boolean isBoss = false; // 보스 몬스터 등장 여부
    private int skillCount = 3; // 스킬 사용 가능 횟수
    private List<Item> items; // 아이템 리스트
    private JLabel storyLabel; // 스토리를 표시할 레이블

    public Game1() {
        // 플레이어 초기화
        ImageIcon playerIcon = new ImageIcon("/Users/ansejun/Desktop/player.jpg");
        Image playerImage = playerIcon.getImage().getScaledInstance(50, 50, Image.SCALE_SMOOTH);
        player = new Player(5, 500, playerImage);

        // 몬스터 초기화
        ImageIcon monsterIcon = new ImageIcon("/Users/ansejun/Desktop/monster.jpg");
        Image monsterImage = monsterIcon.getImage().getScaledInstance(50, 50, Image.SCALE_SMOOTH);
        int monsterX = random.nextInt(750);  // 0부터 750 사이의 랜덤한 x좌표 생성
        int monsterY = random.nextInt(550);  // 0부터 550 사이의 랜덤한 y좌표 생성
        monster = new Monster(monsterX, monsterY, monsterImage);

        // 포탈 초기화
        ImageIcon portalIcon = new ImageIcon("/Users/ansejun/Desktop/potal.jpg");
        Image portalImage = portalIcon.getImage().getScaledInstance(50, 50, Image.SCALE_SMOOTH);
        int portalX = random.nextInt(750);
        int portalY = random.nextInt(550);
        portal = new Portal(portalX, portalY, portalImage);

        // 아이템 초기화
        items = new ArrayList<>();
        generateItems();

        // 키 리스너 등록
        setFocusable(true);
        requestFocusInWindow();
        addKeyListener(this);

        // 스토리 레이블 초기화
        storyLabel = new JLabel("용사가 마왕을 물리치기 위해 던전에 들어왔습니다.");
        storyLabel.setFont(new Font("Arial", Font.BOLD, 16));
        storyLabel.setForeground(Color.WHITE);
        storyLabel.setHorizontalAlignment(SwingConstants.CENTER);
        add(storyLabel);
        storyLabel.setBounds(200, 250, 400, 50);

        // 3초 후에 스토리 레이블을 숨기는 타이머 추가
        Timer timer = new Timer(3000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                storyLabel.setVisible(false);
            }
        });
        timer.setRepeats(false); // 한 번만 실행되도록 설정
        timer.start();

        // 공격 버튼 초기화
        attackButton = new JButton("Attack");
        attackButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                attack(false);
            }
        });

        // 스킬 버튼 초기화
        skillButton = new JButton("Skill (" + skillCount + ")");
        skillButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (skillCount > 0) {
                    attack(true);
                    skillCount--;
                    updateSkillButton();
                }
            }
        });

        // 버튼을 보이지 않게 설정
        attackButton.setVisible(false);
        skillButton.setVisible(false);

        // 버튼을 패널에 추가
        setLayout(null);
        attackButton.setBounds(350, 500, 100, 30);
        skillButton.setBounds(460, 500, 100, 30);
        add(attackButton);
        add(skillButton);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 배경 이미지 그리기
        Image backgroundImage;
        if (isBoss) {
            backgroundImage = new ImageIcon("/Users/ansejun/Desktop/boss_bg.jpg").getImage();
        } else {
            backgroundImage = new ImageIcon("/Users/ansejun/Desktop/background.jpg").getImage();
        }
        g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);

        // 플레이어 그리기
        player.draw(g);

        // 몬스터 그리기 (alive 상태 확인)
        if (monster.isAlive()) {
            monster.draw(g);
        }

        // 보스가 아니면 포탈 그리기
        if (!isBoss) {
            portal.draw(g);
        }

        // 아이템 그리기
        for (Item item : items) {
            item.draw(g);
        }

        // HP 출력
        g.setColor(Color.RED);
        g.drawString("Player HP: " + playerHP, 10, 20);
        g.drawString("Monster HP: " + monsterHP, 10, 40);

        // 플레이어와 몬스터가 만나면 공격 버튼 및 스킬 버튼 표시
        if (player.intersects(monster) && monster.isAlive()) {
            attackButton.setVisible(true);
            skillButton.setVisible(true);
        } else {
            attackButton.setVisible(false);
            skillButton.setVisible(false);
        }

        // 몬스터가 죽었고, 플레이어가 포탈에 접근했을 때 새로운 맵으로 이동
        if (!monster.isAlive() && player.intersects(portal) && !isBoss) {
            nextMap();
        }

        // 플레이어가 아이템을 획득했는지 확인
        for (int i = 0; i < items.size(); i++) {
            if (player.intersects(items.get(i))) {
                items.get(i).applyEffect();
                items.remove(i);
                break;
            }
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        int dx = 0, dy = 0;
        // 플레이어 이동 처리
        switch (keyCode) {
            case KeyEvent.VK_UP:
                dy = -5;
                break;
            case KeyEvent.VK_DOWN:
                dy = 5;
                break;
            case KeyEvent.VK_LEFT:
                dx = -5;
                break;
            case KeyEvent.VK_RIGHT:
                dx = 5;
                break;
        }
        if (player.canMove(dx, dy)) {
            player.move(dx, dy);
            repaint();
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyReleased(KeyEvent e) {}

    // 플레이어의 공격 메서드
    private void attack(boolean isSkill) {
        int damage;
        if (isSkill) {
            // 스킬 사용 시 데미지를 2배로 적용
            damage = (random.nextInt(10) + 1) * 2; // 2배의 랜덤한 피해
        } else {
            // 일반 공격 시 데미지
            damage = random.nextInt(9) + 1; // 1부터 10까지의 랜덤한 피해
        }
        monsterHP -= damage;
        System.out.println("플레이어가 공격했습니다! Monster HP: " + monsterHP);

        // 몬스터가 플레이어에게 반격하고 플레이어의 HP를 감소시킴
        damage = random.nextInt(2) + 1; // 1부터 3까지의 랜덤한 피해
        playerHP -= damage;
        System.out.println("몬스터가 반격했습니다! Player HP: " + playerHP);

        // 플레이어 또는 몬스터의 HP가 0이하인 경우 처리
        if (playerHP <= 0) {
            System.out.println("플레이어 패배! Game over.");
            // 게임 오버 로직 추가 가능
        } else if (monsterHP <= 0) {
            System.out.println("몬스터가 죽었습니다! 플레이어 승리!");
            monster.setAlive(false); // 몬스터를 죽음 상태로 설정
        }

        repaint();
    }

    // 새로운 맵으로 이동하는 메서드
    private void nextMap() {
        System.out.println("이동 중! 맵을 변경합니다....");
        portalCount++;

        player.x = 5; // 플레이어 초기 위치로 이동
        player.y = 500;

        if (portalCount == 3) {
            // 세 번째 포탈을 통과하면 보스 몬스터 등장
            ImageIcon bossIcon = new ImageIcon("/Users/ansejun/Desktop/boss.png");
            Image bossImage = bossIcon.getImage().getScaledInstance(50, 50, Image.SCALE_SMOOTH);
            int bossX = random.nextInt(750);
            int bossY = random.nextInt(550);
            monster = new BossMonster(bossX, bossY, bossImage);
            monsterHP = 200; // 보스 몬스터의 HP는 200으로 설정
            isBoss = true;
        } else {
            // 새로운 몬스터 초기화
            int monsterX = random.nextInt(750);
            int monsterY = random.nextInt(550);
            monster = new Monster(monsterX, monsterY, monster.image);
            monsterHP = 100;
            isBoss = false;
        }

        // 새로운 포탈 초기화
        if (!isBoss) {
            int portalX = random.nextInt(750);
            int portalY = random.nextInt(550);
            portal = new Portal(portalX, portalY, portal.image);
        }

        // 새로운 아이템 생성
        generateItems();

        repaint();
    }

    private void generateItems() {
        items.clear();
        int itemCount = random.nextInt(1) + 1; // 1 ~ 2개의 아이템 생성
        for (int i = 0; i < itemCount; i++) {
            int itemX = random.nextInt(750);
            int itemY = random.nextInt(550);
            ImageIcon itemIcon = new ImageIcon("/Users/ansejun/Desktop/box.png");
            Image itemImage = itemIcon.getImage().getScaledInstance(30, 30, Image.SCALE_SMOOTH);
            items.add(new Item(itemX, itemY, itemImage));
        }
    }

    // 스킬 버튼 텍스트 갱신 메서드
    private void updateSkillButton() {
        skillButton.setText("Skill (" + skillCount + ")");
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Dungeon Game");
        Game1 game = new Game1();
        frame.add(game);
        frame.setSize(800, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    // 내부 클래스 Player 정의
    class Player {
        private int x, y; // 플레이어의 좌표
        private Image image; // 플레이어 이미지

        public Player(int x, int y, Image image
                ) {
            this.x = x;
            this.y = y;
            this.image = image;
        }

        public void draw(Graphics g) {
            g.drawImage(image, x, y, null);
        }

        public void move(int dx, int dy) {
            x += dx;
            y += dy;
        }

        // 플레이어와 몬스터가 만나는지 확인하는 메서드
        public boolean intersects(Monster monster) {
            Rectangle playerRect = new Rectangle(x, y, 50, 50);
            Rectangle monsterRect = new Rectangle(monster.x, monster.y, 50, 50);
            return playerRect.intersects(monsterRect);
        }

        // 플레이어와 포탈이 만나는지 확인하는 메서드
        public boolean intersects(Portal portal) {
            Rectangle playerRect = new Rectangle(x, y, 50, 50);
            Rectangle portalRect = new Rectangle(portal.x, portal.y, 50, 50);
            return playerRect.intersects(portalRect);
        }

        // 플레이어와 아이템이 만나는지 확인하는 메서드
        public boolean intersects(Item item) {
            Rectangle playerRect = new Rectangle(x, y, 50, 50);
            Rectangle itemRect = new Rectangle(item.x, item.y, 30, 30);
            return playerRect.intersects(itemRect);
        }

        // 이동 가능한지 여부 체크
        public boolean canMove(int dx, int dy) {
            // 이동 가능한지 여부를 판단하는 로직을 추가할 수 있습니다.
            return true;
        }
    }

    // 내부 클래스 Monster 정의
    class Monster {
        protected int x, y; // 몬스터의 좌표
        protected Image image; // 몬스터 이미지
        private boolean alive = true; // 몬스터 생존 상태

        public Monster(int x, int y, Image image) {
            this.x = x;
            this.y = y;
            this.image = image;
        }

        public void draw(Graphics g) {
            g.drawImage(image, x, y, null);
        }

        public boolean isAlive() {
            return alive;
        }

        public void setAlive(boolean alive) {
            this.alive = alive;
        }
    }

    // 보스 몬스터 클래스 정의
    class BossMonster extends Monster {
        public BossMonster(int x, int y, Image image) {
            super(x, y, image);
        }

        @Override
        public void draw(Graphics g) {
            super.draw(g);
        }
    }

    // 내부 클래스 Portal 정의
    class Portal {
        private int x, y; // 포탈의 좌표
        private Image image; // 포탈 이미지

        public Portal(int x, int y, Image image) {
            this.x = x;
            this.y = y;
            this.image = image;
        }

        public void draw(Graphics g) {
            g.drawImage(image, x, y, null);
        }
    }

    // 내부 클래스 Item 정의
    class Item {
        private int x, y; // 아이템의 좌표
        private Image image; // 아이템 이미지

        public Item(int x, int y, Image image) {
            this.x = x;
            this.y = y;
            this.image = image;
        }

        public void draw(Graphics g) {
            g.drawImage(image, x, y, null);
        }

        public void applyEffect() {
            playerHP += 10; 
            skillCount++; // 스킬 횟수 증가
            updateSkillButton(); // 스킬 버튼 텍스트 갱신
            System.out.println("Item acquired! Player HP: " + playerHP + ", Skill count: " + skillCount);
        }
    }
}

 

background.jpg
0.02MB
boss_bg.jpg
0.04MB
boss.png
0.06MB
box.png
0.13MB
monster.jpg
0.08MB
player.jpg
0.13MB
pngtree-yellow-treasure-chest-decoration-illustration-image_1389898.jpg
0.01MB
potal.jpg
0.04MB

 

각 게임에 사용된 자료들이다. 해당 파일을 다운로드 후 코드에서 파일의 경로를 수정해주어야 한다.