본문 바로가기

Coding_Study/Java_Code_Memo

JButton으로 슈팅게임 3- 2 (충돌) 총알

몬스터와 총알의 위치가 겹칠 때,

2020/12/12 - [Java_Study/Code_Memo] - JButton으로 슈팅게임 3-1 (충돌) 몬스터 죽이기

 

JButton으로 슈팅게임 3-1 (충돌) 몬스터 죽이기

충돌을 하기에 앞서 각 버튼의 위치를 받아서 비교하는 알고리즘을 공부해야 했어요. 처음에는 하나하나 계산을 해서,  총알의 크기가 20,20이니까 19만큼의 여유를 양쪽으로 더 줘야겠다 해서 

mintpearl-story.tistory.com

지난 번에는 몬스터를 지우는 것 까지 했었습니다.

이 번에는 몬스터와 충돌한 총알도 함께 사라지도록 만들겠습니다.

또 한 번, 전체적으로 코드를 수정해야 했어요.

 

 

전제 : 몬스터는 총알, 주인공 모두와 충돌하는 이벤트가 있으므로, 몬스터를 기준으로 충돌 이벤트를 짜준다.

          똑같은 공식을 몬스터, 총알 모두에게 넣어서 각각 없애주니 자꾸 exception이 떠서

          (이유 불명, 아직 배움이 부족해서, 혹시 이유를 아신다면 조언 부탁드립니다...)

          몬스터에서 충돌을 인지하면 본인 JButton을 없애는 동시에 boolean타입으로 '그' 총알을 없애라고 신호를 보낸다.

          총알 class에서는 해당 신호가 오면 while문을 break한다.

 

오늘 할 일 : 메인(Play_Phase1)에 몬스터도 Map에 담아주는 작업을 한다.

                  각 몬스터 class에서 신호를 보내줄 작업을 한다.

                  총알 if문으로 신호를 받게 설정한다.

 

 

 

- 메인 (Play_Phase1) 작업

  사실 Map에 담을 필요는 없어보이지만, 처음 설계할 때 총알에서도 몬스터를 다 긁어와서 비교하는 것으로 생각했기 때문에

  몬스터도 Map에 다 넣음. 또 for문을 여러번 돌리기 싫어서 잔머리로, 한 map에 key값 범위를 설정하여 넣기로 함

  >> 여기서 문제, 모든 몬스터를 한 Map에 담으려고 하니 종류가 달라 넣을 수 없음

  >> Interface를 생성해서 각 종류를 묶어주는 역할을 함

  >> 문제는 종류를 interface로 묶으니 그 속에는 Thread가 없어서 Thread를 실행하는데 문제가 생김

  >> interface는 interface를 상속받을 수 있으므로, interface에 Runnable을 상속함

      (방향을 잘못 잡아서 본의아니게 많은 공부를 하게 됨. 혹시 더 나은 방법이 있다면 조언 부탁드립니다.)

 

 

-아무 내용 없는 interface에 Runnable을 상속

package Game1;

public interface MonsterGroup extends Runnable{
	
}

- 메인(Play_Phase1)에 전역변수로 Map 추가

public HashMap<Integer, MonsterGroup> listMonster = new HashMap<Integer,MonsterGroup>();

- run()에 각 몬스터를 map으로 변경

- int 타입의 i,j,k로 각 5마리씩 범위를 두고 생성

  (시간 상 5마리 이상 한 번에 나올 수 없기 때문에 범위를 5씩만 줬는데, 혹시 몹의 속도가 빠르다면 범위를 더 넓게 주며 됨)

- for문으로 숫자 4가 되면 다시 해당 숫자를 재활용하도록 하여 숫자가 계속 커지지 않게 함

	@Override
	public void run() {
		for(int i=0;i<5;i++){
			try {
				Thread.sleep(500);//객체가 생성되는 시간
				countTime += 500;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			/**Monster 1 count*/
			if(countTime%1500 == 0) {
				listMonster.put(i, new Monster1(this,i));
				(new Thread(listMonster.get(i))).start();
			}
			
			/**Monster 2 count*/
			if(countTime%2000 == 0) {
				int j = i+5;
				listMonster.put(j, new Monster2(this,j));
				(new Thread(listMonster.get(j))).start();
			}
			
			/**Monster 3 count*/
			if(countTime%3000 == 0) {
				int	k = i+10;
				listMonster.put(k, new Monster3(this,k));
				(new Thread(listMonster.get(k))).start();
			}
			
			if (i == 4) i = 0; // 몹 스레드 재활용 
			
			/**Bullet count*/
			if(countTime%500 == 0&& isFire == true) {
				isFire = false;
				idxBullet += 1; //Map의 Key값 설정
				 if (idxBullet == 30) { //key값이 너무 커지지 않게 재활용
					 idxBullet = 0;
				 }
				 listBullet.put(idxBullet, new BtnBullet(this, idxBullet));
				 (new Thread(listBullet.get(idxBullet))).start();
			}
		}
	}

 

 

 

- 총알 class (BtnBullet) 작업

- public boolean iscrashed; 전역변수

- if문으로 충돌한다면 break하도록 설정

- while문이 끝나면 버튼을 없앰과 동시에 해당 버튼을 map에서 빼기

@Override
	public void run() {
		while(bulletY > 30) { //끝에 닿을 때 까지 움직이기
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			/**run Bullet*/
			this.setLocation(bulletX, bulletY-= 30);
			//System.out.println(this.getLocation());//테스트 코드
			
			/**'Monster' is crashed with 'Bullet'*/
			if(iscrashed){
	            break;
	         }
		}
		play1.remove(this);
		play1.listBullet.remove(idx);
		play1.repaint();
		play1.revalidate();
	}

 

 

- 몬스터 class(Monster1, Monster2, Monster3) 작업

- 각 몬스터 class에 아까 만들어둔 interface를 implements시켜주기

public class Monster1 extends JButton implements Runnable, MonsterGroup

- run()안에 내용 수정 : 충돌이 일어나면 해당 키 값을 가진 총알 JButton에 있는 iscrashed를 true로 변경

/**'Monster' is crashed with 'Bullet'*/
			for(Map.Entry<Integer, BtnBullet> bullet:play1.listBullet.entrySet()){
	            if(isDead(monX,monY,play1.listBullet.get(bullet.getKey()))){
	            	//System.out.println("맞췄다!Monster1"); //테스트 코드
	            	isMonsterOver=true;
	            	
	            	play1.listBullet.get(bullet.getKey()).iscrashed=true;
	            	play1.listBullet.remove(bullet.getKey());
	            	break;
	            }
	         }
			if(isMonsterOver){
	            break;
	         }

 

너무 게임을 잘해서 하늘에 별이 없네요 :)

총알과 몬스터가 동시에 사라지는 모습을 볼 수 있습니다!