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


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:Behavior과DuckBehavior: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.