모든 정적, 글로벌 디자인 패턴을 제거하고 싶지만 어떻게해야합니까?


11

우주에서 작은 던전 크롤러를 만들고 있는데 엔진의 백엔드를 더 멋지게 만드는 방법에 대한 조언을 듣고 싶습니다. 기본적으로 현재 모든 것은 많은 관리자를 기반으로합니다.

  • BackgroundManager : AddBackground(image, parallax)멋진 배경 효과를 만드는 방법이 있습니다.
  • ConfigManager : 구성 파일을 읽거나 작성하며 해당 구성 파일에서 읽은 데이터도 보유합니다.
  • DrawManager은 :이 Draw(sprite)화면에 물건을 그리는 방법을, 사물 좋아 SetView(view), GetView()
  • EntityManager : 모든 활성 엔티티를 보유하고 엔티티를 추가, 제거 및 찾기위한 메소드가 있습니다.
  • DungeonManager은 (실제로 GridManager이라고하지만, 이것은 단순성입니다) :이 방법처럼 GenerateDungeon(), PlaceEnemies(), PlaceFinish()

이제 모든 관리자를 반만 올리지 않았으므로 이것이 바뀌어야한다고 생각합니다. 내 게임은 또한 화면을 기반으로하므로 관리자가 관리하는 물건의 절반이 필요하지 않기 때문에 더 성가신 것입니다. 예를 들어 메인 메뉴 (주 메뉴에는 물리 / 엔티티 / 던전이 필요하지 않습니다 !)

이제 관리자를 정적이 아닌 것으로 만들고 ScreenMainGame에 모든 게임 관련 관리자의 인스턴스를 제공하는 것에 대해 생각했습니다. 그러나 그것은 관리자와 관련된 것을 전화하거나 가져 오는 것이 큰 혼란을 초래 ScreenMainGame.Draw()합니다.

((ScreenMainGame)ScreenManager.CurrentScreen).GridManager.Draw()

정말 못 생겼어

동료 게임 개발자 여러분,이 혼란을 해결하는 방법에 대한 아이디어가 있습니까? 감사하겠습니다!


어떻게 도와야할지 모르겠지만 디자인 패턴에 대한 좋은 책을 읽는 것이 좋습니다. 나는 Head First Design Patterns를 읽었으며 이해하기 매우 쉽습니다. 예제는 Java로되어 있지만 C #에 가깝기 때문에 도움이 될 것입니다. 내 제안이 너무 초보자라면 죄송합니다.
증폭 91

그래픽 카드와 인터페이스하기 위해 무엇을 사용하고 있습니까? XNA? SlimDX?
BlueRaja-대니 Pflughoeft

@BlueRaja : SFML.NET을 사용하고 있습니다.
Dlaor

이 경우 C #에서 이러한 문제를 처리하는 일반적인 방법을 간단히 사용해야합니다. 아래 마지막 링크와 종속성 주입이란 무엇입니까?
BlueRaja-대니 Pflughoeft

답변:


10

무엇에 대한 구성 요소 기반의 엔진 ?

당신은라는 메인 클래스 것 Engine목록을 유지하는 것, GameScreens자신의 목록을 보유 것이다 Components.

엔진은이 UpdateDraw방법 모두 호출 GameScreenUpdateDraw자신이 모든 구성 요소와 전화를 통해 이동 방법, UpdateDraw.

그렇게 발표하면, 나는 그것이 가난하고 반복적 인 디자인처럼 들린다는 데 동의합니다. 그러나 내 코드는 이전의 모든 관리자 클래스 보다 구성 요소 기반 접근 방식을 사용하여 훨씬 깨끗해졌습니다 .

큰 클래스 계층 구조를 거치고 BackgroundManager특정 배경을 모두 검색하지 않아도되므로 이러한 코드를 유지 관리하는 것이 훨씬 간단합니다 . 당신은 단지이 ScrollingBackground, ParallaxBackground, StaticBackground, 등에서 파생 된 모든 Background클래스입니다.

결국 자주 사용되는 많은 컴포넌트와 헬퍼 메소드 (예 : FrameRateDisplayer디버깅 유틸리티, Sprite벡터의 텍스처 및 확장 메소드가있는 기본 스프라이트 클래스)를 사용하여 모든 프로젝트를 재사용 할 수있는 매우 견고한 엔진을 구축하게됩니다. 및 난수 생성).

더 이상 BackgroundManager수업이 없지만 Background대신 스스로 관리 하는 수업이 있습니다.

게임이 시작되면 기본적으로 다음과 같이하면됩니다.

// when declaring variables:
Engine engine;

// when initializing:
engine = new Engine();
engine.Initialize();
engine.LoadContent();
engine.AddGameScreen(new MainMenuScreen());

// when updating:
engine.Update();

// when drawing:
engine.Draw();

이것이 게임 시작 코드입니다.

그런 다음 기본 메뉴 화면에서

class MainMenuScreen : MenuScreen // where MenuScreen derives from the GameScreen class
{
    const int ENEMY_COUNT = 10;

    StaticBackground background;
    Player player;
    List<Enemy> enemies;

    public override void Initialize()
    {
        background = new StaticBackground();
        player = new Player();
        enemies = new List<Enemy>();

        base.AddComponent(background); // defined within the GameScreen class
        base.AddComponent(player);
        for (int i = 0; i < ENEMY_COUNT; ++i)
        {
            Enemy newEnemy = new Enemy();
            enemies.Add(newEnemy);
            base.AddComponent(newEnemy);
        }
    }
}

당신은 일반적인 생각을 얻습니다.

또한 클래스 Engine내에서도 GameScreen새로운 화면을 추가 할 수 있도록 모든 클래스 내 에서 참조를 유지합니다 GameScreen(예 : 사용자가에서 게임 시작 버튼을 클릭하면으로 MainMenuScreen전환 할 수 있음 GameplayScreen).

Component클래스도 마찬가지입니다. 클래스의 부모에 대한 참조를 보유하고 클래스와 부모 에 GameScreen액세스하여 새 컴포넌트를 추가해야합니다 (예 : 컴포넌트와 컴포넌트 를 보유하는 HUD 관련 클래스를 만들 수 있음 ).EngineGameScreenDrawableButtonDrawableTextStaticBackground

"서비스 디자인 패턴"(정확한 이름은 확실하지 않음)과 같이 Engine클래스 내에 다른 유용한 서비스를 유지할 수있는 다른 디자인 패턴을 적용 할 수도 있습니다 (단순히의 목록을 유지하고 IService다른 클래스가 스스로 서비스를 추가하도록 함) ). 예를 들어 Camera2D다른 컴포넌트를 그릴 때 변환을 적용하는 서비스로 모든 프로젝트 의 컴포넌트를 유지합니다 . 이것은 어디서나 매개 변수로 전달하지 않아도됩니다.

결론적으로 엔진을위한 더 나은 디자인이있을 수 있지만 이 링크에서 제안한 엔진은 매우 우아하고 유지 관리가 쉽고 재사용이 가능 하다는 것을 알았습니다 . 나는 적어도 그것을 시도하는 것이 좋습니다.


1
XNA는 GameComponents 및 서비스 를 통해 즉시 사용 가능한 모든 기능을 지원 합니다. 별도의 Engine수업이 필요 없습니다 .
BlueRaja-대니 Pflughoeft

이 답변에 +1 또한 게임 업데이트 스레드와 별도의 스레드에 그림을 넣는 것이 합리적입니까?
f20k

1
@BlueRaja-DannyPflughoeft : 실제로 XNA가 사용되지 않았다고 가정했기 때문에 XNA를 사용하는 방법에 대해 조금 더 설명했습니다.
Jesse Emond

@ f20k : 예, XNA와 거의 같은 방식입니다. 그래도 어떻게 구현되는지 모르겠습니다. = / 인터넷 어딘가에 그것을하는 방법에 관한 기사가 있어야합니다. :)
Jesse Emond

예, XNA를 사용하지 않지만 이것은 내가하고있는 일에 대한 훌륭한 대안처럼 보입니다. 현재 다른 대안이 있는지 알아보기 위해 "헤드 우선 디자인 패턴"책을 읽고 있습니다. 건배!
Dlaor

1

코드를 구성 요소와 서비스로 분리하면됩니다. XNA는 이미 이러한 기능을 기본적으로 지원합니다.

참고 이 문서GameComponents서비스를. 그런 다음 XNA에서 서비스 사용에 대한 이 답변 과 모든 언어의 서비스에 대한 일반적인 답변 을 참조하십시오 .


-3

정적이거나 전역 적이라고해서 항상로드 / 초기화해야한다는 의미는 아닙니다. 싱글 톤 패턴을 사용하여 필요할 때 관리자를 자유롭게 해제하고 다시로드 할 수 있습니다.


4
싱글 톤은 OP가 여기서 해결하려고하는 근본적인 문제의 정면 일뿐입니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.