adsense



[JAVA(swing)] Legacy 2D 애니메이션

이번 포스팅은 2D게임에 적용할 수 있는 스프라이트 애니메이션을 구현하는 예제입니다.

요즘은 cocos2d-x나 유니티 등에서 강력한 애니메이션 기능이 제공되니 그쪽을 쓰면 됩니다만, 프로그래머로서 원리적인 부분을 이해해두면 좋지 않을까~라는 취지로, Legacy한 방법으로서 정리해 봅니다.

기존에는 상태를 판단해서 필요한 그림을 일일이 출력해주는 방법을 썼는데, 그림 매수가 많아질 경우 그런 방식으로는 코딩 분량이 늘어나고, 애니메이션에 강약의 변화를 주기 어려워집니다.

많은 매수의 그림을 좀 더 간편하게 처리하고, 프레임간 딜레이를 다르게 줌으로서 동작에 강약을 부여하도록 하겠습니다.



아래 파일을 다운받아주세요.
AnimationTest.zip

사용방법

이클립스에서 프로젝트 import 하여 불러들입니다. (안드로이드 아닌, 일반 자바 어플리케이션입니다)
자바 어플리케이션을 실행하면 화면 중앙에 레인저 캐릭터가 등장합니다.
키보드의 1, 2, 3, 4 키를 눌러 애니메이션을 변경할 수 있습니다. 5키를 눌러 좌우 방향을 바꿀 수 있습니다.
1-아이들링
2-걷기
3-공격 (공격 동작을 마치면 아이들링 상태로)
4-사망 (사망은 쓰러진 마지막 프레임을 유지)

화면을 출력하기 위한 부분들은 생략하고 (기존의 ASTEROID BELT에서 유용해 온 부분입니다) 애니메이션 제어 관련만 체크해 보겠습니다.

애니메이션을 위해서 알아야 할 것은
- 어떤 그림을 어떤 순서로 보여줘야 하는가
- 그림과 그림 사이에 시간 지연을 얼마나 줘야 하는가
이것은 ArrayList로 관리되고 있습니다.
frameList가 그림의 내용과 순서
frameDelay가 각 그림을 보여주는 시간

그리고 이걸 수행하기 위해
- 지금 몇 번째 프레임 상태인가
- 다음 프레임 전환을 위해 딜레이가 얼마나 남았는가
의 정보가 필요하고 nowFrame, nowDelay가 각각 이 역할을 위해 준비된 변수입니다.





애니메이션을 지정하는 함수(setIdle, selWalk, setAttack, setDead)를 보겠습니다.

1. frameList와 frameDelay를 클리어(이전에 생성된게 있을 수 있으니까)하고, 새롭게 목록을 생성합니다.
2. 애니메이션을 처음부터 보여주기 위해 nowFrame을 0으로, nowDelay에 frameDelay의 최초값을 넣어줍니다.
3. isRoof는 애니메이션이 무한루프인지, 1회만 보여주고 끝나는지 지정합니다.
4. nextAnimation은 1회로 끝날 경우 애니메이션이 끝난 후의 처리를 지정합니다. 무한루프라면 지정하지 않아도 무방합니다.



애니메이션의 진행은 process에서 수행됩니다. process는 스레드에서 불리므로 대략 1/60초에 한 번씩 호출됩니다.

우선
//애니메이션 정보 변경
부분을 봅니다.



nowDelay값을 1 감소시키고, 이 값이 0이라면 nowFrame을 1 증가시켜서 다음 프레임으로 넘어가게 됩니다.
그런데, 그 전에 프레임이 종료되었는가 - 종료되었다면 루프할 것인가, 다른 애니메이션을 부를 것인가, 아니면 마지막 프레임을 유지할 것인가를 판단합니다.
다음 프레임으로 넘어갔다면, nowDelay 값을 다음 프레임을 위한 지연값으로 갱신합니다.

이상의 과정으로 애니메이션을 처리할 수 있습니다.

그 앞에 있는
//상태변환 여부 확인
부분은 키를 눌러 애니메이션을 변경하거나 방향을 바꿀 경우 새 애니메이션을 호출하는 부분입니다.
이쪽은 그다지 설명할게 없으니 패스..


상태별 애니메이션은 각각 다음 특징이 있으므로, 어떤 식으로 지정하면 원하는 애니메이션이 되는지 확인할 수 있습니다.

아이들링 - 일정한 시간 간격으로 무한하게 반복되는 애니메이션
걷기 - 프레임마다 조금씩 다른 시간 간격으로 무한하게 반복되는 애니메이션
공격 - 프레임마다 조금씩 다른 시간 간격으로 1회만 전개하고 다른 상태로 전환하는 애니메이션
사망 - 일정한 시간 간격으로 1회 전개 후 유지하는 애니메이션


이번에는 게임의 메인 스레드에서 애니메이션을 처리했지만, 만약에 보여주는 캐릭터가 복수로 필요하게 되거나 하면 각 캐릭터를 클래스화하고 클래스에서 처리하도록 하면 됩니다. (Witches Flight 등을 참조해 주세요)

이번에 사용된 그림은 opengameart.org에서 가져왔으며, 저작권은 Calciumtrice에게 있고, 크리에이티브 커먼스 CC-BY 3.0를 준수하여 사용했습니다.
http://opengameart.org/content/animated-ranger

한 장의 시트에 그림이 모두 들어가 있는 형태인데, 각 그림이 별도의 이미지로 되어 있는 경우에는 거기 맞춰 이미지 불러오기/출력하기를 적용해주면 됩니다.


애니메이션에 따라서는 그림의 위치가 옮겨지거나, 복수의 그림을 조합해서 보여주거나 등의 경우도 있습니다만, 이번에는 여기까지. 읽어주셔서 감사합니다.

덧글

  • 하얀삼치 2015/05/18 10:30 # 답글

    늘 감사합니다.
  • 펭귄대왕 2015/05/18 11:25 #

    감사합니다
  • 알로하 2015/10/06 19:12 # 삭제 답글

    안녕하세요.. 정말 좋은 예제를 올리셨네요
    코드를 보다가 문득 든 생각인데요 예제에서는 케릭터가 한명만 움직이는 데요
    한번에 여러 케릭터를 따로 움직을 수도 있는지요..??
    따로 라 함은? 각 케릭터 모션마다 스프라이트도 작동하는데요 스프라이트도 케릭터 마다 따로 따로 움직이는 거죠
    괜찮으시다면 조언을 구하고 싶습니다.
  • 펭귄대왕 2015/10/07 11:06 #

    방문해주셔서 감사합니다.
    http://icegeo.egloos.com/306385
    코드가 난잡합니다만, 위 주소의 포스팅이 도움이 되지 않을까 합니다.
    여기서 중요한게 빠져있는데, 캐릭터가 그려지는 순번을 정해주지 않아서 더 앞으로 나와야 될 캐릭터가 뒤에 가린다던가 그런게 안되어 있습니다.
    이점은 따로 다루도록 해 보겠습니다.
댓글 입력 영역
* 비로그인 덧글의 IP 전체보기를 설정한 이글루입니다.


Books

Geek라이프

게임 매니악스 슈팅 게임 알고리즘
마츠우라 켄이치로,츠카사 유키 공저/손정도 역/박민근,Pope Kim 감수

게임 매니악스 퍼즐 게임 알고리즘
마츠우라 켄이치로,츠카사 유키 공저/김병국 역

만들면서 배우는 유니티 게임 프로그래밍
송용성 저

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

될 수 있어! SE 9
나츠미 코지 저/Ixy 그림/김경훈 역
예스24 | 애드온2