발사 애니메이션과 총알 릴리스를 묶는 방법


15

총알을 발사 할 때 생기는 애니메이션이 있다고 가정하겠습니다. 애니메이션이 끝날 때 총알이 어떻게 표시됩니까? 내가 알아낼 수있는 유일한 것은 애니메이션의 시간 길이를 알고 총알 위치 설정을 지연시키고 해당 시간이 지날 때까지 활성화하는 것입니다. 이것이 최선의 접근 방법인지 궁금합니다. 다른 사람들이 어떻게 이것을 처리합니까?

편집 : 질문을 올바르게 표현하는 데 문제가 있다고 생각합니다.

내 질문


감사! 여러분 모두의 많은 좋은 아이디어, 저는 콜백을 사용하는 아이디어를 좋아합니다. 나는 그것을 시도하고 구현 할 것이라고 생각한다. 나는 정말로 시간 추적에 의존하고 싶지 않았다.
tp0w3rn

답변:


8

근본적으로 당신은 올바른 길을 가고 있습니다-이런 종류의 일을하기 위해 애니메이션이 얼마나 오래 지속되는지 알아야합니다. 애니메이션은 단순한 프레임 모음이 아니라 필요한 모든 종류의 다른 정보가 있습니다. 예를 들어 얼마나 많은 프레임이 있고 애니메이션 루프가 얼마나 빨리 재생됩니까 (예 : 초당 10 개의 애니메이션 프레임 또는 25 또는 60?). 모든 애니메이션은 몇 가지 데이터로 정의 할 수 있으며, 일부 일반화 된 애니메이션 코드는보고 재생할 수 있습니다. 애니메이션 부분을 자체 코드 비트로 캡슐화해야합니다. 이러한 애니메이션 정의와 개별 이미지 프레임을 표시하는 방법 외에는 아무것도 알지 못합니다. 즉,로드, 재생 시작, 재생 중지 및 화면의 특정 위치에서 렌더링하도록 지시 할 수있는 애니메이션 개체가 있어야합니다.

유연한 접근 방식은 일종의 애니메이션 정의를 사용하여 이러한 종류의 정보를 캡슐화하는 것입니다. 따라서 "애니메이션 X는이 프레임들 전부입니다. 프레임을 통해 재생하십시오"라고 말하는 것이 아니라 좀 더 복잡한 것을 얻게됩니다.

예를 들어 일종의 모형 데이터 형식

애니메이션 =
{
  {name = "walk", files = "walk * .png", frameCount = "12", loop = "true"},
  {name = "fire"files = "fire * .png"frameCount = "6",
       이벤트 = {
           {name = "bulletLeavesGun", frame = "4", param1 = "43", param2 = "30"}
       }
  }
}

따라서 코드는 다음과 같이 말합니다.

currentAnimation = animations.Get("fire");
currentAnimation.Play();

이벤트를 감지하는 방법은 다시 호출하는 애니메이션 코드 (예 : 애니메이션이 특정 프레임에서 재생되어 새 이벤트를 감지 한 경우 새 이벤트에 대해 알려주기 위해 게임 코드를 호출 함)를 사용하거나 다음과 같은 애니메이션 :

List<Event> events = currentAnimation.EventsSinceLastCheck();
foreach (AnimationEvent event in events)
{
    if (event.name == "bulletLeavesGun")
    {
        Vector2 bulletPosition = new Vector2(event.param1, event.param2);
        Vector2 actualBulletPosition = new Vector2(
                 character.x + bulletPosition.x, 
                 character.y + bulletPosition.y);
        CreateBulletAt(actualBulletPosition);
    }
}

참고 사항 :

  • 애니메이션 코드는 게임 코드와 별도로 존재해야합니다. 게임 플레이 코드가 애니메이션 재생의 기본 요소에 너무 밀접하게 묶여있는 것을 원하지 않습니다.
  • 애니메이션 코드는 애니메이션 정의에 따라 루프할지 여부를 알고 있습니다
  • 애니메이션 코드는 애니메이션이 언제 완료되는지 알고 다른 코드를 호출하여 '이봐, "불"이라는 애니메이션이 끝났습니다. 지금 무엇을하고 싶습니까? "
  • 애니메이션 코드는 이름과 관련된 임의의 데이터 (param1 및 param2) 이외의 이벤트에 대해 아무것도 모릅니다.
  • 애니메이션 코드는 현재 켜져있는 프레임을 알고 있으며 새 프레임으로 변경되면 '오, 지금 프레임 4에 있습니다. 즉,'fire '라는 이벤트가 발생했다는 것을 의미합니다. 내가 최근에 한 사건 목록을보고 물어 보는 사람에게 말할 수 있습니다. '

애니메이션 내에서 총알 발사가 필요하지 않지만 일단 완료되면 이벤트 개념없이 훨씬 덜 복잡한 시스템으로 도망 갈 수 있습니다. 그러나 애니메이션이 자체적으로 재생되고 시간이 얼마인지 알고 애니메이션이 완료되면 게임 코드를 다시 호출 할 수있는 시스템이 여전히 필요합니다.


논리 인식 애니메이션을 유지하는 데 동의하지 않습니다 (현재 프레임 4에서 "fire"라는이 이벤트가 발생했음을 의미합니다). 애니메이션은 맹목적이고 멍청해야합니다. 서버 측 로직과 애니메이션을 찢어 야했고 게임에서 UI를 다시 사용하고 싶지 않습니다. 매우 짧고 세그먼트 화 된 애니메이션을 사용하는 것이 좋습니다. 로직과 병렬로 재생하면 로직이 로직에 의해 정의 된 속도로 애니메이션 시퀀스를 트리거 할 수 있습니다. 애니메이션 상태에 대한 로직 테스트를하지 마십시오.
코요테

애니메이션을 여러 조각으로 나누는 것은 매우 불필요한 것 같습니다. 애니메이션 상태를 폴링하지 않는 데 동의하지만 여전히 첫 번째 권장 사항이 남습니다. 그가 게임의 나머지 부분 (관찰자 패턴?)에서 애니메이션 코드를 분리하기 위해 별도의 이벤트 시스템을 의미했는지는 모르겠지만 그렇게하는 방법입니다. "논리"는 애니메이션 코드에 대해 알지 못하며 그 반대도 마찬가지입니다.
jhocking

@Coyote 나는 두 가지를 섞고 있다고 말하고 싶습니다. 예, 서버 측 로직은 항상 시각적 요소와 독립적이어야합니다 (탄환 발생시 알아 내기 위해 애니메이션 시스템을 실행하지 않아도되므로). 클라이언트에서 애니메이션 시스템을 구축하는 데 도움이되지는 않습니다. . 클라이언트에서는 비주얼이 서버에 무의식적으로 노예화되는 것을 원하지 않습니다. 왜냐하면 게임과 서버 사이에 시차가 발생하여 총알이 이상한 시간에 나타나고 캐릭터와 동기화되지 않기 때문입니다. . 당신이 둘 다 가질 수있는 이유는 없습니다 (계속 ...)
MrCranky

@Coyote (계속), 게임 플레이는 비주얼에서 분리 된 서버에 의해 구동 될 수 있습니다. 따라서 총알은 서버에서 X 시간에 시작되고 클라이언트는 총알 게임 플레이 시뮬레이션 뒤에 몇 프레임 지연되는 총알 발사 시각으로 발사 애니메이션을 즉시 재생하여 해당 작업을 미러링합니다. 시각적 충실도와 게임 플레이 시뮬레이션 간에는 모든 종류의 타협이 이루어져야합니다. 따라서 "애니메이션은 맹목적이고 멍청해야합니다"라고 말하면됩니다. 이벤트를 애니메이션 프레임에 연결해야하는 경우가 있습니다. 다른 방법으로는 이벤트를 올바르게 표시하거나 소리로 만들 수 없기 때문입니다.
MrCranky

@Coyote 사실 지금 생각합니다. 총알 발사는 이것에 대한 끔찍한 예입니다. 주로 아래의 thedaian의 답변 때문입니다. 발사는 곧바로 이루어져야합니다. 더 좋은 예는 캐릭터가 착륙 할 때 먼지 VFX가 발생하는 것입니다. 서버와 클라이언트는 캐릭터가 점프하기 시작할 때 동기화하지만 시각적 표시는 클라이언트에게 맡겨집니다. 애니메이션이 발이지면에 닿는 오른쪽 프레임에 닿으면 VFX 이벤트가 발생합니다. 마찬가지로, 특정 애니메이션 프레임에서 다른 애니메이션으로 분기할지 여부를 결정해야하는 경우 이벤트가 필요합니다.
MrCranky

3

어떤 식 으로든 애니메이션이 완료 될 때까지 기다렸다가 해당 지점에서 글 머리 기호를 만들어야합니다.

애니메이션 속도가 고정되어 있다면 타이머를 설정하기 만하면됩니다. 약간의 변형으로, 총알 내부에 코드가 나타나서 보이지 않고 잠시 나타나서 움직일 수 있습니다.

개발 플랫폼에 따라, 애니메이션이 원하는 지점에 도달하는 순간을 정확하게 응답 할 수있는 일종의 애니메이션 업데이트 기능 또는 콜백이있을 수 있습니다. 예를 들어 Flixel을 사용하는 방법입니다.


1
Flixel의 addAnimationCallback방법은 소성 엔티티에서 사용될 수 있습니다. 콜백 함수에서, 발사 애니메이션의 현재 프레임이 글 머리 기호 엔티티를 생성해야하는 프레임인지 확인할 수 있습니다. 그렇다면 화면에 글 머리 기호를 추가 할 수 있습니다.
스노우 블라인드

2

정답 : 플레이어가 '화재'버튼을 눌렀을 때 재생하고 싶은 애니메이션이 있고 재생이 완료된 후 총알이 나오고 있다고 가정합니다. 이상적으로는 애니메이션 시간을 하드 코딩하지 말고 애니메이션이 완료 될 때 (플랫폼에 따라 콜백 함수 등을 사용하여) 글 머리 기호를 발사해야합니다. 지나치게 복잡하지 않은 다른 방법으로는 생각할 수 없습니다.

대체 게임 디자인 답변 : 실제로, 정말 좋은 이유가 없다면, 'fire'버튼을 누르고 총알이 나타나는 것을 지연시키지 않을 것입니다. 애니메이션이 실제로 짧지 않으면 (기본적으로 1 ~ 2 프레임, 최대, 기본적으로 총구 플래시) 발사 버튼 응답이 느리게 느껴지고 일반적인 플레이어에게는 성가 시게됩니다. 글 머리 기호가 나오기 전에 애니메이션을 사용하기로 결정한 경우에도 (턴 기반 RPG 및 전술 게임이이를 허용 할만한 이유가 될 수 있음) "어딘가에 애니메이션 끄기"옵션을 포함하여 플레이어가 원하는 경우 더 빠르게 움직입니다.


예, 화재가 천천히 반응하지 않도록하십시오. 이것은 점프와 관련된 일반적인 문제와 같습니다. 애니메이터는 큰 바람을 일으킨다. 그러나 플레이어는 버튼을 누르 자마자 공수를 기대한다.
jhocking

2

MrCranky가 말했듯이; 애니메이션과 논리를 분리하십시오.

그러나 가장 중요한 것은 논리가 마스터 부분으로 남아 있어야한다는 것 입니다.

  • 발사 버튼을 누르면 캐릭터의 상태 (로직)에서 드로우 " 액션 "을 트리거해야합니다 .
  • 이 조치는 모든 매개 변수 (사용 시간 등)를 사용 하여 그리기 애니메이션 을 트리거해야합니다 .
  • 드로우 액션 이 완료 되면 발사 액션을 시작할 수 있습니다 (무기에 따라 한 번 이상 발사 될 수 있음)
  • 이 액션은 총알을 생성하고 화재 애니메이션을 트리거 할 수 있습니다 .

로직에서 UI를 제어하는 ​​것이 나중에 로직을 유지, 재사용 및 공유 할 수있는 유일한 방법입니다 (렌더러가없는 새 렌더러, 새 게임, 서버 버전 ...).


1

먼저 이벤트 시스템 (관찰자 패턴?)을 사용하여 코드 조각을 분리합니다. 이것은 애니메이션에만 국한된 것이 아니라 확실히 적용됩니다. 그런 다음 애니메이션 코드는 dispatchEvent (event)라고 간단히 말할 수 있으며 코드의 다른 부분은 코드의 어느 부분도 서로를 알 필요없이 해당 이벤트를 수신합니다.

이제 애니메이션 코드에는 실제로 이벤트 디스패처에 대한 참조가 필요하며 (종속성 주입으로 쉽게 수행됨) 실제로 애니메이션을 정의하는 XML 또는 JSON이 필요합니다. 다음과 같은 것 :

{
  animation: {
    name: shoot,
    length: 12,
    spritesheet: shoot.png
    event: {
      frame: 4,
      name: bulletLeavesGun,
    },
  },
}

애니메이션을로드 할 때 데이터를 읽고 재생 중에 해당 프레임에있을 때 애니메이션 코드가 이벤트를 전달하도록합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.