JAVA/실습

버블게임 만들기 : 더 알아보기(버블 터뜨리기)

JJJAEOoni 2022. 2. 13. 23:40
반응형

 

 

package site.metacoding.mytest;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

/**
 * 
 * @author 정재원
 * 
 *
 */

// main을 가진 클래스는 해당 프로그램의 컨텍스트(문맥)를 다 알고 있다.
public class BubbleFrame extends JFrame {

	private static final String TAG = "BubbleFrame : ";

	private BubbleFrame context = this;

	private JLabel backgroundMap; // JLabel로 사진 붙이기
	private Player player;

	public Player getPlayer() {
		return player;
	}

	public void setPlayer(Player player) {
		this.player = player;
	}

	public BubbleFrame() {
		initObject();
		initSetting();
		initListener();
		initService();

		setVisible(true); // 내부에 paintComponent() 호출 코드가 있다.
	}

	// 각종 모든 세팅
	private void initSetting() {
		setSize(1000, 640);
		setLayout(null); // JFrame의 기본 JPanel의 레이아웃을 AbsoulteLayout으로 설정
		setLocationRelativeTo(null); // JFrame 화면 가운데 배치
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // x버튼 클릭시 JVM 같이 종료
	}

	// new 하는 곳
	private void initObject() {
		backgroundMap = new JLabel(new ImageIcon("image/backgroundMap.png"));
		setContentPane(backgroundMap); // 백그라운드 화면 설정

		player = new Player(context); // 플레이어 생성
		add(player); // Frame에 플레이어 붙이기
	}

	private void initListener() {
		addKeyListener(new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {

				if (e.getKeyCode() == KeyEvent.VK_LEFT) {
					if (!player.isLeft() && !player.isLeftWallCrash()) {
						player.left();
					}
				} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
					if (!player.isRight() && !player.isRightWallCrash()) {
						player.right();
					}
				} else if (e.getKeyCode() == KeyEvent.VK_UP) {
					if (!player.isUp() && !player.isDown()) {
						player.up();
					}
				} else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
					player.attack();
				}
			}

			@Override
			public void keyReleased(KeyEvent e) {
				// System.out.println(TAG + "키보드 릴리즈");

				if (e.getKeyCode() == KeyEvent.VK_LEFT) {
					// isLeft를 false로
					player.setLeft(false);
				} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
					// isRight를 false로
					player.setRight(false);
				}
			}

		});
	}

	// backgroundMapService 독립적인 스레드
	private void initService() {
		new Thread(new BackgroundMapService(player)).start();

	}

	public static void main(String[] args) {
		new BubbleFrame();
	}

}
package site.metacoding.mytest;

import javax.swing.ImageIcon;
import javax.swing.JLabel;

/**
 * 
 * @author 정재원 플레이어는 좌우이동이 가능하다. 점프가 가능하다. 방울을 발사한다.
 *
 */

public class Player extends JLabel {

	private static final String TAG = "Player : ";

	private BubbleFrame context;

	private static final int SPEED = 4;
	private static final int JUMPSPEED = 2;

	// 위치 상태
	private int x, y;
	private ImageIcon playerR, playerL;

	// 움직임 상태
	private boolean isLeft, isRight, isUp, isDown;

	// 충돌 상태
	private boolean leftWallCrash, rightWallCrash;

	// 방향 상태
	private int direction; // -1 왼쪽 0 상태x 1 오른쪽

	// X
	public int getX() {
		return x;
	}

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

	// Y
	public int getY() {
		return y;
	}

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

	// isLeft
	public boolean isLeft() {
		return isLeft;
	}

	public void setLeft(boolean isLeft) {
		this.isLeft = isLeft;
	}

	// isRight
	public boolean isRight() {
		return isRight;
	}

	public void setRight(boolean isRight) {
		this.isRight = isRight;
	}

	// isUp
	public boolean isUp() {
		return isUp;
	}

	public void setUp(boolean isUp) {
		this.isUp = isUp;
	}

	// isDown
	public boolean isDown() {
		return isDown;
	}

	public void setDown(boolean isDown) {
		this.isDown = isDown;
	}

	// leftWallCrash
	public boolean isLeftWallCrash() {
		return leftWallCrash;
	}

	public void setLeftWallCrash(boolean leftWallCrash) {
		this.leftWallCrash = leftWallCrash;
	}

	// rightWallCrash
	public boolean isRightWallCrash() {
		return rightWallCrash;
	}

	public void setRightWallCrash(boolean rightWallCrash) {
		this.rightWallCrash = rightWallCrash;
	}

	// direction
	public int getDirection() {
		return direction;
	}

	public void setDirection(int direction) {
		this.direction = direction;
	}

	// 생성자
	public Player(BubbleFrame context) {
		this.context = context;

		initObject();
		initSetting();
	}

	private void initSetting() {
		// 플레이어 좌표 설정
		x = 90;
		y = 535;

		// default 사진 설정
		setIcon(playerR);
		setSize(50, 50);

		// 플레이어 그림 그리기 paintComponent 호출
		setLocation(x, y);

		isLeft = false;
		isRight = false;
		isUp = false;
		isDown = false;

		leftWallCrash = false;
		rightWallCrash = false;

		direction = 1;
	}

	private void initObject() {
		playerR = new ImageIcon("image/playerR.png");
		playerL = new ImageIcon("image/playerL.png");
	}

	public void left() {
		System.out.println(TAG + "왼쪽");

		isLeft = true;
		setRightWallCrash(false);
		direction = -1;
		setIcon(playerL);

		new Thread(() -> {
			while (isLeft) {
				x = x - SPEED;
				setLocation(x, y);

				try {
					Thread.sleep(10);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
	}

	public void right() {
		System.out.println(TAG + "오른쪽");

		isRight = true;
		setLeftWallCrash(false);
		direction = 1;
		setIcon(playerR);

		new Thread(() -> {
			while (isRight) {
				x = x + SPEED;
				setLocation(x, y);

				try {
					Thread.sleep(10);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
	}

	public void up() {
		System.out.println(TAG + "위쪽");

		isUp = true;

		new Thread(() -> {
			// up
			for (int i = 0; i < 130 / JUMPSPEED; i++) {
				y = y - JUMPSPEED;
				setLocation(x, y);

				try {
					Thread.sleep(5);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			isUp = false;
			down();

		}).start();
	}

	public void down() {
		System.out.println(TAG + "아래쪽");
		isDown = true;

		new Thread(() -> {
			// down
			while (isDown) {
				y = y + JUMPSPEED;
				setLocation(x, y);

				try {
					Thread.sleep(3);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		}).start();
	}

	public void attack() {
		System.out.println(TAG + "공격!");
		Bubble bubble = new Bubble(context); // JLabel
		context.add(bubble);

		new Thread(new BackgroundBubbleService(bubble)).start();
	}
}
package site.metacoding.mytest;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

// 백그라운드 서비스 (독립적인 스레드로 돌려야 한다)
public class BackgroundMapService implements Runnable {

	private static final String TAG = "BackgroundMapService : ";

	// 컴포지션
	private Player player;
	private BufferedImage image;

	// 컴포지션을 위한 기술 -> 의존성 주입 (생성자를 통해서 주입) = DI (Dependency Injection)
	public BackgroundMapService(Player player) {
		this.player = player;

		try {
			image = ImageIO.read(new File("image/backgroundMapService.png"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		// 멈추지 않고 while을 돌며 색상 확인
		while (true) {
			try {
				Color leftColor = new Color(image.getRGB(player.getX() - 10, player.getY() + 25));
				Color rightColor = new Color(image.getRGB(player.getX() + 50 + 10, player.getY() + 25));

				// System.out.println(TAG + "leftColor : " + leftColor);
				// System.out.println(TAG + "rightColor : " + rightColor);

				int bottomColor = image.getRGB(player.getX() + 10, player.getY() + 50 + 5) // -1
						+ image.getRGB(player.getX() + 50 - 10, player.getY() + 50 + 5); // -1

				// System.out.println(TAG + bottomColor);

				if (bottomColor != -2) { // 바닥에 장애물이 있다!
					// System.out.println(TAG + "바닥에 밟히는게 있네");
					player.setDown(false); // 그만 떨어져
				} else { // 바닥이 흰색
					if (!player.isDown() && !player.isUp()) {
						// System.out.println(TAG + "바닥에 아무것도 없어!!");
						player.down();
					}
				}

				if (leftColor.getRed() == 255 && leftColor.getGreen() == 0 && leftColor.getBlue() == 0) { // 왼쪽벽이 빨간색이면
					System.out.println(TAG + "왼쪽 벽에 부딪혔다!");
					player.setLeftWallCrash(true);
					player.setLeft(false);
				} else if (rightColor.getRed() == 255 && rightColor.getGreen() == 0 && rightColor.getBlue() == 0) {
					System.out.println(TAG + "오른쪽 벽에 부딪혔다!");
					player.setRightWallCrash(true);
					player.setRight(false);
				}

				Thread.sleep(10);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}
package site.metacoding.mytest;

import javax.swing.ImageIcon;
import javax.swing.JLabel;

public class Bubble extends JLabel {

	private static final String TAG = "Bubble : ";
	private static final int BUBBLESPEED = 1;

	private BubbleFrame context;
	private Player player;

	private int x, y;

	private ImageIcon bubble, bomb;

	private boolean isLeft, isRight, isUp, topWallCrash, leftWallCrash, rightWallCrash;

	// isLeft
	public boolean isLeft() {
		return isLeft;
	}

	public void setLeft(boolean isLeft) {
		this.isLeft = isLeft;
	}

	// isRight
	public boolean isRight() {
		return isRight;
	}

	public void setRight(boolean isRight) {
		this.isRight = isRight;
	}

	// isUp
	public boolean isUp() {
		return isUp;
	}

	public void setUp(boolean isUp) {
		this.isUp = isUp;
	}

	// topWallCrash
	public boolean isTopWallCrash() {
		return topWallCrash;
	}

	public void setTopWallCrash(boolean topWallCrash) {
		this.topWallCrash = topWallCrash;
	}

	// leftWallCrash
	public boolean isLeftWallCrash() {
		return leftWallCrash;
	}

	public void setLeftWallCrash(boolean leftWallCrash) {
		this.leftWallCrash = leftWallCrash;
	}

	// rightWallCrash
	public boolean isRightWallCrash() {
		return rightWallCrash;
	}

	public void setRightWallCrash(boolean rightWallCrash) {
		this.rightWallCrash = rightWallCrash;
	}

	// bubble은 player의 위치에 의존해야한다.
	// player에만 의존하면 적군을 만들 때 문제가 발생함
	// 따라서 context에 의존!
	public Bubble(BubbleFrame context) {
		this.context = context;
		this.player = context.getPlayer();

		isLeft = false;
		isRight = false;
		isUp = false;
		topWallCrash = false;
		leftWallCrash = false;
		rightWallCrash = false;

		initObject();
		initSetting();

		// 방향체크
		if (player.getDirection() == -1) {
			left();
		} else if (player.getDirection() == 1) {
			right();
		}
	}

	private void initObject() {
		bubble = new ImageIcon("image/bubble.png");
		bomb = new ImageIcon("image/bomb.png");
	}

	private void initSetting() {
		x = player.getX();
		y = player.getY();

		setIcon(bubble);
		setSize(50, 50);
		setLocation(x, y);
	}

	public void left() {
		isLeft = true;

		new Thread(() -> {
			try {
				for (int i = 0; i < 400; i++) {
					x = x - BUBBLESPEED;
					setLocation(x, y);
					Thread.sleep(1);

					if (leftWallCrash == true) {
						up();
						break;
					} else if (i == 399) {
						up();
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}).start();

	}

	public void right() {
		new Thread(() -> {
			try {
				for (int i = 0; i < 400; i++) {
					x = x + BUBBLESPEED;
					setLocation(x, y);
					Thread.sleep(1);

					if (rightWallCrash == true) {
						up();
						break;
					} else if (i == 399) {
						up();
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}).start();
	}

	public void up() {
		isUp = true;

		try {
			while (isUp) {
				y = y - BUBBLESPEED;
				setLocation(x, y);
				Thread.sleep(1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void pop() {
		// 천장에 붙고 4초뒤에 사진변경, repaint
		// setTopWallCrash가 트루면

		new Thread(() -> {

			try {
				Thread.sleep(4000);

				if (topWallCrash == true) {
					setIcon(bomb);
					setLocation(x, y);

					Thread.sleep(1000);
					context.remove(this);
					context.repaint();
				}

			} catch (Exception e) {
				e.printStackTrace();
			}

		}).start();

	}
}
package site.metacoding.mytest;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

// 백그라운드 서비스 (독립적인 스레드로 돌려야 한다)
public class BackgroundBubbleService implements Runnable {

	private static final String TAG = "BackgroundBubbleService : ";

	private Bubble bubble;
	private BufferedImage image;

	public BackgroundBubbleService(Bubble bubble) {
		this.bubble = bubble;

		try {
			image = ImageIO.read(new File("image/backgroundMapService.png"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		// 멈추지 않고 while을 돌며 색상 확인
		while (true) {
			try {

				Color leftColor = new Color(image.getRGB(bubble.getX() - 10, bubble.getY() + 25));
				Color rightColor = new Color(image.getRGB(bubble.getX() + 50 + 10, bubble.getY() + 25));

				int topColor = image.getRGB(bubble.getX() + 25, bubble.getY() - 5);

				// System.out.println(TAG + topColor);

				if (topColor == -65536) { // 버블이 천장에 닿았어!
					// System.out.println(TAG + "머리 부딪혔어");
					bubble.setUp(false); // 그만 올라가
					bubble.setTopWallCrash(true);
					bubble.pop();
				}

				if (leftColor.getRed() == 255 && leftColor.getGreen() == 0 && leftColor.getBlue() == 0) { // 왼쪽벽이 빨간색이면
					// System.out.println(TAG + "왼쪽 벽에 부딪혔다!");
					bubble.setLeftWallCrash(true);
					bubble.setLeft(false);
				} else if (rightColor.getRed() == 255 && rightColor.getGreen() == 0 && rightColor.getBlue() == 0) {
					// System.out.println(TAG + "오른쪽 벽에 부딪혔다!");
					bubble.setRightWallCrash(true);
					bubble.setRight(false);
				}

				Thread.sleep(10);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
반응형