길고 길었던 Bubble Bubble 프로젝트가 끝이 났다. 사실 완벽하게 끝난건 아니다
Bubble쪽 List로 받은 내용도 삭제해야 하는데.. 일단 마무리된거만 올릴려고 한다.
필기는 이때까지 한거 다 적어뒀으니 참고 하실분들은 참고 하세요.
BubbleFrame.java
<java />
package bubble.test.ex18;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class BubbleFrame extends JFrame {
private BubbleFrame mContext = this;
private JLabel backgroundMap;
private Enemy enemy;
private Player player;
public BubbleFrame() { // 생성자 만들기
initObject();
initSetting();
initListener(); // listener 추가
setVisible(true);
}
private void initObject() {
backgroundMap = new JLabel(new ImageIcon("image/backgroundMap.png")); // label 안에 이미지 넣음
setContentPane(backgroundMap);
// backgroundMap.setSize(100,100);
// backgroundMap.setLocation(300,300);
// backgroundMap.setSize(1000,600);
// add(backgroundMap);// JFrame에 JLabel이 그려진다.
player = new Player(mContext); // Player함수를 호출하여 BubbleFrame에 추가한다
add(player);
enemy = new Enemy(mContext);
add(enemy);
new BGM();
}
private void initSetting() {
setSize(1000, 640);
setLayout(null);// absolute 레이아웃 (자유롭게 그림을 그릴 수 있다.)
setLocationRelativeTo(null); // JFrame 가운데 배치하기
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // x버튼으로 창을 끌 때 JVM 같이 종료 하기
}
private void initListener() { // this 이친구의 this
addKeyListener(new KeyAdapter() { // 람다식으로 Interface를 가져올시 전부 기능을 정의 해야함 하지만 Adapter를 사용해서 정의가 가능하다
// 키보드 클릭 이벤트 핸들러
@Override
public void keyPressed(KeyEvent e) {
// System.out.println(e.getKeyCode()); // 실행하여 방향키를 입력해본다
// 39 오른쪽
// 37 왼쪽 숫자로 표현하면 알아보기 힘들다 KeyEvent.VK_ 를 활용하여 알기 쉽게 한다
// 40 밑
// 38 위
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (!player.isLeft() && !player.isLeftWallCrash()) {
player.left();
}
break;
case KeyEvent.VK_RIGHT:
if (!player.isRight() && !player.isRightWallCrash()) {
player.right();
}
break;
case KeyEvent.VK_UP:
if (!player.isUp() && !player.isDown()) {
player.up();
}
break;
case KeyEvent.VK_SPACE: //버블의 주체는 player인데 bubbleFrame에서 지금 new를 하고 있다.
// System.out.println("발싸!");
// Bubble bubble = new Bubble(mContext); // this 익명 클래스의 정보
// add(bubble);
player.attack();
break;
}
}
// case KeyEvent.VK_DOWN: 떨어지거나 할때 사용하는데 따로 down키를 눌릴 일이 없다
// player.down();
// break;
// 키보드 해제 이벤트 핸들러
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
player.setLeft(false);
break;
case KeyEvent.VK_RIGHT:
player.setRight(false);
break;
}
}
});
}
public static void main(String[] args) {
new BubbleFrame();
}
}
Moveable.java
<java />
package bubble.test.ex18;
public interface Moveable {
public abstract void left();
public abstract void right();
public abstract void up();
default public void down() {};
default public void attack() {};
// public이 아닌이유 버블은 공격의 주체가 아니다 -> 공격은 player가 하는것
// 자바 높은 버전부터 나온 문법
// default를 사용하면 인터페이스도 몸체가 있는 메서드를 만들수 있다. (다중 상속이 안되는 것이 많기 때문에)
// 그래서 어댑터 패턴보다는 default를 사용하는것이 좋다 .
}
Player.java
<java />
package bubble.test.ex18;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
// class player -> new 가능한 애들!! 게임에 존재할 수 있음. (추상메서드를 가질 수 없다.)
@Setter
@Getter
public class Player extends JLabel implements Moveable { // player 자체가 label이다
private BubbleFrame mContext; // 못받아 오니BubbleFrame 호출해야한다
private List<Bubble> bubbleList;
// 위치 상태
private int x;
private int y;
// 플레이어의 방향
private PlayerWay playerWay;
// 움직임 상태
private boolean left;
private boolean right;
private boolean up;
private boolean down;
// 벽에 충돌한 상태
private boolean leftWallCrash;
private boolean rightWallCrash;
// 플레이어 속도 상태
private final int SPEED = 4; // 상수처리
private final int JUMP = 2; // up, down
private ImageIcon playerR, playerL;
public Player(BubbleFrame mContext) {
this.mContext = mContext;
initObject(); // 오브젝트 세팅
initSetting();
initBackgroundPlayerService();
}
private void initObject() {
playerR = new ImageIcon("image/playerR.png"); // 이미지 ImageIcon에 사진 추가
playerL = new ImageIcon("image/playerL.png");
bubbleList = new ArrayList<>();
}
private void initSetting() { // 기본 시작 위치
x = 80;
y = 535;
// 최초 상태 -> 움직인다 (좌표가 이동한다)
// 키보드 오른쪽을 누른다 -> 오른쪽으로 간다
left = false;
right = false;
up = false;
down = false;
leftWallCrash = false;
rightWallCrash = false;
playerWay = PlayerWay.RIGHT;
setIcon(playerR);
setSize(50, 50);
setLocation(x, y);
}
private void initBackgroundPlayerService() {// Thread 사용시 Runable 사용해야하지만 BackgroundPlayerService자체가 Runable 상속 받았기
// 때문에 바로 가능
new Thread(new BackgroundPlayerService(this)).start();
}
@Override
public void attack() { // Moveable에서 attack을 호출한다.
new Thread(() -> { // 어택 호출시 쓰레드 실행한다.
Bubble bubble = new Bubble(mContext); // Thread가 시작되면서 bubble이 만들어 지고 왼쪽 아니면 오른쪽으로만 이동하면 된다
mContext.add(bubble);
bubbleList.add(bubble);
if (playerWay == playerWay.LEFT) {
bubble.left();
} else {
bubble.right();
}
}).start();
}
// 이벤트 핸들러
@Override
public void left() {
playerWay = PlayerWay.LEFT;
left = true;
new Thread(() -> { // Thread 생성
while (left) {
x = x - SPEED; // x축 1만큼 - 이동
setIcon(playerL); // 왼쪽으로 갈때는 왼쪽 이미지
setLocation(x, y);
try {
Thread.sleep(10);// 0.01초
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start(); // Thread에는 Runable의 익명 클래스가 필요하다
}
@Override
public void right() {
playerWay = PlayerWay.RIGHT;
right = true;
new Thread(() -> {
while (right) {
setIcon(playerR); // 왼쪽으로 갈때는 오른쪽 이미지
x = x + SPEED; // x축 1만큼 +이동
setLocation(x, y);
try {
Thread.sleep(10);// 0.01초
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start(); // Thread에는 Runable의 익명 클래스가 필요하다
}
// left + up , right + up 가능하다 Thread가 없으면 불가능 함
@Override
public void up() {
System.out.println("짬푸");
up = true;
new Thread(() -> {
for (int i = 0; i < 130 / JUMP; i++) { // JUMP 변경시에도 알아보기 좋다. 나중에 복잡해진다
y = y - JUMP; // y값을 - 하는게 점프
setLocation(x, y);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
up = false;
down();
}).start();
}
@Override
public void down() {
// System.out.println("down");
down = true;
new Thread(() -> {
while (down) { // JUMP 변경시에도 알아보기 좋다. 나중에 복잡해진다
// for문 쓰면 부조건 바닥에 떨어짐 while문 변경 -> 떨어지다가 false로 바뀌면서 멈춤
y = y + JUMP; // y값을 - 하는게 점프
setLocation(x, y);
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
down = false;
}).start();
}
}
PlayerWay.java(Enum)
<java />
package bubble.test.ex18;
public enum PlayerWay {
LEFT,RIGHT;
}
BackgroundPlayerService.java
<java />
package bubble.test.ex18;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;
import javax.imageio.ImageIO;
// 메인 쓰레드 바쁨 - 키보드 이벤트를 처리하기 바쁨.
// Background에서 플레이어의 움직임을 관찰하는 Class
public class BackgroundPlayerService implements Runnable {
private BufferedImage image; // image를 Buffered로 읽어야 test 가능
private Player player;
private List<Bubble> bubbleList; // 전체 리스트를 가져와서 계산을 한다.
// 플레이어, 버블
public BackgroundPlayerService(Player player) {
this.player = player;
this.bubbleList = player.getBubbleList();
try {
image = ImageIO.read(new File("image/backgroundMapService.png"));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Override
public void run() {
while (true) {
// 1. 버블 충돌 체크
for (int i = 0; i < bubbleList.size(); i++) {
Bubble bubble = bubbleList.get(i);
if (bubble.getState() == 1) {
if ((Math.abs(player.getX() - bubble.getX()) < 10) && (Math.abs(player.getY() - bubble.getY()) > 0
&& Math.abs(player.getY() - bubble.getY()) < 50)) {
System.out.println("적군 사살 완료");
bubble.clearBubbled();
break;
}
}
}
// 2. 벽 충돌 체크
// 색상 확인 -> 부딪치는곳 영역 잡기 위해서 사용중
Color leftColor = new Color(image.getRGB(player.getX() - 10, player.getY() + 25));
Color rightColor = new Color(image.getRGB(player.getX() + 50 + 15, player.getY() + 25));
// -2가 나온다는 뜻은 바닥에 색깔이 없이 흰색
int bottomColor = image.getRGB(player.getX() + 10, player.getY() + 50 + 5) // 가장 왼쪽 하단 = -1
+ image.getRGB(player.getX() + 40, player.getY() + 50 + 5); // 가장 오른쪽 하단 = -1
// System.out.println("bottomColor" + bottomColor);
// System.out.println("leftColor : " + leftColor);
// System.out.println("rightColor : " + rightColor);
// Color color = new Color(image.getRGB(player.getX(), player.getY()));
// System.out.println("색상 : " + color);
// 바닥 충돌 확인
if (bottomColor != -2) {
// System.out.println("바닥에 충돌함");
player.setDown(false);
} else { // -2 일때 실행됨 => 내 바닥 색깔이 하얀색이라는 것
if (!player.isUp() && !player.isDown()) { // player가 isUP + is Down 상태가 아닐때
player.down();
}
}
// 외벽 충돌 확인
if (leftColor.getRed() == 255 && leftColor.getGreen() == 0 && leftColor.getBlue() == 0) { // RGB 빨간색
// System.out.println("왼쪽 벽에 충돌함");
player.setLeftWallCrash(true);
player.setLeft(false);
} else if (rightColor.getRed() == 255 && rightColor.getGreen() == 0 && rightColor.getBlue() == 0) {
// System.out.println("오른쪽 벽에 충돌함");
player.setRightWallCrash(true);
player.setRight(false);// 이것만 하면 되는줄 알았지만 계속 누르게 되면 뜷고 들어가게 된다.
} else {
player.setLeftWallCrash(false);
player.setRightWallCrash(false);
}
try { // sleep 없으면 너무 빨리 실행된다.
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Bubble.Java
<java />
package bubble.test.ex18;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Bubble extends JLabel implements Moveable {
// 의존성 콤포지션 -> bubble은 player에 의존적이다
private BubbleFrame mContext;
private Player player;
private Enemy enemy; // 적군이 여러명이면 Enemy 컬렉션으로 만들면 된다.
private BackgroundbubblerService backgroundbubblerService; // bubble이 만들어질때마다 new
// 위치 상태
private int x;
private int y;
// 움직임 상태
private boolean left;
private boolean right;
private boolean up;
// private boolean down; 방울은 밑으로 못간다
// 적군을 맞춘 상태
private int state; // 0(물방울), 1(적을 가둔 물방울)
private ImageIcon bubble; // 물방울
private ImageIcon bubbled; // 적을 가둔 물방울
private ImageIcon bomb; // 물방울이 터진 상태
public Bubble(BubbleFrame mContext) { // player를 넣어줘야 방울의 위치를 잡아 줄수 있다
this.mContext = mContext; // 모든정보를 가진 Context가 있으니까 플레이어 정보를 들고 올수 있다.
this.player = mContext.getPlayer();
this.enemy = mContext.getEnemy();
initObject();
initSetting();
// initThread();
}
private void initSetting() {
left = false;
right = false;
up = false;
x = player.getX();
y = player.getY();
// bubble의 방향이 결정되어야 한다.
setIcon(bubble);
setSize(50, 50);
state = 0;
}
private void initObject() {
bubbled = new ImageIcon("image/bubbled.png");
bubble = new ImageIcon("image/bubble.png");
bomb = new ImageIcon("image/bomb.png");
backgroundbubblerService = new BackgroundbubblerService(this);
}
// private void initThread() {
// // 버블은 쓰레드가 하나만 필요하다.
// new Thread(()->{
// if(player.getPlayerWay() == PlayerWay.LEFT) {
// left();
// } else {
// right();
// }
// }).start();
// }
@Override
public void left() {
left = true;
for (int i = 0; i < 400; i++) {
x--;
setLocation(x, y);
if (backgroundbubblerService.leftWall()) {
left = false;
break;
}
// 40과 60의 범위 절대값
if ((Math.abs(x - enemy.getX()) < 10)
&& (Math.abs(y - enemy.getY()) > 0 && Math.abs(y - enemy.getY()) < 50)) {
System.out.println("물방울이 적군과 충돌하였습니다.");
if (enemy.getState() == 0) {
attack();
break;
}
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
up();
}
@Override
public void right() {
right = true;
for (int i = 0; i < 400; i++) {
x++;
setLocation(x, y);
if (backgroundbubblerService.rightWall()) {
right = false;
break;
}
// 아군과 적군의 거리가 10의 차이가 나면
if ((Math.abs(x - enemy.getX()) < 10)
&& (Math.abs(y - enemy.getY()) > 0 && Math.abs(y - enemy.getY()) < 50)) {
System.out.println("물방울이 적군과 충돌하였습니다.");
if (enemy.getState() == 0) {
attack();
break;
}
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
up();
}
@Override
public void up() {
up = true;
while (up) {
y--;
setLocation(x, y);
if (backgroundbubblerService.topWall()) {
up = false;
break; // break 필요는 없지만 이단계에서 바로 체크가 되어서 2번 안돌아도 되니까 break 사용함
}
try {
if (state == 0) { // 기본 물방울
Thread.sleep(1);
} else { // 적은 가둔 물방울
Thread.sleep(10);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (state == 0)
clearBubble(); // 천장에 버블이 도착하고 나서 3초 후에 메모리에서 소멸
}
@Override
public void attack() {
state = 1;
enemy.setState(1);
setIcon(bubbled);
mContext.remove(enemy); // 메모리에서 사라지게 한다. (가비지 컬렉션 -> 즉시 발동하지 않음)
mContext.repaint(); // 깔끔하게 안사라져서 리페인트 작업 해야한다. 화면갱신
}
// 행위 -> clear (동사) -> bubble (목적어)
private void clearBubble() {// 다른곳에서 호출할일이 없기 때문에 private 사용
try {
Thread.sleep(3000);
setIcon(bomb);
Thread.sleep(500);
mContext.remove(this); // bubbleFrame 의 bubble이 메모리에서 소멸된다.
mContext.repaint(); // bubbleFrame 의 전체를 다시 그린다.(메모리에서 없는 건 안그린다.)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void clearBubbled() {
new Thread(()->{
System.out.println("clearBubbled");
try {
up = false;
setIcon(bomb);
Thread.sleep(1000);
mContext.remove(this);
mContext.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
BackgroundbubblerService.java
<java />
package bubble.test.ex18;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class BackgroundbubblerService {// bubble이 만들어질때마다 유지 되어야한다. -> 버블은 언제 만들어지나?(만들어지는 시점) -> VK_SPACE에서
private BufferedImage image;
private Bubble bubble;
public BackgroundbubblerService(Bubble bubble) {
this.bubble = bubble;
try {
image = ImageIO.read(new File("image/backgroundMapService.png"));
} catch (Exception e) {
}
}
public boolean leftWall() {
Color leftColor = new Color(image.getRGB(bubble.getX() - 10, bubble.getY() + 25));
// 외벽 충돌 확인
if (leftColor.getRed() == 255 && leftColor.getGreen() == 0 && leftColor.getBlue() == 0) {
return true;
}
return false;
}
public boolean rightWall() {
Color rightColor = new Color(image.getRGB(bubble.getX() + 50 + 15, bubble.getY() + 25));
if (rightColor.getRed() == 255 && rightColor.getGreen() == 0 && rightColor.getBlue() == 0) {
return true;
}
return false;
}
public boolean topWall() {
Color topColor = new Color(image.getRGB(bubble.getX()+25, bubble.getY()-10));
if (topColor.getRed() == 255 && topColor.getGreen() == 0 && topColor.getBlue() == 0) {
return true;
}
return false;
}
}
Enemy.Java
<java />
package bubble.test.ex18;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
// class player -> new 가능한 애들!! 게임에 존재할 수 있음. (추상메서드를 가질 수 없다.)
@Getter
@Setter
public class Enemy extends JLabel implements Moveable { // player 자체가 label이다
private BubbleFrame mContext; // 못받아 오니BubbleFrame 호출해야한다
// 위치 상태
private int x;
private int y;
// 적군의의 방향
private EnemyWay enemyWay;
// 움직임 상태
private boolean left;
private boolean right;
private boolean up;
private boolean down;
private int state; // 0(살아있는 상태), 1(물방울에 갇힌 상태)
// 적군의 속도 상태
private final int SPEED = 3; // 상수처리
private final int JUMP = 1; // up, down
private ImageIcon enemyR, enemyL;
public Enemy(BubbleFrame mContext) {
this.mContext = mContext;
initObject(); // 오브젝트 세팅
initSetting();
initBackgroundEnemyService();
right();
}
private void initObject() {
enemyR = new ImageIcon("image/enemyR.png"); // 이미지 ImageIcon에 사진 추가
enemyL = new ImageIcon("image/enemyL.png");
}
private void initSetting() { // 기본 시작 위치
x = 480;
y = 178;
// 최초 상태 -> 움직인다 (좌표가 이동한다)
// 키보드 오른쪽을 누른다 -> 오른쪽으로 간다
left = false;
right = false;
up = false;
down = false;
state = 0;
enemyWay = enemyWay.RIGHT;
setIcon(enemyR);
setSize(50, 50);
setLocation(x, y);
}
private void initBackgroundEnemyService() {// Thread 사용시 Runable 사용해야하지만 BackgroundPlayerService자체가 Runable 상속 받았기
// 때문에 바로 가능
new Thread(new BackgroundEnemyService(this)).start();
}
// 이벤트 핸들러
@Override
public void left() {
enemyWay = EnemyWay.LEFT;
left = true;
new Thread(() -> { // Thread 생성
while (left) {
x = x - SPEED; // x축 1만큼 - 이동
setIcon(enemyL); // 왼쪽으로 갈때는 왼쪽 이미지
setLocation(x, y);
try {
Thread.sleep(10);// 0.01초
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start(); // Thread에는 Runable의 익명 클래스가 필요하다
}
@Override
public void right() {
enemyWay = EnemyWay.RIGHT;
right = true;
new Thread(() -> {
while (right) {
setIcon(enemyR); // 왼쪽으로 갈때는 오른쪽 이미지
x = x + SPEED; // x축 1만큼 +이동
setLocation(x, y);
try {
Thread.sleep(10);// 0.01초
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start(); // Thread에는 Runable의 익명 클래스가 필요하다
}
@Override
public void up() {
up = true;
new Thread(() -> {
for (int i = 0; i < 130 / JUMP; i++) { // JUMP 변경시에도 알아보기 좋다. 나중에 복잡해진다
y = y - JUMP; // y값을 - 하는게 점프
setLocation(x, y);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
up = false;
down();
}).start();
}
@Override
public void down() {
// System.out.println("down");
down = true;
new Thread(() -> {
while (down) { // JUMP 변경시에도 알아보기 좋다. 나중에 복잡해진다
// for문 쓰면 부조건 바닥에 떨어짐 while문 변경 -> 떨어지다가 false로 바뀌면서 멈춤
y = y + JUMP; // y값을 - 하는게 점프
setLocation(x, y);
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
down = false;
}).start();
}
}
EnemyWay.java(Enum)
<java />
package bubble.test.ex18;
public enum EnemyWay {
LEFT,RIGHT;
}
BackgroundEnemyService.java
<java />
package bubble.test.ex18;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;
import javax.imageio.ImageIO;
// 메인 쓰레드 바쁨 - 키보드 이벤트를 처리하기 바쁨.
// Background에서 플레이어의 움직임을 관찰하는 Class
public class BackgroundEnemyService implements Runnable {
private BufferedImage image; // image를 Buffered로 읽어야 test 가능
private Enemy enemy;
// 플레이어, 버블
public BackgroundEnemyService(Enemy enemy) {
this.enemy = enemy;
try {
image = ImageIO.read(new File("image/backgroundMapService.png"));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Override
public void run() {
while (enemy.getState() == 0) {
Color leftColor = new Color(image.getRGB(enemy.getX() - 10, enemy.getY() + 25));
Color rightColor = new Color(image.getRGB(enemy.getX() + 50 + 15, enemy.getY() + 25));
int bottomColor = image.getRGB(enemy.getX() + 10, enemy.getY() + 50 + 5) // 가장 왼쪽 하단 = -1
+ image.getRGB(enemy.getX() + 40, enemy.getY() + 50 + 5); // 가장 오른쪽 하단 = -1
if (bottomColor != -2) {
// System.out.println("바닥에 충돌함");
enemy.setDown(false);
} else { // -2 일때 실행됨 => 내 바닥 색깔이 하얀색이라는 것
if (!enemy.isUp() && !enemy.isDown()) { // player가 isUP + is Down 상태가 아닐때
enemy.down();
}
}
// 외벽 충돌 확인
if (leftColor.getRed() == 255 && leftColor.getGreen() == 0 && leftColor.getBlue() == 0) { // RGB 빨간색
enemy.setLeft(false);
if(!enemy.isRight()) {
enemy.right();
}
} else if (rightColor.getRed() == 255 && rightColor.getGreen() == 0 && rightColor.getBlue() == 0) {
enemy.setRight(false);// 이것만 하면 되는줄 알았지만 계속 누르게 되면 뜷고 들어가게 된다.
if(!enemy.isLeft()) {
enemy.left();
}
}
try { // sleep 없으면 너무 빨리 실행된다.
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
BGM.java
<java />
package bubble.test.ex18;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.UnsupportedAudioFileException;
public class BGM {
public BGM() {
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("sound/bgm.wav"));
Clip clip = AudioSystem.getClip();
clip.open(ais);
// 소리 설정
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
// 볼륨 조정
gainControl.setValue(-30.0f);
clip.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}

힘들었습니다. 난중에 보강해서 다시 올리겠습니다 쓩!
'Java' 카테고리의 다른 글
자바 -의존성 (0) | 2022.10.11 |
---|---|
버블버블 코드 리팩토링 (객체지향) (0) | 2022.10.10 |
bubble - 물방울 메모리에서 소멸시키고 화면 다시 그리기 (0) | 2022.10.10 |
전체 스레드 동작 원리 짚어보기 (0) | 2022.10.07 |
버블이(?)가 달라졌어요 (0) | 2022.10.06 |