Phase 1의 내용과 많이 겹치기 때문에
Phase 2는 혼자 빠르게 하고 한꺼번에 가지고 왔습니다.
전제 : Phase1과 Phase 2는 다른 JPanel이다.
Phase1이 끝나고 짧은 스토리가 나온 뒤 Phase 2가 시작된다.
스토리 내의 선택에 따라 보스까지 가지 않고 게임이 끝날 수 있다.
Phase2가 시작되면 Boss와 함께 Phase 1에서 썼던 Monster2와 같은 경로의 몹을 등장시킨다.
Boss의 에너지는 1,000이고, energy bar로 표시된다.
Boss는 JPanel의 끝과 끝으로 한바퀴 돈다.
Boss가 내려가면 에너지가 차도록 한다.
Boss의 에너지가 0이 되면 엔딩화면으로 넘어간다.
오늘 할 일 : 이전에 했던 작업 + 에너지 바 추가 하기
- 메인(Play_Phase2) 작업
package Game1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import miniGame_Main_ChooseGame.Main_StartHere;
public class Play_Phase2 extends JPanel implements KeyListener, Runnable{
Main_StartHere main;
BtnMe btnMe; BtnBullet bullet;
Boss boss; Monster4 monster;
public Point poMe;
private int meX = 225, meY =720;
private int countTime;
private int bossEnergy;
private JLabel eneryBar;
private Image backgroundImage; //배경 이미지
private boolean isSpacePress;
private boolean isFire;
private boolean isWon;
private boolean isPhase2Stop;
private boolean isGameOver;
public HashMap<Integer,BtnBullet2> listBullet = new HashMap<Integer,BtnBullet2>();
private int idxBullet;
public Play_Phase2(Main_StartHere main) {
this.main = main;
try {//배경 이미지 삽입
backgroundImage = ImageIO.read(new File("스테이지2.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
this.setSize(500,800);
this.setLayout(null); //자유롭게 움직이기위해 레이아웃을 없앤다.
this.addKeyListener(this); //btnMe를 키값으로 움직이기 위해
btnMe = new BtnMe(this); //주인공 버튼 class
btnMe.setBounds(meX,meY, 50,50);
this.add(btnMe);
boss = new Boss(this);
(new Thread(boss)).start();
eneryBar = new JLabel();
eneryBar.setOpaque(true);
eneryBar.setBackground(Color.red);
this.add(eneryBar);
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(100);//객체가 생성되는 시간
countTime += 100;
} catch (InterruptedException e) {
e.printStackTrace();
}
if(isPhase2Stop == true) {
break;
}
/**set EnergyBar*/
eneryBar.setBounds(0,0,getBossEnergy(),20);
this.repaint();
this.revalidate();
/**Monster count*/
if(countTime%1000 == 0) {
monster = new Monster4(this);
(new Thread(monster)).start();
}
/**Bullet count*/
if(countTime%500 == 0&& isFire == true) {
isFire = false;
idxBullet += 1; //Map의 Key값 설정
if (idxBullet == 30) { //key값이 너무 커지지 않게 재활용
idxBullet = 0;
}
listBullet.put(idxBullet, new BtnBullet2(this, idxBullet));
(new Thread(listBullet.get(idxBullet))).start();
}
}
if(isGameOver == true) { // 게임 끝
ImageIcon icon = new ImageIcon("tomb-2.png");
int result = JOptionPane.showConfirmDialog (main, "Game Over, Try Again?", "안타깝네요!", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,icon);
if(result == 0) {
main.Play_PhaseToNext(4);//첫 페이지로 간다
} else if(result == -1 || result == 2) {
main.Play_PhaseToNext(5);//게임 메인으로 간다
}
} else if(isWon == true) {
main.Play_PhaseToNext(6);
}
}
@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 keyReleased(KeyEvent e) {//스페이스 연사를 방지하기 위함
isSpacePress=false;
}
public void keyTyped(KeyEvent e) {} //사용 안 함
@Override
protected void paintComponent(Graphics g) { //이미지 작업
super.paintComponent(g);
g.drawImage(backgroundImage,0,0,500,800,null);
}
/**Me Location*/
void setMePosition(int meX, int meY) {
poMe = new Point(meX, meY);
}
/**Game over*/
public void setOver(boolean b) {
btnMe.setLocation(0,800); //죽고 나서 버튼 위치 남아있는 오류, 버튼 위치를 미리 밖으로 보내버리기
this.remove(btnMe);
isPhase2Stop = true;
isGameOver = true;
}
/**checking the boss is died, true > win*/
void setCheckBoss(boolean isBossOver) {
isPhase2Stop = true;
isWon = true;
}
/**get,set BossEnergy*/
public int getBossEnergy() {
return bossEnergy;
}
public void setBossEnergy(int bossEnergy) {
this.bossEnergy = bossEnergy/2;
}
}
- Monster4 작업
package Game1;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JButton;
public class Monster4 extends JButton implements Runnable, MonsterGroup {
Play_Phase2 play2;
private int monX, monY;
private int idx;
private boolean direction;
private boolean isMonsterOver;
Monster4(Play_Phase2 play2){
this.play2 = play2;
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*/
play2.add(this);
}
private boolean isDead(int monX, int monY, JButton bullet){ //충돌 알고리즘
if (Math.abs((monX+this.getWidth()/2)-(bullet.getX()+bullet.getWidth()/2))
< (bullet.getWidth()/2+this.getWidth()/2)
&& Math.abs((monY+this.getHeight()/2)-(bullet.getY()+bullet.getHeight()/2))
< (bullet.getHeight()/2+this.getHeight()/2)){
return true;
}else{
return false;
}
}
@Override
public void run() {
while(monY<700){
try {
Thread.sleep(100);//적이 떨어지는 시간
} catch (InterruptedException e) {
e.printStackTrace();
}
/**set Location*/
if (direction == false) { //오른쪽으로
this.setLocation(monX+=10, monY+=30);
if (monX > 430) {
direction = true;
}
} else if (direction == true) { //왼쪽으로
this.setLocation(monX-=10, monY+=30);
if (monX < 20) {
direction = false;
}
}
/**'Me' is crashed with 'Monster'*/
if(isDead(monX, monY, play2.btnMe)){
play2.setOver(true);
break;
}
/**'Monster' is crashed with 'Bullet'*/
for(Map.Entry<Integer, BtnBullet2> bullet:play2.listBullet.entrySet()){
if(isDead(monX,monY,play2.listBullet.get(bullet.getKey()))){
isMonsterOver=true;
play2.listBullet.get(bullet.getKey()).iscrashed=true;
play2.listBullet.remove(bullet.getKey());
break;
}
}
if(isMonsterOver){
break;
}
}
play2.remove(this);
play2.repaint();
play2.revalidate();
}
}
- Boss작업
package Game1;
import java.util.Map.Entry;
import javax.swing.ImageIcon;
import javax.swing.JButton;
public class Boss extends JButton implements Runnable{
Play_Phase2 play2;
private int bossX = 190, bossY = 30;
private int isMove;
private boolean isBossOver;
private int bossEnergy = 1000;
Boss(Play_Phase2 play2){
this.play2 = play2;
ImageIcon icmi = new ImageIcon("보스 얼굴.png");
this.setIcon(icmi);
this.setBorderPainted(false);
this.setFocusPainted(false);
this.setContentAreaFilled(false);
this.setBounds(bossX, bossY, 120, 120);
/**add Monster*/
play2.add(this);
}
private boolean isDead(int bossX, int bossY, JButton bullet){ //충돌 알고리즘
if (Math.abs((bossX+this.getWidth()/2)-(bullet.getX()+bullet.getWidth()/2))
< (bullet.getWidth()/2+this.getWidth()/2)
&& Math.abs((bossY+this.getHeight()/2)-(bullet.getY()+bullet.getHeight()/2))
< (bullet.getHeight()/2+this.getHeight()/2)){
return true;
}else{
return false;
}
}
@Override
public void run() {
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
/**set Location*/
if(isMove==0){
bossX -=5;
if(bossX<0){isMove= 1;}
}else if(isMove==1){
bossY +=25;
if(bossY>650){isMove =2;}
}else if(isMove==2){
bossX +=15;
if(bossX>380){isMove = 3;}
bossEnergy += 10; //한 바퀴 돌 때 마다 에너지 채우기
if (bossEnergy >= 1000) {
bossEnergy = 1000;
}
play2.setBossEnergy(bossEnergy);
}else if(isMove==3){
bossY -=25;
if(bossY<30){isMove=0;}
}
this.setLocation(bossX, bossY);
/**'Me' is crashed with 'Boss'*/
if(isDead(bossX, bossY, play2.btnMe)){
play2.setOver(true);
break;
}
/**'Boss' is crashed with 'Bullet'*/
for(Entry<Integer, BtnBullet2> bull:play2.listBullet.entrySet()){
if(isDead(bossX,bossY,bull.getValue())){
bossEnergy -= 50;
if(bossEnergy <0) {
bossEnergy = 0;
}
play2.setBossEnergy(bossEnergy);
play2.listBullet.get(bull.getKey()).iscrashed=true;
}
}
if(bossEnergy == 0) {
isBossOver = true;
break;
}
}
play2.remove(this);
play2.repaint();
play2.revalidate();
if(isBossOver == true) {
play2.setCheckBoss(true);
}
}
}
패널 교체 방법은 아래 참고
2020/12/10 - [Java_Study/Code_Memo] - JButton으로 슈팅게임 1-1 시작 패널
주인공은 재활용
package Game1;
import javax.swing.ImageIcon;
import javax.swing.JButton;
public class BtnMe extends JButton {
Play_Phase1 play1; Play_Phase2 play2;
BtnMe(Play_Phase1 play1){
this.play1 = play1;
ImageIcon imageMe = new ImageIcon("주인공.png");
this.setIcon(imageMe);
this.setBorderPainted(false);
this.setFocusPainted(false);
this.setContentAreaFilled(false);
}
BtnMe(Play_Phase2 play2){
this.play2 = play2;
ImageIcon imageMe = new ImageIcon("주인공.png");
this.setIcon(imageMe);
this.setBorderPainted(false);
this.setFocusPainted(false);
this.setContentAreaFilled(false);
}
}
주인공 설명은 아래 참고
2020/12/11 - [Java_Study/Code_Memo] - JButton으로 슈팅게임 2-1 주인공 만들기
총알은 새로 작업
package Game1;
import javax.swing.ImageIcon;
import javax.swing.JButton;
public class BtnBullet2 extends JButton implements Runnable{
Play_Phase2 play2;
private int bulletX, bulletY;
private int idx;
public boolean iscrashed;
BtnBullet2(Play_Phase2 play2, int idx){
this.play2 = play2;
this.idx = idx;
//btnMe의 위치에 따라 총알의 초기값을 조정해주기
if(play2.poMe != null) {//btnMe의 중간에서 총알이 나가게 함
bulletX = play2.poMe.x+15;
bulletY = play2.poMe.y;
} else{ //만약 움직이지 않으면 Point 메소드에 값이 전달되지 않아 null이 됨
bulletX = 240;
bulletY = 720;
}
ImageIcon icon = new ImageIcon("총알.png"); //이미지 처리
this.setIcon(icon);
this.setBorderPainted(false);
this.setFocusPainted(false);
this.setContentAreaFilled(false);
this.setBounds(bulletX, bulletY, 20,20);
/**add Bullet*/
play2.add(this);
}
@Override
public void run() {
while(bulletY > 30) { //끝에 닿을 때 까지 움직이기
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
/**run Bullet*/
this.setLocation(bulletX, bulletY-= 30);
/**'Monster' is crashed with 'Bullet'*/
if(iscrashed){
break;
}
}
play2.remove(this);
play2.listBullet.remove(idx);
play2.repaint();
play2.revalidate();
}
}
총알 설명은 아래 참고
2020/12/11 - [Java_Study/Code_Memo] - JButton으로 슈팅게임 2-2 총알 만들기
주말이 끝나가서 마음이 급해 빠르게 했는데,
혹시 수정할 부분이나 조언이 있다면 언제든 감사히 듣겠습니다. :)
궁금한 점도 언제든 문의해주세요.
'Coding_Study > Java_Code_Memo' 카테고리의 다른 글
JButton으로 슈팅게임 _ 전체 코드 (0) | 2020.12.13 |
---|---|
JButton으로 슈팅게임 _ 마무리 (5) | 2020.12.13 |
JButton으로 슈팅게임 3-4 Phase1 종료 (0) | 2020.12.13 |
JButton으로 슈팅게임 3-3 (충돌) 주인공 죽이기_Game Over (0) | 2020.12.12 |
JButton으로 슈팅게임 3- 2 (충돌) 총알 (0) | 2020.12.12 |