[JAVA] SWING을 이용한 간단한 던전게임 만들기
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
각 게임에 사용된 자료들이다. 해당 파일을 다운로드 후 코드에서 파일의 경로를 수정해주어야 한다.