monogame 프레임워크는 현재는 MS사의
지원이 중단된 XBOX 360 게임을 개발하기 위해
서드파티에게 배포하던 SDK 인 XNA를
(SDK - 소프트웨어 개발 도구)
오픈소스 커뮤니티에서 크로스플랫폼으로
확장한 것이며 MS가 시작한 프로젝트답게
.NET Core 플랫폼의 C#을 사용합니다.
여기서 크로스 플랫폼이란 우선 다양한
운영체제를 사용할 수 있다는 것이고
(MAC OS, WINDOWS, LINUX)
PC를 비롯한 다양한 콘솔에서 실행가능한
게임을 개발할 수 있다는 뜻 입니다.
(PS4, XBOX ONE 등)
윈도우에서 monogame 개발 환경의 설치는
아래의 문서를 참고합니다.
Mac OS나 Linux의 경우 monogame 웹사이트의
Getting Started 문서를 참고하도록 합니다.
Visual Studio Code 에서 monogame 설치하기 - C# 게임개발 환경 (tistory.com)
*비주얼 스튜디오는 2019버전에서
확장기능을 통하여 설치가 가능합니다.
현재 비주얼 스튜디오 2022 버전을
사용한다면 마켓플레이스에 업데이트가
되기 전에는 비주얼 스튜디오 코드를
사용하는 것을 추천합니다.
monogame의 dotnet 템플릿을 설치하고
명령프롬프트에서 dotnet new --list 를 입력하면
Game 으로 시작되는 다양한 템플릿을 볼 수 있습니다.
(MonoGame 태그)
여기에는 안드로이드용, 아이폰용, 윈도우 데스크탑,
크로스플랫폼 데스크탑 등이 있습니다.
첫번째 템플릿은 크로스 플랫폼 데스크탑으로
만들어 보겠습니다. 약식명이 mgdesktopgl 입니다.
.NET CLI 를 사용할 것 입니다. 프로젝트 이름은
폴더이름이자 namespace 이름이 됩니다.
dotnet new mgdesktopgl -o 프로젝트이름
기본 와꾸가 설치되는데 다른 프레임워크들처럼
알아서 여러가지 파일이 셋업이 됩니다.
소스코드는 두개의 파일이 있습니다.
Game1.cs는 게임 로직이 들어가는 곳이고
Program.cs는 Main() 함수가 들어가는 시작점입니다.
처음부터 이것들을 다 세밀하게 들여다보진 않을 겁니다.
처음에는 전체적으로 이런 구조이다-
정도로 이해하고 하나씩 실습을
하면서 개별 필드와 메소드의 의미를
알아가는 것이 좀 수월할 수 있습니다.
monogame은 OOP(객체지향프로그래밍)로
개발된 프레임워크입니다. OOP로 만든
게임프레임워크는 비슷한 방식도 많은데
게임루프(GameLoop) 로직이 클래스로
구현되어 있습니다.
게임루프는 게임 로직의 기본입니다.
1. 초기화 (initialize)
2. 로드 (LoadContent)
3. 업데이트 (Update)
4. 드로우(Draw)
5. 언로드(UnloadContent)
6. 끝맺음(Finalize)
우리가 게임을 시작할 때 초기화와 로드가
발생하고 게임 실행이 준비가 됩니다.
그 다음에 3-4번의 업데이트와 드로우가
무한루프를 돌면서 게임이 진행됩니다.
사용자가 게임을 종료할 때까지
프로그램은 이 안에 있습니다.
게임을 종료하면 5-6 종료 과정이
진행되고 운영체제로 복귀합니다.
(큰 게임에서는 다음 스테이지를 위해
현재의 Asset을 unload 하기도 한다)
세부적인 구조는 게임마다 다르겠지만
모든 게임이 이 안에 있다고 해도
과언이 아닙니다. 게임루프가 하는일은
끝날 때까지 업데이트와 드로우를 하는 겁니다.
너무 추상적이긴 한데 게임의 개념은 그렇습니다.
게임의 엄청난 중독성은 사용자가 종료 명령을
실행하기 전까지 영원히 업데이트와
드로우를 할 수 있기 때문입니다.
온라인게임은 서버를 24시간 켜놓으니까
어떤면에서는 반영구적인 것이라 볼 수도 있지요.
가장 핵심되는 내용이 이 코드에 다 들어가 있습니다.
물론 프레임워크가 알아서 여러가지를 해줍니다.
프로그래머는 여기서부터 시작하면 됩니다.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace TestProject
{
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
*대략적 설명
코드를 대략 설명하면 using 에서 MS의
XNA 라이브러리를 갖다가 씁니다.
네임스페이스가 Microsoft.Xna.Framework 입니다.
XNA에 기반한 코드를 사용하기에
개발자는 더 쉽게 GPU와 Audio 자원을
사용할 수 있습니다.
(XNA는 MS사에서 2013년에 지원종료 후
Monogame 에서 오픈소스화 하였다.
나중에는 MS사가 Monogame을 가져다가
윈도우8의 게임을 만들기도 했다.)
[monogame과 XNA의 관계]
monogame 는 XNA 프로젝트를
오픈소스 크로스 플랫폼으로
포팅하며 시작되었습니다.
원래 MS사에서 자사의 운영체제인
윈도우즈와 콘솔게임인 XBOX 플랫폼에서
사용할 목적으로 개발하였으나
이것의 범위를 넓힌 것 입니다.
따라서 지금도 Xna의 namespace를
그대로 유지하는 전통이 남아있습니다.
기존 XNA 유저들에 대한 배려이기도 하고
MSDN 문서들을 그대로 사용할 수 있습니다.
monogame 을 사용하면서 상위 클래스인
Xna 의 namespace 들도 사용하게 될 것 입니다.
Microsoft.Xna.Framework Namespace | Microsoft Docs
Game 클래스를 상속하는 Game1
클래스가 정의되어 있습니다.
GraphicsDeviceManager 는 말그대로
그래픽 장치를 조작하기 위한 클래스 변수입니다.
스프라이트는 게임내 애니메이션을
구현하는 요소입니다. (SpriteBatch)
Game1 생성자는 윈도우에 그리기위해
필요한 요소들을 셋업합니다.
Initialize 는 초기화 코드입니다.
초기화는 한번 실행됩니다.
LoadContent는 게임에서 사용할 콘텐트,
리소스들을 로드합니다.
Update 는 게임 로직이 들어갑니다.
예를 들어 슈팅게임에서 적의 총알이
플레이어 캐릭터와 충돌하면
체력을 깎거나 게임오버가 되는 등
상태를 업데이트 합니다.
초당 60프레임이면 1초에 60번
실행되는 것으로 상당히 부드럽게 느낄 수 있지요.
Draw는 Update에 따라 변경된 그림을
다시 그려줍니다. 배경부터 캐릭터 스프라이트의
이동까지 모든 것을 그려줍니다.
퉁쳐서 이야기하면 게임은 update 와
draw(render)가 전부입니다.
게임루프의 흥미로운 점이지요.
- 처음에는 개별 메소드의 하는 일만
알고 있어도 충분합니다.
하나씩 게임의 기능을 만들 것 이니까요.
* Program.cs는 Game1 클래스를 생성하고
실행합니다. 이 부분은 그냥 놔두면 됩니다.
using System;
namespace TestProject
{
public static class Program
{
[STAThread]
static void Main()
{
using (var game = new Game1())
game.Run();
}
}
}
초기화 Initialize()에 다음을 추가합니다.
_graphics 는 그래픽장치 관리자
인스턴스입니다.
...Width가 너비 ...Height가 높이입니다.
protected override void Initialize()
{
base.Initialize();
_graphics.PreferredBackBufferWidth = 800;
_graphics.PreferredBackBufferHeight = 600;
_graphics.ApplyChanges();
}
GraphicsDevice.Clear(Color.Beige); 에서
Color.색상 에 여러가지 배경색을 선택할 수 있습니다.
Visual Studio Code 에서 Tab 키를 누르면
다양한 색상을 선택할 수 있습니다.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Beige);
base.Draw(gameTime);
}
구글에 뒤져보면 monogame에 관한 자료는
생각보다 많지 않더군요.
해외나 한글자료나 마찬가지 입니다.
monogame 은 2D 게임쪽에 강점이 있는데
C#을 쓴다면 해외쪽도 유니티가 대세이고
C++에 강력한 SDL 라이브러리가 있으니
굳이 .NET 에서 monogame이
메리트가 떨어지는게 아닌가 생각이 듭니다.
MS가 윈도우만을 위해 소프트웨어를
개발하던 시절의 프로젝트들은 그다지
생명력이 떨어지는 것 같습니다.
오픈소스 커뮤니티에서 살아남은
프로젝트 들이 오래가는 것 같네요.
이게 앞으로는 어떻게 될지 모르겠지만...
윈도우 환경에서 간단한 앱을 만들기에는
C#이 쉽게 되어 있는데 하드웨어를
완전하게 제어해야 하는 게임 프레임워크에는
역시 C++이 더 효과적인게 아닌가...
.NET 공부하는 김에 궁굼해서
조금 건드려보는 수준입니다.