게임을위한 행동 / 컴포넌트 기반 시스템 만들기


11

배경

저는 취미로 게임 개발을하고 있으며, 더 나은 방법으로 게임을 디자인하고 있습니다. 현재 표준 OOP 접근 방식을 사용하고 있습니다 (8 년 동안 엔터프라이즈 개발을 해왔 기 때문에 실제로 적용됩니다). 예를 들어 "바디"

public class Baddie:AnimatedSprite //(or StaticSprite if needed, which inherit Sprite)
{
    //sprite base will have things like what texture to use, 
    //what the current position is, the base Update/Draw/GetInput methods, etc..
    //an AnimatedSprite contains helpers to animated the player while 
    //a StaticSprite is just one that will draw whatever texture is there
}

문제

2d 플랫 포머를 만들고 있는데 점프 할 수 있으려면 baddie가 필요합니다. 일반적으로 내가하는 일은 Update / GetInput 메소드에 적절한 코드를 추가하는 것입니다. 그런 다음 플레이어를 크롤링, 오리, 등산 등으로 만들어야하는 경우 코드가 이동합니다.

주의하지 않으면 해당 메소드가 복잡 해져서 이와 같은 메소드 쌍을 작성하게됩니다.

CheckForJumpAction(Input input)DoJump()

CheckforDuckAction(Input input)DoDuck()

따라서 GetInput은

public void DoInput(Input input)
{
    CheckForJumpAction(input);
    CheckForDuckAction(input);
}

업데이트는 다음과 같습니다

public void Update()
{
    DoJump();
    DoDuck();
}

나가서 플레이어가 뛰어 내려야하는 다른 게임을 만들면 보통 기능이있는 게임에 들어가서 복사합니다. 지저분하다. 그게 내가 더 좋은 것을 찾는 이유입니다.

해결책?

Blend에 요소에 첨부 할 수있는 동작이있는 방식이 정말 좋습니다. 내 게임에서 같은 개념을 사용하는 것에 대해 생각하고 있습니다. 동일한 예를 살펴 보겠습니다.

기본 동작 객체를 생성합니다

public class Behavior
{
    public void Update()
    Public void GetInput()
}

그리고 그것을 사용하여 행동을 만들 수 있습니다. JumpBehavior:BehaviorDuckBehavior:Behavior

그런 다음 Sprite베이스에 동작 컬렉션을 추가하고 각 엔티티에 필요한 것을 추가 할 수 있습니다.

public class Baddie:AnimatedSprite
{
    public Baddie()
    {
        this.behaviors = new Behavior[2];
        this.behaviors[0] = new JumpBehavior();
        //etc...
    }

    public void Update()
    {
        //behaviors.update
    }

    public GetInput()
    {
        //behaviors.getinput
    }
}

많은 게임에서 Jump and Duck을 사용하고 싶을 경우, 그 동작을 그대로 적용 할 수 있습니다. 일반적인 라이브러리를 만들 수도 있습니다.

작동합니까?

내가 알 수없는 것은 그들 사이에 상태를 공유하는 방법입니다. 점프와 덕을 보면 둘 다 그려지는 텍스처의 현재 부분뿐만 아니라 플레이어의 상태에도 영향을줍니다. (점프는 시간이 지남에 따라 증가하는 양의 상향 힘을 가할 것이고 오리는 움직임을 멈추고 질감과 바디의 충돌 크기를 변경하려고합니다.

이걸 어떻게 묶어서 작동시킬 수 있습니까? 동작 사이에 종속성 속성을 만들어야합니까? 각 행동 에 부모에 대해 알고 직접 수정해야합니까? 내가 생각한 한 가지는 트리거 될 때 실행되도록 각 동작에 대리자를 전달할 수 있다는 것입니다.

나는 더 많은 문제를 찾고 있다고 확신하지만, 전체 목적은 게임과 동일한 게임의 엔티티 사이에서 이러한 동작을 쉽게 재사용 할 수 있도록하는 것입니다.

그래서 나는 그것을 당신에게 넘깁니다. 이것이 어떻게 / 가능한지를 설명 할 수 있습니까? 더 좋은 아이디어가 있습니까? 나는 모두 귀입니다.


이것은 gamedev.stackexchange.com 에서 더 잘 물어볼 수 있습니까?
rcapote

나는 당신이 가고있는 곳을 좋아하지만 당신이 제기 한 문제를 해결하는 방법을 모르겠습니다. 매우 흥미롭고 게임 개발 이상의 의미를 지닙니다.
Edward Strange

@rcapote는 화이트 보드 / 토론을 위해이 사이트가 아닙니까?

2
@ 조-아니, 아니 여기에서 "토론"을 언급하지 않으면 존재하지 않을 수 있습니다. 이 사이트는 질문-> 답변-> 완료 유형의 상호 작용에만 해당됩니다.
Edward Strange

글쎄, 컴포넌트 기반 엔터티 시스템은 최근 게임 개발 커뮤니티에서 트렌드를 시작한 것이므로 더 관심을 끌 것이라 생각했지만 어쨌든 좋은 대답을 얻을 것입니다. gamedev.net에서 흥미로울만한이 문제에 대한 흥미로운 토론이 있습니다 : gamedev.net/topic/…
rcapote

답변:


1

프리젠 테이션을 살펴보십시오 . 찾고있는 패턴과 매우 비슷합니다. 이 패턴은 동작 및 첨부 가능한 속성을 지원합니다. 프레젠테이션에서 언급하지는 않지만 첨부 가능한 이벤트를 만들 수도 있습니다. 이 아이디어는 WPF에서 사용되는 종속성 속성과 비슷합니다.


9

나에게 이것은 전략 패턴 을 사용하는 거의 교과서 사례처럼 들린다 . 이 패턴에서, 일반적인 행동은 인터페이스에서 정의 될 수 있습니다. 인터페이스에서 당신은 캐릭터의 점프 또는 달리기 능력에 어떻게 파워 업이 영향을 미치는지에 대해 생각할 수 있습니다.

(생각 된) 예를 들어 :

// The basic definition of the jump behavior
public interface IJumpBehavior {
    void Jump();
}

이제 각 특정 점프에 대한 세부 사항을 몰라도 캐릭터가 사용할 수있는 다양한 유형의 점프를 구현할 수 있습니다.

// This is the jump the character may have when first starting
public class NormalJump : IJumpBehavior {

     public void Jump() {
         Console.WriteLine("I am jumping, and being pretty boring about it!");
     }

}

// This is the jump of a character who has consumed a power-up
public class SuperJump : IJumpBehavior {
    public void Jump() { 
         Console.WriteLine("I am all hopped up on star power, now my jumps can do damage!");
     }
}

점프 할 수있는 캐릭터는 이제 IJumpable에 대한 참조를 포함 할 수 있으며 다양한 구현을 소비 할 수 있습니다

public class HeroCharacter {

    // By default this hero can perform normal jump.
    private IJumpBehavior _jumpBehavior = new NormalJump();

    public void Jump() {
        _jumpBehvaior.Jump();
    }

    // If you want to change the hero's IJumpable at runtime
    public void SetJump(IJumpBehavior jumpBehavior) {
      _jumpBehavior = jumpBehavior;
    }

}

그러면 코드가 다음과 같이 보일 수 있습니다.

HeroCharacter myHero = new HeroCharacer();

// Outputs: "I am jumping, and being pretty boring about it!"
myHero.Jump()

// After consuming a power-up
myHero.SetJump(new SuperJump());

// Outputs: "I am all hopped up on star power, now my jumps can do damage!"
myHero.Jump();

이제 이러한 동작을 쉽게 재사용하거나 나중에 더 많은 유형의 점프를 추가하거나 단일 사이드 스크롤링 플랫폼을 기반으로 더 많은 게임을 만들 때이를 확장 할 수 있습니다.


내가 찾고있는 것이 아니지만, 이것은 매우 가깝고 좋아합니다. 나는 그것을 가지고 놀려고합니다. 감사!

1

DCI 아키텍처를 살펴보면 도움이 될 수있는 OO 프로그래밍에 대한 흥미로운 정보를 얻을 수 있습니다.

C #에서 DCI 스타일 아키텍처를 구현하려면 간단한 도메인 클래스를 사용하고 확장 메소드 및 인터페이스와 함께 컨텍스트 오브젝트 (동작)를 사용하여 도메인 클래스가 다른 역할 하에서 협업 할 수 있어야합니다. 인터페이스는 시나리오에 필요한 역할을 표시하는 데 사용됩니다. 도메인 클래스는 의도 한 동작에 적용되는 인터페이스 (역할)를 구현합니다. 역할 간 협업은 컨텍스트 (행동) 오브젝트에서 발생합니다.

별도의 프로젝트에서 도메인 개체간에 공유 할 수있는 일반적인 동작 및 역할 라이브러리를 만들 수 있습니다.

C # 의 코드 예제는 C #의 DCI를 참조하십시오 .


0

컨텍스트 객체를 비헤이비어에 전달하여 비헤이비어의 영향을받는 스프라이트 / 오브젝트의 상태를 변경하는 방법을 제공하는 것은 어떻습니까? 이제 개체에 여러 가지 동작이있는 경우 각각 루프에서 호출되어 컨텍스트를 변경할 수있는 기회를 제공합니다. 속성의 특정 수정이 다른 속성의 수정을 제외 / 제한하는 경우 컨텍스트 개체는이 사실을 나타 내기 위해 일종의 플래그를 설정하는 메서드를 제공하거나 원치 않는 수정을 거부 할 수 있습니다.

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