게임 전체 변수를 저장하는 가장 좋은 방법


23

난이도, 해상도, 전체 화면 등과 같은 옵션 화면이 있지만 런타임에 이러한 변수를 저장 / 취득하는 "최상의"방법을 찾는 데 어려움을 겪고 있습니다.

현재 Constants모든 GameOption열거 형 이 포함 된 클래스를 구현 했지만 이러한 모든 옵션의 기본값을 어떻게 선택합니까? 또한 현재 선택된 열거 형을 얻는 방법은 무엇입니까?

해상도와 관련하여 특히 값을 저장하기로 결정했지만 기본값 또는 현재 저장된 값을 얻는 방법을 잘 모르겠습니다. 어떤 방향 으로든 좋을 것입니다. 감사! :)

namespace V1.test.RPG
{
  public class GameOptions
  {
    public enum Difficulty { EASY, MEDIUM, HARD }
    public enum Sound { ON, QUIET, OFF }
    public enum Music { ON, QUIET, OFF }
    public enum ResolutionWidth
    {
        SMALL      = 1280,
        MEDIUM     = 1366,
        LARGE      = 1920,
        WIDESCREEN = 2560
    }
    public enum ResolutionHeight
    {
        SMALL      = 800,
        MEDIUM     = 768,
        LARGE      = 1080,
        WIDESCREEN = 1080
    }
    public Boolean fullScreen = false;
  }
}

NB : 나는 SO에게 물었고 그들은 이곳을 가리켰다. 거기에 의견이 있지만 다른 방법으로 / 가장 많이 사용되는 방법을 듣고 싶습니다.


1
당신은 바로 이곳에서 물었습니다. 당신을 보낸 사람은 착각했습니다 어쨌든 당신을 돕기 위해 질문에 대답했지만 이것은 게임 개발 관련 질문이 아니며 일반적인 프로그래밍 질문입니다.
jhocking

방금 SO 스레드를 읽었습니다. Scott Chamberlin의 답변이 마음에 듭니다.
jhocking

@ jhocking 나는 일반적인 응용 프로그램과 다를 수있는 게임 개발과 관련된 측면이있는 경우를 대비하여 그를 지적했습니다. 또한이 주제에 대해 일반적인 질문과 대답이 이미있을 수 있다고 생각합니다.
Chris Hayes

지구본에 대한 실제 질문과는 달리, 고정 된 해결책이 있다고 가정하지 마십시오.
Lars Viklund

답변:


32

성장 계획 :
하드 코딩 된 상수는 소규모 프로젝트에 적합하지만 결국 소프트웨어 크기가 커짐에 따라 모든 것을 다시 컴파일하지 않고도 해당 설정을 변경할 수 있기를 바랍니다. 게임이 실행되는 동안 설정을 변경하고 싶을 때가 많으며 하드 코딩 된 상수로는 그렇게 할 수 없습니다.

CVars :
프로젝트가 성장하면, 당신은 한 번 봐 걸릴 수도 있습니다 CVARs을 . CVAR은 "스마트 변수"이므로 런타임 중에 콘솔, 터미널 또는 UI를 통해 수정할 수 있습니다. CVAR은 일반적으로 기본 값을 래핑하는 객체 측면에서 구현됩니다. 그러면 객체는 값을 추적하고 파일에 저장하거나 파일에서로드 할 수 있습니다. CVAR 오브젝트를 맵에 저장하여 이름 또는 다른 고유 ID로 액세스 할 수 있습니다.

개념을 조금 더 설명하기 위해 다음 의사 코드는 int값 을 래핑하는 CVAR 유형의 간단한 예입니다 .

// just some flags to exemplify:
enum CVarFlags {
    CVAR_PERSISTENT, // saved to file once app exits
    CVAR_VOLATILE    // never saved to file
};

class CVar {
public:
    // the constructor registers this variable with the global list of CVars
    CVar(string name, int value, int defaultValue, int flags);

    int getValue();
    void setValue(int v);
    void reset(); // reset to the default value

    // etcetera...

private:
    int flags; // flags like: save-to-file, etc.
    int value; // the actual value
    int defaultValue; // the default value to reset the variable to
};

// global list of all CVars:
map<string, CVar> g_cvars;

전역 접근 :
위의 예에서,의 생성자는 CVar항상 전역 cvars지도에 변수를 등록 한다고 가정했습니다 . 변수를 다음과 같이 선언 할 수 있으므로 매우 유용합니다.

CVar my_var = new CVar("my_var", 0, 42, CVAR_PERSISTENT);

해당 변수는 전역지도에서 자동으로 제공되며 변수 이름으로지도를 색인화하여 다른 곳에서 액세스 할 수 있습니다.

CVar v = g_cvars.find("my_var");

지속성 :
게임이 종료되면 맵을 반복하고로 표시된 모든 변수 CVAR_PERSISTENT를 파일에 저장합니다. 다음에 게임을 시작할 때 다시로드하십시오.

판례법 :
강력한 CVAR 시스템에 대한보다 구체적인 예는 Doom 3 에 나와있는 구현을 확인하십시오 .


4

그럼 먼저 값이 무엇인지 열거를 정의 해제 할 수 있습니다 , 값이없는 것 입니다 . 따라서 열거 형을 선언 한 후에도 다른 변수를 선언해야합니다. 예를 들면 다음과 같습니다.

public enum Sound
{
    ON,
    QUIET,
    OFF
}

public Sound soundValue;

이 예에서는 이제 soundValueON, QUIET 또는 OFF로 설정할 수 있습니다 .


그런 다음 코드의 다른 부분이이 "설정"개체에 액세스 할 수 있도록 코드를 구성해야합니다. 그 부분에 대한 도움이 필요한지 모르겠지만이 문제를 해결하는 일반적인 패턴에는 싱글 톤 (요즘에는 찌그러짐) 또는 서비스 로케이터 또는 종속성 주입이 포함됩니다.


1

glampert 솔루션은 매우 완벽하지만 개인적인 경험을 추가 할 것입니다.

나는이 같은 문제에 부딪 쳤고, 나의 해결책은 정적 변수 클래스를 사용하는 것이 었습니다.

Variables 클래스는 내부적으로 맵을 문자열에서 문자열로 유지합니다 (지금까지는 모든 변수가 문자열 임). getter 및 setter를 통해 액세스합니다.

요점은 전역 변수에 액세스하면 코드의 전혀 관련이없는 부분이 갑자기 서로 간섭하기 때문에 모든 종류의 미묘한 오류가 발생할 수 있다는 것입니다.

이를 피하기 위해 다음과 같은 의미를 부과했습니다. set해당 이름의 변수가 사전에 이미 있으면 메서드를 사용하면 예외가 발생하고 get반환하기 전에 사전에서 변수를 삭제합니다.

두 개의 추가 방법은 당신이 무엇을 기대 제공 setAndOverwrite하고 getAndKeep. 다른 방법의 의미론의 요점은 "이 방법은이 변수를 초기화해야하지만 다른 방법은 이전에 수행 한"종류의 오류를 쉽게 발견 할 수 있다는 것입니다.

사전을 초기화하기 위해 초기 변수는 json 파일에 저장되고 게임이 시작될 때 읽 힙니다.

슬프게도 아직 게임에 너무 멀지 않아서이 접근법의 견고성을 증언 할 수 없습니다. 여전히 CVAR 외에 흥미로운 것을 제공 할 수도 있습니다.

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