안녕하세요.

 

이번시간은 랜덤한 요소를 게임에 적용해 보도록 하겠습니다.

 

방식은 간단합니다. 0, 1, 2가 랜덤하게 저장되는 변수를 만든 다음, if문으로 조건분기를 시키는 거죠.

 

우선, 1/3의 확률로 인간이 공격에 실패하도록 만들어보겠습니다. (지난 시간에 테스트용으로 변경했던 코드는 원래대로 되돌려주세요)

 

알고나니 간단하죠? 랜덤수가 0일 경우에만 공격이 빗나가고 나머지 경우는 공격이 이루어지도록 코딩했습니다.

 

이번에는 블루슬라임의 경우인데요, 1/3의 확률로 자기자신을 치유하고, 나머지 경우에는 인간을 공격하도록 코딩해보세요.

 

.

.

.

 

한번 해보셨나요? 저는 아래와 같이 코딩했습니다.

 

- 125행 : 기존의 랜덤 변수를 재활용했습니다. 변수는 같지만 새로운 랜덤값이 들어가겠죠.

 

- 130행 : 128행과는 달리, 형변환을 해줄 필요는 없습니다. 101행에서 블루슬라임 객체를 인수로 넣어줬기 때문에 블루슬라임의 어택 함수가 호출이 됩니다.

 

 

다음 시간에 레드슬라임까지 조정하고 나면 드디어 게임 완성이네요.

 

감사합니다.


안녕하세요.


엄청 오랜만에 찾아뵙는 것 같습니다^^;


그동안 회사일이 바빠서... 라는 핑계 아닌 핑계를 대봅니다만;;; 다음편을 기다리고 계셨던 분들께는 죄송하다는 말씀 드립니다(__)



몇달 사이에 코드를 지워버린 분도 계실듯하여; 각 클래스별로 코드 전문을 올려놓고 시작하도록 하겠습니다.



// Study01.java


// Slime.java


// Human.java



정상적으로 실행되는지 확인해보시길 바랍니다.


근데 몇번을 실행해보아도 항상 인간의 승리로 끝나니까 시시하죠? 그 이유는 슬라임의 공격력과 인간의 공격력이 정해져 있기 때문입니다.


뻔한 게임이 되는 걸 피하려면 랜덤한 요소를 추가해야 되는데요, 이를테면 캐릭터의 공격력이나 공격 횟수를 가변적으로 설정하는 거죠.


목표는 아래와 같습니다.



1. 인간의 공격이 빗나가는 경우를 만든다.


2. 블루 슬라임이 자신을 치유할 때도 있고, 인간을 공격할 때도 있다.


3. 레드 슬라임은 한번씩 2배의 공격력으로 인간을 공격한다.



이걸 위해서는 랜덤한 숫자가 저장되는 변수를 만들 필요가 있습니다. 0, 1, 2 이렇게 3가지 숫자 중에서 랜덤하게 저장되는 변수를 만들건데요, 만드는 방법은 아래와 같습니다.



int randomNum = (int) (Math.random() * 3);



끝에 붙은 3이 중요한데요, 이걸 만약에 5로 바꾸면 0, 1, 2, 3, 4 이렇게 5가지 숫자 중에서 랜덤하게 골라집니다.


게임에 바로 적용하기 전에 연습을 한번 해봅시다. 슬라삐를 클릭하면 0, 1, 2 중에 하나가 출력되도록 아래처럼 수정해보세요.






잘 동작하는군요^^ 다음시간에는 랜덤 기법을 게임에 적용해보도록 하겠습니다.


감사합니다.


안녕하세요.


기존에는 슬라임이 죽었을때 버튼을 또 클릭하면 '이미 죽어있습니다' 메세지가 떴는데요, 이것을 아예 버튼이 클릭이 안되도록 수정해보겠습니다.


우선 메인클래스에서 btn1과 btn2를 static 전역변수로 수정한다음 휴먼 클래스로 가주세요.



// Human


btn1과 btn2는 J버튼 클래스를 통해서 만들어진 객체죠.


그 클래스에는 setEnabled라는 함수가 있는데 버튼의 활성화 유무를 결정합니다.


그 함수의 인수가 false라는 말은 비활성이라는 뜻이죠.




이렇게 슬라임이 죽으면 버튼이 비활성화되어 누를 수 없게 됩니다.



// Study01


배틀함수에 있던 '슬라임이 죽었는지 판단하는' if문은 이제 필요없으니 제거해줍시다.


감사합니다.


안녕하세요.



* 인간이 슬라임을 공격 -> 슬라임 이미지가 공격당하는 모습으로 바뀜 -> 일정시간 경과 -> 원래의 슬라임 이미지로 복귀



이제 이걸 해봐야겠죠?


사진은 아래 사진을 사용하겠습니다.



   


slime2.zip



주인공이 휘두르는 검이 화염검이라고 칩시다 ㅎㅎ












저번처럼 study.img폴더에 드래그하여 추가하시면 되겠습니다.




그 다음으로는 이렇게 이미지 라벨과 그 라벨에 그림으로서 들어갈 아이콘들을 전역변수로 선언해줍니다. 아래쪽에 선언된 부분은 삭제해줘야겠죠.


이제 휴먼 클래스로 가서 공격 함수를 수정해보도록 합시다.




빨간네모 부분이 추가한 부분입니다.


* 22~25행 : 해당 그림을 이미지아이콘 변수에 집어넣습니다. 그림에 불이 있기 때문에 변수명에 fire를 붙였습니다 ㅎ


* 27~31행 : 공격받은 슬라임이 bs1인지 아닌지 판단하여 그림을 설정합니다. 


* 39, 40행 : 일정시간 후에는 원래의 이미지로 되돌아갑니다.


* 46행 : 일정시간을 0.5초로 지정했습니다.




성공이군요^^


메인클래스의 코드 전문을 아래에 올려두겠습니다.


감사합니다.





안녕하세요.


이제 우리는 공격당하는 슬라임의 모습을 구현할 건데요, 그 과정을 순차적으로 설명하면 아래와 같습니다.



* 인간이 슬라임을 공격 -> 슬라임 이미지가 공격당하는 모습으로 바뀜 -> 일정시간 경과 -> 원래의 슬라임 이미지로 복귀



다른 부분은 구현하기 쉽지만 '일정시간 경과'는 타이머와 타이머 태스크에 대해 알고 있어야 구현이 가능합니다.


간단한 예제를 살펴봅시다.


콘솔창에 1이 출력된 다음 3초 후에 2가 출력되는 예제입니다.




(설명을 위해 간략화 했기 때문에 아직 정상실행은 안됩니다)


* 12행 : 먼저 1을 출력시킵니다.


* 14행 : 타이머 객체를 생성합니다. 타이머는 알람이라고 생각하시면 됩니다. 정해진 시간이 지나면 작업을 수행합니다.


* 15행 : 작업 객체를 생성합니다. = 우측에는 일정시간 후에 수행할 작업을 적으시면 되는데 특정한 형식에 맞춰서 적어야 합니다. 좀있다 설명드릴게요.


* 17행 : 타이머와 작업을 연결시키는 코드입니다. 스케쥴의 첫번째 인수는 수행할 작업, 두번째 인수는 얼마후에 작업을 수행할 건지를 적습니다. 밀리세컨드 단위이기 때문에 3000이 3초입니다.


이제 완성된 코드를 보시죠.





15행이 엄청 부피가 커졌네요^^; 세부적인 내용에 대해 설명하자면 상당히 난해하기 때문에 패스하구요(그래도 이해하고 싶은 분은 '익명클래스'로 검색하시면 됩니다), 수학공식 같이 정형화된 틀이라고 생각하시면 되겠습니다. run 함수 속의 내용만 잘 적으시면 잘 동작합니다^^


20행 : 콘솔창에 2를 출력합니다.


21행 : 타이머로서의 역할을 다 했으면 이렇게 꺼줘야합니다.


24행 : 중괄호 뒤에 세미콜론이 붙는게 이상해보이시겠지만 이 경우에는 꼭 적어주셔야 합니다.




1이 찍히고 3초 후에 2가 찍히면 성공~


다음시간에는 이번 시간에 배운 내용을 이용해서 공격당하는 슬라임을 구현해보겠습니다.


감사합니다.


안녕하세요.


이번 시간에는 사용자가 클릭한 슬라임이 블루슬라임인지 아닌지 판단하도록 코딩해보겠습니다.




122행을 해석하자면 '만약 s가 블루슬라임의 인스턴스라면'이 되겠네요.


인스턴스란? 클래스를 통해 만들어진 객체를 뜻합니다. 클래스도 넓은 의미로 보면 객체기 때문에 좁은 의미의 객체를 확실히 지칭하기 위해 인스턴스라는 말을 씁니다.




하지만 보시다시피 s객체의 함수 중에 heal은 보이지 않습니다.


s는 슬라임 클래스의 인스턴스이기 때문이죠.


해결방법은 아래와 같습니다.




변수 앞에다가 클래스명이 적힌 괄호를 붙여주면 해당 클래스로 형변환이 됩니다.

부모자식 관계만 서로 변환이 가능합니다.


그런데 말입니다.




사실은 s에 점찍었을때 나오는 목록 중에 맨밑에 보시면 heal이 있습니다^^ㅋ


선택을 하게 되면...




s를 알아서 형변환시켜서 heal 함수를 붙여주네요^^


아까의 두줄이 한줄로 합쳐진 형태입니다.



다음시간에는 댓글로 요청이 들어온 '슬라임이 공격을 당했을때 이미지가 바뀌는 것'을 진행해보도록 하겠습니다~


감사합니다.





안녕하세요.


블루슬라임 클래스는 다 만들었으니 이번엔 레드슬라임 클래스를 만들어보겠습니다.


블루슬라임 클래스 밑에다가 아래처럼 코딩해주세요.




레드슬라임은 다른 슬라임보다 공격력이 강하도록 설정했습니다.


이제 메인 클래스를 수정해줘야겠죠.




우선 클래스명과 변수명을 변경해줬습니다.


한가지 꿀팁을 알려드리자면 변수명에다가 커서를 두고 알트 + 시프트 + r을 누르면 동일한 변수의 이름을 한꺼번에 바꾸는게 가능합니다^^




레드슬라임이니까 슬라임 그림도 빨간색으로 바꿔줍니다^^




이번 강좌에서 핵심이 되는 부분입니다.


우선 110행을 보면 배틀함수의 인수가 BlueSlime이 아니라 Slime입니다. 왜냐하면 블루슬라임으로 하게되면 레드슬라임은 배틀함수의 적용을 받지 못하거든요. (빨간밑줄 생깁니다) 그래서 두종류의 슬라임의 부모인 슬라임으로 변경시킨거죠.


이번엔 빨간네모안의 if문을 보시죠. 배틀함수의 인수로 들어온 s가 블루슬라임일 수도 있고 레드슬라임일 수도 있기 때문에 if문으로 구분을 시켜놨습니다. 블루슬라임이면 치료함수를 수행하고 그밖의 경우(레드슬라임일 경우)에는 공격함수를 수행하도록 한거죠.




정상적으로 실행되는지 확인하시구요^^



그런데말입니다. 아래 그림을 다시 보시죠.




만약에 블루슬라임이 10마리고 레드슬라임이 1마리 있을때 위의 방식대로 하자면 if를 10번 사용해야되는 문제점에 봉착하게 됩니다. s를 객체와 비교하지 말고 클래스와 비교하는 방법은 없을까요? 이를테면,


if (s == BlueSlime)


이렇게 말이죠. 물론 이렇게 코딩하면 에러가 나지만 '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
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
// Slime.java
 
package study;
 
import javax.swing.JOptionPane;
 
class Slime {
 
    String name;
    int hp = 80;
 
    // 생성자
    public Slime(String n) {
 
        name = n;
 
    }
 
    // 공격
 
    public void attack(Human h) {
 
        if (hp > 0) {
 
            h.hp = h.hp - 10;
 
            if (h.hp < 1) {
                JOptionPane.showMessageDialog(null"Game Over");
                System.exit(0);
            }
 
            Study01.lbl2.setText(name + "의 공격. " + h.name + "의 체력은 " + h.hp + ".");
        }
 
    }
 
}
 
class BlueSlime extends Slime {
 
    // 생성자
    BlueSlime(String n) {
        super(n);
    }
 
    // 약한 공격
    @Override
    public void attack(Human h) {
 
        if (hp > 0) {
 
            h.hp = h.hp - 8;
 
            if (h.hp < 1) {
                JOptionPane.showMessageDialog(null"Game Over");
                System.exit(0);
            }
 
            Study01.lbl2.setText(name + "의 공격. " + h.name + "의 체력은 " + h.hp + ".");
        }
 
    }
 
    // 치료
    void heal(Slime s) {
 
        if (hp > 0 && s.hp > 0) {
 
            s.hp += 10;
 
            if (s.hp > 80) {
                s.hp = 80;
            }
 
            Study01.lbl2.setText(name + "는 " + s.name + "를 치료. 그의 체력은 " + s.hp + ".");
        }
    }
}

 

그런데 말입니다.

 

어택함수가 hp 감소 부분 말고는 동일하게 적혀있으니까 중복인 느낌이 많이들죠?

 

그래서 지난번에 배운 오버로딩 기법을 사용해서 중복을 제거해보도록 하겠습니다.

 

 

// Slime

 

위는 부모클래스인 슬라임 클래스입니다.

 

기존의 어택함수에다가는 데미지 인수를 추가하여 데미지만큼 체력이 감소하도록 했고, 데미지 인수가 없는 어택함수를 따로 하나 만들어뒀습니다.

 

이렇게 하면 어택함수를 호출할때 인수가 휴먼인수만 있으면 21행의 함수가 실행되겠죠. 그 함수가 실행되면 데미지 인수에 10을 넣어서 25행의 함수가 실행이 됩니다. 따라서 결과적으로 체력이 10이 깎이는거죠.

 

이게 블루슬라임 클래스와 무슨 관련이 있냐구요? 아래를 보시죠.

 

 

// BlueSlime

 

블루슬라임 클래스도 인수가 두개인 어택함수를 상속받아서 가지고 있습니다.

 

블루슬라임 클래스의 인수가 한개인 어택함수를 호출하면 데미지 인수에 8을 넣어서 인수가 두개인 어택함수가 호출이 되는 구조입니다^^

 

어택함수를 한줄로 줄이는데 성공했네요^^

 

감사합니다.

 

+ Recent posts