이번에는 하늘에서 떨어지는 몬스터를 만들어볼 생각입니다.
당연히 몬스터도 JButton이겠죠?
저는 몬스터1의 이미지를 붉은 별로 했어요.
배경이 너무 마음에 드는데 적은 노란별로 했더니 안보이더라고요.
고민하는 저한테 친구가 별이 꼭 노란색이어야 해? 라고 물어봤어요.
그래서 바로 색을 변경, 훨씬 눈에도 잘 들어오고 낙엽같아서 감성이 묻어나네요.
(고마워 칭구야 :> )
게임의 스토리(?)에 따르면, 주인공은 첫 패널에 나온 여자의 부탁으로 악당에게 있는 달을 찾으러 갑니다.
그리고 저 별은 악당의 부하인 거죠.
자, 해봅시다.
전제 : 몬스터1 JButton class에 Runnable로 Thread 구현
'Play_Phase1'에 Thread를 추가해 몬스터 객체 자동 소환
오늘 할 일 : 'Play_Phase1' class에 Runnable 추가
몬스터1 JButton class를 일정 시간마다 소환
(추가) 총알의 속도를 조절하기 위하여 같은 Thread 이용하기
- Monster1 class에 JButton 상속받고 Runnable로 Thread추가
- 좌표 x의 값은 랜덤으로 설정 _ Math.random사용_ 양 옆에 20정도의 여유를 둠
- 좌표 y의 값은 -50으로 화면 밖에서 생성하여 자연스럽게 나타나게 조정
- run()에 while문을 사용하여 y좌표 700이 되면 끝나고 JButton이 사라지게 함
//while문은 꼭 써야할 이유가 아니라면 실수했을 때 컴퓨터에 무리가게 한다고 자제하라고 주워들었는데 맞나요 ..?
//그렇지만 여기에서는 while문이 편하게 느껴지더라고요.
// 혹시 더 나은 조건이 있다면 조언 부탁드립니다.
package Game1;
import javax.swing.ImageIcon;
import javax.swing.JButton;
public class Monster1 extends JButton implements Runnable {
Play_Phase1 play1;
private int monX, monY;
Monster1(Play_Phase1 play1){
this.play1 = play1;
monX =(int)((Math.random()*420)+20); //위치 설정
monY = -50;
ImageIcon icmon = new ImageIcon("별_빨강.png"); //이미지 설정
this.setIcon(icmon);
this.setBorderPainted(false);
this.setFocusPainted(false);
this.setContentAreaFilled(false);
this.setBounds(monX, monY, 50, 50);
/**add Monster*/
play1.add(this);
}
@Override
public void run() {
while(monY<700){
try {
Thread.sleep(100);//적이 떨어지는 시간
} catch (InterruptedException e) {
e.printStackTrace();
}
/**set Location*/
this.setLocation(monX, monY+=15);
}
play1.remove(this);
play1.repaint();
play1.revalidate();
}
}
- 플레이 메인(Play_Phase1)에 Runnable을 추가
- run()안에 int타입의 countTime변수를 추가하여 지나간 시간만큼 그 수를 더하게 함
- Monster1은 1.5초에 하나씩 나오게 설정
- Thread 작업하는김에 총알이 화면에 출력되는 갯수를 줄이기 위해 시간 제한(0.5초)을 둠
조건을 (SpaceBar를 누른다) + (0.5초) 두개를 병합해서 줌
//countTime%500 == 0&& isFire == true
- boolean타입의 isFire를 추가하여 Space Bar를 눌렀을 때 true로 바뀌게 설정
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
meX += 20;
} else if(e.getKeyCode()==KeyEvent.VK_LEFT) {
meX -= 20;
} else if(e.getKeyCode()==KeyEvent.VK_UP) {
meY -= 20;
} else if(e.getKeyCode()==KeyEvent.VK_DOWN) {
meY += 20;
} else if(e.getKeyCode()==KeyEvent.VK_SPACE) {
if(!isSpacePress){ //스페이스 연사를 방지하기 위함
isSpacePress=true;
}
isFire =true;
}
if(meX < 10) { //일정 범위 이상 못 나가도록
meX = 10;
} else if(meX > 450) {
meX = 440;
} else if(meY < 300) {
meY = 300;
} else if(meY > 700) {
meY = 700;
}
btnMe.setLocation(meX, meY); //위치 설정
setMePosition(meX, meY); //총알을 위한 위치 설정 메소드
this.repaint(); //화면 갱신
this.revalidate();
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(500);//객체가 생성되는 시간
countTime += 500;
} catch (InterruptedException e) {
e.printStackTrace();
}
/**Monster 1 count*/
if(countTime%1500 == 0) {
monster1 = new Monster1(this);
(new Thread(monster1)).start();
}
/**Bullet count*/
if(countTime%500 == 0&& isFire == true) {
isFire = false;
bullet = new BtnBullet(this);
(new Thread(bullet)).start();
}
}
}
자, 여기서 문제.
총알과 몬스터의 Thread는 플레이 패널(Play_Phase1)에서 실행시켜줬는데,
'Play_Phase1'의 run()은 어디서 실행시켜야 할까요?
여기서 시행착오를 좀 겪었습니다. 패널 내에서,
Thread t1 = new Thread(this);
t1.start();
이렇게 했는데 시작을 안 하더라고요.
혹시 저번 focus문제 기억하시나요?
2020/12/11 - [Java_Study/Code_Memo] - JButton으로 슈팅게임 2-1 주인공 만들기
여기서 Key Listener를 실행하기 위해 JFrame까지 갔었잖아요?
이번에도 같은 방법으로 해결했습니다.
- 메인 프레임(Main_StartHere)에 있는 JPanel연결 Method에서
(new Thread(playPhase1)).start(); 를 실행시킨다!
public void MainPnl2ToNext(int i) { //메인 패널에서 첫화면/게임화면 이동
this.remove(main2);
if (i == 1) { //첫 화면으로
this.add(firstPage);
} else if (i ==2) { //게임 화면으로
playPhase1 = new Play_Phase1(this);
this.add(playPhase1);
playPhase1.setFocusable(true);
playPhase1.requestFocus();
(new Thread(playPhase1)).start();
}
this.repaint();
this.revalidate();
}
다음번에는 몬스터를 추가로 만들어볼 거예요.
이미 만들어놓은 몬스터가 있으니까 이번에는 좀 더 쉽겠죠? 제발 ;<
'Coding_Study > Java_Code_Memo' 카테고리의 다른 글
JButton으로 슈팅게임 3- 2 (충돌) 총알 (0) | 2020.12.12 |
---|---|
JButton으로 슈팅게임 3-1 (충돌) 몬스터 죽이기 (0) | 2020.12.12 |
JButton으로 슈팅게임 2-2 총알 만들기 (0) | 2020.12.11 |
JButton으로 슈팅게임 2-1 주인공 만들기 (0) | 2020.12.11 |
JButton으로 슈팅게임 1-2 시작 패널 마무리 (0) | 2020.12.11 |