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


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.