adsense



[JAVA/slick2d] 2D 슈팅게임 위치즈 스크램블 제작강좌 -step 11-

step 11. 적 캐릭터의 종류를 늘려보겠습니다.

추가할 것은 색상을 조금 붉게 바꾼 enemy0_1.png 입니다. 이녀석은 느리지만, 단단하고, 총알을 좀 더 많이 쏠 것입니다.
일단 편의상 Neuroi2라고 하겠습니다.


그런데, Bullet 클래스를 보면, 적과의 충돌을 체크하기 위해 checkHit에서 "NEUROI1" 모임을 얻어와 Neuroi1 클래스를 억세스하고 있는데요,
이 상태로는 적이 추가되면 그때마다 checkHit에 코드를 추가해줘야 합니다.
그렇게 하면 모처럼 캐릭터 한 종류 한 종류를 클래스화하여 코드 구조를 심플하게 바꿔준 보람이 없습니다.
이걸 코드를 늘리지 않고 해결하는 방법을 진행해보겠습니다.


checkHit에서 억세스하는 Neuroi1 클래스의 유니크한 부분은 setHit입니다. (rect는 GameObject 공통)
그렇다면 GameObject와 Neuroi1 사이에 setHit 함수를 포함한 중개 클래스-Enemy 클래스를 하나 만들어



Enemy는 GameObject를 상속하고


Neuroi1, Neuroi2는 Enemy 클래스를 상속하면,


Bullet 클래스의 checkHit에서 Neuroi1을 다루던 부분은

이와같은 식이 되어 적이 아무리 추가되더라도 checkHit의 코드를 더 이상 수정해 줄 필요가 없습니다.


Enemy 클래스는 GameObject를 상속한 추상 클래스로 만듭니다.

Image img 부터 Random rand까지, 적 클래스라면 공통으로 쓸만한 지역 변수도 모두 Enemy로 옮기고 권한을 protected로 변경합니다.


생성자 안에 this.name = "ENEMY"; 를 넣어, 별도로 name을 정의할 필요 없게 합니다.



그리고 setInit, setHit와 checkHit를 추상함수로 선언만 하고, 범용성에 맞춰 일부 인수를 수정합니다.


abstract public void setInit(float posX, float posY, int moving); <- 캐릭터의 종류에 따라 출발하는 x좌표가 다를 수도 있으므로 posX를 추가
abstract public int setHit(int damage, Player shooter);
abstract protected void checkHit(); <- checkHit는 private에서 protected로 변경.

마지막으로 Neuroi1이 상속해오는 클래스를 GameObject에서 Enemy로 변경하고
setInit의 인수를 수정, checkHit의 권한을 protected로 수정하면 됩니다.

그리고 GameScene에서 적 캐릭터를 생성하고 setInit를 호출해주는 부분에서, posX 인수가 추가되었으니 적당한 더미값을 넣어주고
setName은 모두 제거합니다.

여기까지 해서 잘 동작한다면 정상적으로 수정한 것입니다.



그럼 적 캐릭터를 추가해보겠습니다.
Enemy 클래스를 상속한 Neuroi2 클래스를 만듭니다.

Neuroi2의 시나리오는 다음과 같습니다/
- 붉은색을 띈 enemy0_1.png 이미지를 사용
- 최초 x좌표는 지정한 좌표로.
- 플레이어가 y좌표 240보다 위에 있으면 화면 아래에서, 아니면 화면위에서 등장 (step1)
- 천천히 움직여 위에서 나왔을 경우 y좌표 120, 아래에서 나왔을 경우 360에서 정지 (step2)
- 정지하면 느린 탄환을 나선형으로 뿌린다 : 반시계 방향으로 한 바퀴 빙 돌면서 쏜다. (step3)
- 탄환을 다 뿌리고 나면 가속하면서 화면 왼쪽으로 이동해 사라진다. (step4 - 실제로는 step5)
- 내구력은 10
- 득점은 100

Neuroi1의 내용을 복붙하고 Neuroi1을 모두 Neuroi2로 수정합니다.

- 붉은색을 띈 enemy0_1.png 이미지를 사용
: img를 얻어오는 곳에서 파일명을 enemy0_1.png로 수정

- 내구력은 10
: 변하지 않는 내용이므로 setInit에서 하드코딩. posX는 인수를 받아서 지정합니다.

- 플레이어가 y좌표 240보다 위에 있으면 화면 아래에서, 아니면 화면위에서 등장
: setInit에 moving 값으로 지정해 줄 수도 있지만 이것도 기본적으로는 Neuroi2 클래스에서 처리해야 합니다.

두 플레이어 중 어느 플레이어를 등장 기준으로 삼을지 정하고,
해당 플레이어의 위치를 보고 처음 나타날 장소와 이동할 각도를 정합니다. (스피드는 공통)
120에서 정지할지 360에서 정지할지, 나타날 장소와 함께 이것도 정해주고 (moving값으로 구분)




render는 Neuroi1과 완전히 같으니까 건드릴 부분이 없습니다.
이제 나머지 움직임 제어는 update에서 해 줍니다.

step 값에 따라 처리해 줄 내용이 다르니까, 보기좋게 switch를 사용해서 분기합니다.
switch에서 case문을 구술할 때는 break를 빼먹지 않도록 조심합니다. (의도적으로 break를 뺄 수도 있지만 흐름 추적을 위해서는 썩 좋은 방법은 아닙니다)



step==1 : y좌표가 120 또는 360 선을 넘으면 (float값에 삼각함수로 이동하기 때문에 딱 120, 360이 되지 않을 가능성이 높습니다) speed를 0으로 만들어 정지상태가 되고 step을 2로
step==2 : 이동이 끝났다고 바로 총알을 쏘기 시작하는게 아니고 약간의 딜레이를 줍니다. 끝나면 총알 발사 상태로.
step==3 : 총알을 쏘기 시작합니다. 4프레임마다 1발씩 쏘며, cnt가 1~180까지 카운트하는데 360 - cnt*2니까 358, 350, 342, (중략), 20, 14, 6 이런 각도로 총 45발을 발사하게 됩니다.
step==4 : 총알을 쏜 후 잠시 딜레이. 이후 움직임 방향을 왼쪽 직선 (degree=270)으로 정하고 step 5로 넘어갑니다.
step==5 : 조금씩 speed에 가속을 해서 왼쪽으로 이동해 사라집니다.


그리고 GameScene에서 적당히 등장시켜주면 됩니다.


이것으로 Bullet이나 Player 등에서는 별도로 추가 코딩해주지 않으면서 적 캐릭터를 추가하는 방법이 마련되었습니다.




그외에 추가적으로

- 플레이어의 임시 UI가 점멸하지 않게
- 플레이어가 공격받은 후에는 경직에서 풀리고 바로 공격받지 않게 1.5초 정도 무적 상태
- 플레이어 격추 시 폭연 이펙트를 추가하고 추락 궤도를 조금 수정

이런 부분들이 step 10과 달라져 있습니다.



핑백

덧글

  • 꾸벅 2016/01/17 14:02 # 삭제 답글

    포스팅 잘 보았습니다 자바나 c++관련으로 저런류의 게임을 만들어보고 싶은 마음만 있고 어떻게 해야되는질 몰랐는데 처음부터 자세히 써주셔서 감사합니다.
    포스팅 1번부터 보고 한번 따라해봐야겠네요ㅎㅎ
  • 펭귄대왕 2016/01/18 10:40 #

    많이 부족한 내용입니다만, 도움이 되면 좋겠습니다.
    혹시 보시다가 이해가 안되시는 부분이 있거든 최대한 답해드리도록 하겠습니다.
댓글 입력 영역


Books

Geek라이프

메가 드라이브 퍼펙트 카탈로그
마에다 히로유키 저/조기현 역

미소녀 일러스트 테크닉
B-은하, pen스케, 카와이 저/정유진 역

핵심강좌! Cocos2d-x
이재환 저

피규어의 교과서 레진 키트 & 도색 입문 편
후지타 시게토시 저/김정규 역
예스24 | 애드온2
일본서적 전문사이트 NEPIC