안녕하세요.


지난시간에는 게임이 클리어까지 잘 진행되는 걸 확인했습니다. 그런데 메세지가 콘솔창에 찍혀나온다는 게 단점이었죠.


메세지가 라벨에 표시되도록 수정해나갈건데요, 근데 인간이 공격하는 내용과 슬라임이 공격하는 내용을 동시에 표시할 것이기 때문에 라벨이 하나더 필요해보입니다.




빨간네모 위치에 하나더 만들건데요, 공간이 되게 비좁아보입니다. 디자인을 좀 수정해야겠네요.






31행 : 두번째 라벨을 위한 변수를 추가했습니다.


45행 : 프레임의 세로 길이를 좀 늘렸습니다.


62행 : 첫번째 라벨의 세로위치를 약간 내렸습니다.


70행 : 두번째 라벨에 맨 처음으로 표시할 내용은 주인공의 체력입니다.







자, 이렇게 되었습니다. 이제 진도를 나가도록 하죠.


감사합니다.


안녕하세요.


지난시간에는 버튼을 눌렀을때 콘솔창에 출력시키는 것까지 성공시켰습니다.


그런데 각 버튼의 액션함수마다 코딩을 하는건 중복이기 때문에 다른 방법을 사용해야될 필요성이 대두되었습니다.


답은 간단합니다. 전투용 함수를 이용하는 거죠. 아래를 보시죠.




배틀함수를 만들고 각 액션함수에서 호출해줬습니다. 이렇게 하면 전투내용을 배틀함수에 한번만 적어주면 되니 효율적이죠^^


자, 그럼 1탄에서 사용했던 코드를 배틀함수에 넣어보겠습니다.






이런 모습이 되겠죠.


그런데 h, s1, s2 변수에 에러가 나있네요. 에러메세지를 보면 '해석할 수 없다'고 나옵니다. 그 이유는 세 변수가 메인함수 내에서 선언된 지역변수이기 때문입니다. 전역변수인 s는 에러가 나있지 않죠?


그렇다면 세 변수를 전역변수로 변신시킵시다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Study01.java
 
package study;
 
import java.awt.Font;
import java.util.Enumeration;
 
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;
 
public class Study01 {
 
    // 빈 슬라임 변수
    static Slime s = null;
    
    // 슬라임과 인간 객체 생성
    static Slime s1 = new Slime("슬라삐");
    static Slime s2 = new Slime("슬라디");
    static Human h = new Human("알렉스");
 
    public static void main(String[] args) {
        
        // [start] 디자인 코드
 
        // 라벨 변수 선언
        JLabel lbl;
 
cs


이렇게 되겠죠. static 함수인 메인함수에서도 사용되어야 하니 앞에 static도 붙였습니다.


자, 이제 보다 업그레이드 된 게임이 완성되었네요. 실행해봅시다!






잘되시나요? ㅎㅎ


그런데 기껏 GUI를 만들어놓고 메세지가 콘솔에 출력이 되니 좀 모순이네요. 다음시간에는 라벨에다가 전투 메세지가 표시되도록 고쳐보겠습니다.


감사합니다.


안녕하세요.


진도를 잘 따라오고 계신가요? ㅎ


지금까지의 코드는 아래와 같습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Study01.java
 
package study;
 
import java.awt.Font;
import java.util.Enumeration;
 
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;
 
public class Study01 {
 
    // 빈 슬라임 변수
    static Slime s = null;
 
    public static void main(String[] args) {
 
        // 라벨 변수 선언
        JLabel lbl;
 
        // 슬라임과 인간 객체 생성
        Slime s1 = new Slime("슬라삐");
        Slime s2 = new Slime("슬라디");
        Human h = new Human("알렉스");
 
        // 모든 글꼴 통일
        Enumeration<Object> keys = UIManager.getDefaults().keys();
        while (keys.hasMoreElements()) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource)
                UIManager.put(key, new FontUIResource("굴림", Font.PLAIN, 14));
        }
 
        // [start] 프레임 설정
        JFrame frm = new JFrame();
        frm.setTitle("슬라임 퇴치하기");
        frm.setSize(350300);
        frm.setLocationRelativeTo(null);
        frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frm.getContentPane().setLayout(null);
        // [end]
 
        // 버튼 설정
        JButton btn1 = new JButton(s1.name);
        JButton btn2 = new JButton(s2.name);
        btn1.setBounds(3017012230);
        btn2.setBounds(18217012230);
        frm.getContentPane().add(btn1);
        frm.getContentPane().add(btn2);
 
        // 라벨 설정
        lbl = new JLabel();
        lbl.setBounds(3020027450);
        lbl.setText("게임을 시작합니다");
        lbl.setHorizontalAlignment(JLabel.CENTER); // 수평 가운데 정렬
        frm.getContentPane().add(lbl);
 
        // [start] 이미지 라벨 생성
        JLabel imgLbl = new JLabel();
        ImageIcon bsImg = new ImageIcon(Study01.class.getResource("/study/img/slime(blue).png"));
        imgLbl.setIcon(bsImg);
        imgLbl.setBounds(3030122130);
        imgLbl.setHorizontalAlignment(JLabel.CENTER);
        frm.getContentPane().add(imgLbl);
        // [end]
 
        // [start] 이미지 라벨2 생성
        JLabel imgLbl2 = new JLabel();
        imgLbl2.setIcon(bsImg);
        imgLbl2.setBounds(18230122130);
        imgLbl2.setHorizontalAlignment(JLabel.CENTER);
        frm.getContentPane().add(imgLbl2);
        // [end]
 
        // 프레임이 보이도록 설정
        frm.setVisible(true);
 
        // 버튼을 눌렀을때
        btn1.addActionListener(event -> {
            s = s1;
 
        });
 
        btn2.addActionListener(event -> {
            s = s2;
        });
 
        System.out.println(s.name);
    }
 
}
 
cs


아직 실행하지는 마시구요, 마지막 부분을 다시한번 봅시다.






버튼을 눌렀을때 작동하는 코드를 맨 아래쪽으로 옮겼습니다. 이러한 특수한 코드가 디자인 코드속에 섞여 있으면 가독성이 떨어지니까요.


아무튼 위 코드의 의도는 버튼을 누르면 해당하는 객체가 변수 s에 할당이 되어서 콘솔창에 그 이름이 표시되게 하는 것입니다.


실행해볼까요?






웁스~ 실행하자마자 93행에 에러가 났다고 빨간 글씨가 뜨네요. 버튼을 클릭해도 아무 반응이 없습니다.


왜그럴까요? 93행을 아래와 같이 수정하고 실행하면 감이 잡히실 겁니다.



System.out.println(1);



실행해봅시다.






버튼을 누르기도 전에 1이 뜨네요. 이게 중요합니다. 


일반적으로 코드는 위에서 아래로 순서대로 실행되지만 '버튼을 눌렀을때', '마우스를 갖다댔을때', '특정키를 눌렀을때' 같은 이벤트(한국말로 사건) 코드는 그 사건이 발생했을때 실행됩니다.





따라서 버튼을 눌렀을때의 코드보다 93행이 먼저 실행이 된다는거죠. 변수 s에 아무것도 할당되어 있지 않으니 에러가 나는게 당연합니다.


슬라임의 이름을 보려면 아래와 같이 수정해야겠죠.





1
2
3
4
5
6
7
8
9
10
        // 버튼을 눌렀을때
        btn1.addActionListener(event -> {
            s = s1;
            System.out.println(s.name);
        });
 
        btn2.addActionListener(event -> {
            s = s2;
            System.out.println(s.name);
        });
cs

(행번호는 무시하세요)


콘솔출력을 액션 함수 속에 넣으니 잘 되는군요^^




그런데 그렇다면 우리는 아래처럼 코딩할 수 밖에 없을까요?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        // 버튼을 눌렀을때
        btn1.addActionListener(event -> {
            s = s1;
            
            // 슬라임이 살아있을때만 공격
            // ...
            
            // 슬라임이 모두 죽으면 게임 클리어
            // ...
            
        });
 
        btn2.addActionListener(event -> {
            s = s2;
            
            // 슬라임이 살아있을때만 공격
            // ...
            
            // 슬라임이 모두 죽으면 게임 클리어
            // ...
        });
cs

(행번호는 실제 행번호와 다릅니다)


똑같은 내용을 2번 적어줘야 되니 중복이네요. 슬라임이 10마리라면 10번... ㄷ ㄷ 애초에 s변수를 만들어준 의미가 없어졌네요.


좋은 방법이 없을까요? 답은 의외로 간단합니다. 다음 시간에 알아보죠.


감사합니다.


안녕하세요.


지난시간의 에러를 한번 보시죠.




에러가 난 곳에 마우스를 갖다대니 메세지가 뜨는데 '지역변수 s는 어찌어찌 돼야 된다'고 어려운 영어로 쓰여있네요.


해결방법은 간단합니다. s를 전역변수로 바꾸는 거죠.





s를 이렇게 메인함수 바깥으로 이동시키면 전역변수로 변신합니다.





근데 이번에는 에러내용이 바꼈네요. static 함수에서 static이 아닌 변수는 사용할 수 없다는 내용입니다. 메인함수가 static이니까 변수 s를 static으로 바꿔줘야겠네요. 빨간네모를 클릭하셔도 되고 수작업으로 static을 붙여주셔도 됩니다.





이렇게 수정하면 에러가 사라집니다^^




다음시간에는 전투가 이루어지도록 코딩해봅시다.


감사합니다.



안녕하세요.


진도를 나가기 전에 알아야될 개념이 있어서 짚고 넘어갈까 합니다.


아래와 같은 축구선수 클래스를 만들어봅시다. (메인 함수는 없습니다)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// SoccerPlayer.java
 
 
package study;
 
public class SoccerPlayer {
    
    int str = 100// 공격력
    int def = 70// 수비력
    
    // 공격 중심
    public void offensive() {
        
        str += 10;
        def -= 10;
 
    }
 
    // 수비 중심
    public void defensive() {
        
        str -= 10;
        def += 10;
 
    }
}
 
cs


(14행은 str = str + 10을 축약한 형태입니다. 마찬가지로 15행은 def = def - 10의 축약입니다.)


변수가 선언된 위치를 유심히 봅시다. str과 def 변수는 함수 바깥에 선언되어 있습니다. 만약 offensive 함수 속에 선언하면 어떻게 될까요?





20, 21행에서 에러가 나는군요.

왜냐하면 함수 속에서 변수를 선언하면 그 함수 속에서만 사용할 수 있기 때문입니다.


이처럼 함수 바깥에 선언하여 클래스 전체에서 사용가능한 변수를 전역변수,

함수 속에 선언하여 해당 함수 속에서만 사용가능한 변수를 지역변수라고 합니다.


감사합니다.


안녕하세요.


지난시간에 디자인적인 코딩은 모두 끝냈습니다.


이제 전투가 잘 이루어지도록 생명력을 불어넣어야겠죠.


1탄 만들때 만들어두었던 슬라임 클래스와 인간 클래스를 사용하면 됩니다.


아래를 보시죠.




(행번호 옆의 빨간네모가 제일먼저 눈에 들어오시나요^^; 원하는 부분만큼 코드를 접을 수 있게 해주는 플러그인입니다. [start]와 [end]로 범위를 지정할 수 있죠. 자세한 점은 https://blog.naver.com/jktk1/221483421176를 참고하세요.)


일단 코드가 길어서 두부분으로 나누었습니다.


- 23행 : 객체를 생성할때 보통은 생성과 동시에 변수에 집어넣지만(다른말로 할당한다고도 합니다) 이렇게 미리 변수만 선언해놓고 나중에 할당할 수도 있습니다.


- 49, 50행 : 버튼의 텍스트를 각 슬라임 객체의 이름 변수를 참조하도록 수정햇습니다. 이렇게 해두면 훗날 슬라임의 이름을 바꿔야 될 일이 생겼을때 26, 27행만 수정하면 되죠.




- 57행 : 23행에서 라벨 변수를 선언해두었으니 lbl 앞에 붙어있던 JLabel을 지워줍시다.



그런데 65행과 69행에서 에러가 나있네요. 다음시간에는 이 에러를 해결해보도록 하겠습니다.


감사합니다.


안녕하세요.





이렇게 오른쪽에도 슬라임 그림을 넣는게 지난시간의 숙제였죠? 정답은 아래와 같습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        // 라벨 생성
        JLabel imgLbl = new JLabel();
        
        // 라벨에 넣을 아이콘 생성
        ImageIcon bsImg = new ImageIcon(Study01.class.getResource("/study/img/slime(blue).png"));
        
        // 라벨에 아이콘 설정
        imgLbl.setIcon(bsImg);
        
        // 기타 설정
        imgLbl.setBounds(3030122130);
        imgLbl.setHorizontalAlignment(JLabel.CENTER);
        frm.getContentPane().add(imgLbl);
        
        // ★ 라벨2 생성
        JLabel imgLbl2 = new JLabel();
        
        // ★ 라벨2에 아이콘 설정
        imgLbl2.setIcon(bsImg);
        
        // ★ 기타 설정
        imgLbl2.setBounds(18230122130);
        imgLbl2.setHorizontalAlignment(JLabel.CENTER);
        frm.getContentPane().add(imgLbl2);
 
        // 프레임이 보이도록 설정
        frm.setVisible(true);
cs


이제는 굳이 설명 안드려도 다 이해가 되실 것 같네요. 한가지 주목할만한점은 이미지 아이콘 객체를 하나더 만들지 않고 기존 것을 재사용한 점이겠네요(19행 참조)


그런데말입니다. 예민한 분은 여태까지 계속 신경이 쓰인 부분이 있을 겁니다. 한글의 글꼴이 좀 보기가 싫죠. 모든 컴포넌트의 글꼴을 '굴림'으로 한번 바꿔볼까 합니다.

메인함수의 맨윗부분에다가 아래 코드를 추가하시면 되겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Study01.java
 
package study;
 
import java.awt.Font;
import java.util.Enumeration;
 
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;
 
public class Study01 {
 
    public static void main(String[] args) {
        
        // ★ 모든 글꼴 통일
        Enumeration<Object> keys = UIManager.getDefaults().keys();
        while (keys.hasMoreElements()) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource)
                UIManager.put(key, new FontUIResource("굴림", Font.PLAIN, 14));
        }
 
        // 프레임 생성
        JFrame frm = new JFrame();
cs



되게 복잡하죠^^; 코드 내용을 이해하실 필요는 없구요, 25행의 ("굴림", Font.PLAIN, 14) 이 부분만 입맛에 맞게 바꿔주시면 되겠습니다.


(글꼴, 유형, 크기) 입니다.


만약에 크기 20짜리 굵은 궁서를 하고 싶으면 ("궁서", Font.BOLD, 20) 이라고 코딩하면 되겠죠.



자, 어떻게 바꼈는지 볼까요?




깔끔해졌군요^^



코드 전문은 아래와 같습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Study01.java
 
package study;
 
import java.awt.Font;
import java.util.Enumeration;
 
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;
 
public class Study01 {
 
    public static void main(String[] args) {
        
        // 모든 글꼴 통일
        Enumeration<Object> keys = UIManager.getDefaults().keys();
        while (keys.hasMoreElements()) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource)
                UIManager.put(key, new FontUIResource("굴림", Font.PLAIN, 14));
        }
 
        // 프레임 생성
        JFrame frm = new JFrame();
 
        // 프레임 제목 설정
        frm.setTitle("슬라임 퇴치하기");
 
        // 프레임 크기 설정
        frm.setSize(350300);
 
        // 프레임을 화면 가운데에 배치
        frm.setLocationRelativeTo(null);
 
        // 프레임을 닫았을 때 프로그램이 종료되도록 설정
        frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        // 레이아웃 설정
        frm.getContentPane().setLayout(null);
 
        // 버튼 생성
        JButton btn1 = new JButton("슬라삐");
        JButton btn2 = new JButton("슬라디");
 
        // 버튼 위치와 크기 설정
        btn1.setBounds(3017012230);
        btn2.setBounds(18217012230);
 
        // 프레임에다가 버튼 추가
        frm.getContentPane().add(btn1);
        frm.getContentPane().add(btn2);
 
        // 라벨 설정
        JLabel lbl = new JLabel();
        lbl.setBounds(3020027450);
        lbl.setText("게임을 시작합니다");
        lbl.setHorizontalAlignment(JLabel.CENTER); // 수평 가운데 정렬
        frm.getContentPane().add(lbl);
 
        // 버튼이 눌렸을때
        btn1.addActionListener(event -> {
            lbl.setText("나는 슬라삐");
        });
 
        btn2.addActionListener(event -> {
            lbl.setText("나는 슬라디");
        });
 
        // 라벨 생성
        JLabel imgLbl = new JLabel();
 
        // 라벨에 넣을 아이콘 생성
        ImageIcon bsImg = new ImageIcon(Study01.class.getResource("/study/img/slime(blue).png"));
 
        // 라벨에 아이콘 설정
        imgLbl.setIcon(bsImg);
 
        // 기타 설정
        imgLbl.setBounds(3030122130);
        imgLbl.setHorizontalAlignment(JLabel.CENTER);
        frm.getContentPane().add(imgLbl);
 
        // ★ 라벨2 생성
        JLabel imgLbl2 = new JLabel();
 
        // ★ 라벨2에 아이콘 설정
        imgLbl2.setIcon(bsImg);
 
        // ★ 기타 설정
        imgLbl2.setBounds(18230122130);
        imgLbl2.setHorizontalAlignment(JLabel.CENTER);
        frm.getContentPane().add(imgLbl2);
 
        // 프레임이 보이도록 설정
        frm.setVisible(true);
 
    }
 
}
 
cs



이로써 슬라임 게임의 디자인적인 코딩은 다 끝났습니다.


이제 버튼을 눌러서 전투를 할 수 있도록 코드를 손봐야겠죠?


감사합니다.


안녕하세요.





'슬라삐'라고 적힌 버튼 위에 파란색 슬라임 그림을 넣어보도록 하겠습니다.


우선 코드부터 보시죠.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
        // 버튼이 눌렸을때
        btn1.addActionListener(event -> {
            lbl.setText("나는 슬라삐");
        });
 
        btn2.addActionListener(event -> {
            lbl.setText("나는 슬라디");
        });
 
        // ★ 라벨 생성
        JLabel imgLbl = new JLabel();
        
        // ★ 라벨에 넣을 아이콘 생성
        ImageIcon bsImg = new ImageIcon(Study01.class.getResource("/study/img/slime(blue).png"));
        
        // ★ 라벨에 아이콘 설정
        imgLbl.setIcon(bsImg);
        
        // ★ 기타 설정
        imgLbl.setBounds(3030122130);
        imgLbl.setHorizontalAlignment(JLabel.CENTER);
        frm.getContentPane().add(imgLbl);
 
        // 프레임이 보이도록 설정
        frm.setVisible(true);
cs

- 11행 : 그림은 따로 컴포넌트(버튼, 라벨 등을 컴포넌트라고 합니다)가 있는 것이 아니라 라벨 앞에 붙이는 아이콘을 사용합니다. 그래서 이미지용 라벨 객체를 생성한 겁니다. 객체를 나타내는 변수 이름은 이미지 라벨을 줄여서 imgLbl이라고 했는데요, L이 대문자인 이유는 다음과 같습니다. 변수 이름이든 함수 이름이든 중간에 띄어쓰기가 들어가면 안됩니다. 그렇다고 imglbl 이런 식으로 하면 가독성이 떨어지죠. 그래서 img_lbl 이렇게 중간에 밑줄을 적는 방식이 있고 두번째 단어 첫글자를 대문자로 적는 방식이 있습니다.

- 14행 : 라벨에 붙일 아이콘 객체입니다. 이미지 아이콘 클래스를 사용합니다. 생성자 인수가 제법 복잡해보이는데요,
(현재 클래스명.class.getResource("/패키지명/그림폴더명/그림파일명"));
이렇게 되어있는 구조입니다. 그림파일명은 png라는 확장자까지 적어주시길 바랍니다.


이미지 라벨에다가 아무런 글자도 세팅하지 않았으므로 아이콘(이미지)만 표시하게 됩니다. 20행을 잘 이해하셔야 되는데요, 이 구문은 라벨에 대한 것이기 때문에 가로길이나 세로길이를 변경해도 속에 있는 아이콘(이미지)의 크기는 변하지 않습니다. 아이콘의 크기를 변경시키는 방법이 있긴 있지만 코드가 제법 복잡해지기 때문에 알씨 같은 프로그램을 사용해서 그림 크기를 미리 바꿔놓는 것이 좋습니다.



그림이 잘 뜨나요? ㅎㅎ 


이번엔 슬라디 버튼 위에도 파란색 슬라임 그림을 넣어보시길 바랍니다.





이렇게 말이죠^^ 해답은 다음 강의에서 공개하겠습니다 ㅎㅎ

감사합니다.


+ Recent posts