MonoGame
MonoGame 3.8 · DesktopGL · C# / .NET
먼저 문장 하나를 화면에 표시해 보세요. 이 작은 예제는 실제 항구 내보내기 파일을 직접 읽으며, 완전한 대화 재생기는 아닙니다. 이후 데이터를 게임 UI에 연결하세요.
1 · 파일 및 장면 준비
MonoGame DesktopGL 프로젝트로 시작하세요. story.json을 Content/에 넣고 출력 폴더에 원본 파일로 복사하도록 설정하세요. 아래 프로젝트 설정을 참고하세요. Game1에 ReadWelcome을 추가하세요. Content Pipeline Tool에서 DialogueFont라는 SpriteFont를 만들고 콘텐츠를 빌드한 뒤 다음 코드로 불러오세요: Content.Load
2 · 첫 번째 텍스트 표시
<ItemGroup>
<None Update="Content/story.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>Game1에 SpriteFont _dialogueFont;와 string _dialogueLine = ""; 필드를 추가하세요. LoadContent에서 사용할 코드: _dialogueFont = Content.Load
// Game1.cs: add using System.IO; using System.Text.Json; using System.Text;
// Place this method inside the existing Game1 class.
private string ReadWelcome(string locale)
{
using var stream = TitleContainer.OpenStream("Content/story.json");
using var document = JsonDocument.Parse(stream);
var content = document.RootElement.GetProperty("content");
const string id = "fd7b61a3-8233-4ba7-8f77-b88b119a91bf";
var message = content.GetProperty("texts").GetProperty(id).GetProperty("sourceMessage");
if (content.GetProperty("translations").TryGetProperty(locale, out var table)
&& table.TryGetProperty(id, out var translation))
message = translation.GetProperty("message");
var line = new StringBuilder();
foreach (var segment in message.GetProperty("segments").EnumerateArray())
{
if (segment.GetProperty("kind").GetString() != "text")
throw new InvalidDataException("Text-only example");
line.Append(segment.GetProperty("text").GetString());
}
return line.ToString();
}예상 출력은 “Welcome to the harbour. I am Mira.”입니다. locale = "de" 또는 언어 매개변수 de를 사용하면 “Willkommen im Hafen. Ich bin Mira.”가 표시됩니다. 없는 언어는 원문을 사용합니다. 이 예제는 텍스트 세그먼트를 지원하며, 자리표시자를 알림 없이 무시하지 않습니다.
3 · 한 문장에서 대화
위의 고정 텍스트 ID는 첫 번째 테스트용입니다. 게임에서는 story-index.json에서 flowRef/entryRef를 선택하고 execution.entries[entryRef].nodeRef, 이어서 execution.nodes[nodeRef]를 읽으세요. 현재 대화 노드는 text.textRef와 speakerRef를 제공합니다. 다음 진행 방식은 노드 종류에 따라 달라집니다.
이름과 대사는 Begin/End 사이에서 SpriteBatch.DrawString으로 그립니다. 긴 텍스트의 줄바꿈과 글꼴이 지원하는 문자를 확인하세요. 답변 영역과 마우스 및 키보드 입력은 게임에서 구현하며 번역된 텍스트 대신 ID를 유지합니다. End에서는 Game.Exit()가 아닌 dialogueOpen = false로 표시와 입력을 끄세요.
- Continue와 End: 연결을 따라 진행하고 대화창 닫기
- 선택지: 답변 ID, 표시 순서, 선택한 답변의 다음 진행
- 조건과 변수: 10 또는 2 골드
- 언어: 같은 ID로 새 언어의 콘텐츠 가져오기
- 명령: 아이템을 주고 가게를 엽니다.
- Call/Return: 하위 이야기로 이동했다가 돌아오기
이 프로그래밍 언어로 답변과 금화 검사 살펴보기
선택지 데이터 읽기
로딩 후 story를 사용할 수 있는 위치에 이 코드를 넣으세요. RPG Maker에서는 const story = $gameTemp.vnleExample.story;를 사용합니다. 확인용으로 ID를 출력하며, 실제 게임에서는 이 출력을 답변 버튼으로 바꾸세요. 항구의 두 답변과 이후 금화 검사를 다루는 예제일 뿐, 범용 해석기는 아닙니다.
// Inside ReadWelcome while document is alive; inspect data before returning.
var nodes = document.RootElement.GetProperty("execution").GetProperty("nodes");
var choice = nodes.GetProperty("42edfff8-b8fe-46bf-ae0d-9e2347b6e726");
foreach (var idToken in choice.GetProperty("optionOrder").EnumerateArray())
{
string optionId = idToken.GetString();
var option = choice.GetProperty("options").GetProperty(optionId);
System.Console.WriteLine(optionId + " " + option.GetProperty("text").GetProperty("textRef").GetString());
}
var branch = nodes.GetProperty("c1c3c372-0a73-4cd0-851d-ede59d5709bb");
int gold = 10; // Repeat with 2.
int minimum = branch.GetProperty("condition").GetProperty("right").GetProperty("value").GetProperty("value").GetInt32();
var next = branch.GetProperty(gold >= minimum ? "whenTrue" : "whenFalse");
System.Console.WriteLine(next.GetProperty("nodeRef").GetString());
// Copy strings/values you need later before disposing JsonDocument.금화가 10개이면 next는 “Pay five gold”, 2개이면 “Not enough gold”를 가리킵니다. 실제 게임에서는 선택한 경로가 이 노드에 도달했을 때만 검사하세요. 각 답변은 자신의 다음 진행 정보를 제공합니다.
4 · 자신의 이미지 연결하기
이 추가 예제는 현재 대화 객체 node와 주석에 적힌 UI 요소가 있다고 가정합니다. C++와 MonoGame에서는 speakerRef를 이미 SpeakerId 또는 speakerId로 읽은 상태입니다. 키는 미라의 실제 캐릭터 ID이며, 이미지 이름과 위치는 게임에서 정합니다. 표시된 위치에 코드를 넣으세요.
// Game1 class field, so both LoadContent and Draw can access it:
private readonly System.Collections.Generic.Dictionary<string, Texture2D> portraits = new();
// Inside LoadContent(): import/build mira.png as portraits/mira.
portraits["807b2957-7bab-4a28-83a4-1f3d1589bbc2"] = Content.Load<Texture2D>("portraits/mira");
// Inside a SpriteBatch Begin/End in Draw; speakerId comes from speakerRef:
if (portraits.TryGetValue(speakerId, out var portrait))
_spriteBatch.Draw(portrait, new Vector2(24, 120), Color.White);화자 이름도 대사처럼 content.characters[speakerRef].nameTextRef로 구하세요. 이미지 연결이 없으면 이전 초상화를 숨기거나 대체 이미지를 표시하세요. 이미지는 언어에 따라 선택되지 않습니다.
5 · 게임과 함께 파일 배포하기
이 예제에서는 JSON을 Content.Load로 읽지 마세요. TitleContainer가 원본 파일을 열며 csproj가 파일을 복사합니다. SpriteFont와 텍스처는 Content Pipeline으로 빌드하세요. 먼저 DesktopGL에서 사용하고 다른 플랫폼은 별도로 확인하세요.
결과 확인
- 영어와 독일어 인사말이 올바르게 표시되고, 사용할 수 없는 언어를 선택하면 영어 원문이 표시되어야 합니다.
- 진행 로직을 추가했다면 두 답변, 금화 10개와 2개, 하위 이야기에서 돌아오기, End를 시험하세요.
- 빌드한 게임을 프로젝트 폴더 밖에서 실행하세요. JSON, 글꼴, 초상화가 그곳에서도 제공되어야 합니다.
공식 문서
API 및 이 접근 방식을 위한 설정 참조: