본문 바로가기
프로그래밍

How To XNA : 2. 비어있는 게임 화면과 구조

by 건우아빠유리남편 2009. 7. 14.
반응형

비어있는 게임 화면과 구조

Visual Studio 2005 또는 XNA Game Studio Express (이하 XGS)를 실행한다. 새로운 프로젝트를 만들고 Visual C#의 XNA Game Studio 2.0의 Windows Game (2.0) 템플릿을 선택하고 프로젝트를 생성한다. Xbox 360 Game (2.0) 프로젝트는 Xbox 360에서 실행 가능한 게임을 만드는 프로젝트이다. PC용 프로젝트나 Xbox 360용 프로젝트를 만들었다고 해도, 플랫폼간 서로 프로젝트를 복사할 수 있으니 일단은 PC용 프로젝트를 만들도록 한다.

 

프로젝트를 생성하면 소스 파일로서는 Game1.cs 파일과 Program.cs 파일이 생성되는데 게임 로직이 들어가는 파일은 Game1.cs 이다.

자동으로 생성된 Program.cs 파일을 살펴보도록 하자.

 

using System;
namespace WindowsGame1

{

 

게임은 프로젝트의 이름과 같은 네임스페이스를 가진다. 이 프로젝트의 이름은 WindowsGame1 이기 때문에 WindowsGame1 이라는 네임스페이스 안에 프로그램 코드가 생성되었다. 만약 프로젝트의 이름과 다른 네임스페이스를 가지고 싶은 경우에는 프로젝트 속성에서 응용프로그램 -> 기본 네임스페이스를 원하는 이름으로 바꾸기 바란다.

 

    static class Program
    {

 

XNA 게임은 프로그램이라는 클래스 내에서 생성이 된다.

 

        /// <summary>
        /// 응용 프로그램의 메인 진입점
        /// </summary>

        static void Main(string[] args)
        {
            using (Game1 game = new Game1())
            {
                game.Run();
            }
        }
    }
}

 

Program 클래스의 static Main 함수에서 Game1 클래스를 생성하고 Game1의 Run 함수를 실행한다.

Program.cs의 소스는 모두 보았으니 이번에는 Game1.cs를 살펴보도록 하자.

 

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

 

기본적인 System과 Generic 네임스페이스외에도 Microsoft.Xna.Framework 네임스페이스에 소속된 객체들을 참조한다. Microsoft.Xna.Framework 네임스페이스는 게임에서 필요한 타이머나 게임 루프등을 기본적으로 제공해주는 네임스페이스이다. 이 네임스페이스 내에는 절두체나 커브, 게임타임, 윈도우, 수학함수등의 클래스와 게임 컴포넌트에 관계된 인터페이스를 포함한다. Microsoft.Xna.Framework.Audio 네임스페이스는 XACT에서 제작된 컨텐츠 파일들을 로드하고 재생할 수 있는 저수준 API들을 제공한다. Microsoft.Xna.Framework.Content 네임스페이스에서는 컨텐츠 파이프라인에 대한 런타임 컴포넌트들을 제공하고 있으며 Microsoft.Xna.Framework.GamerServices 네임스페이스는 게이머들간의 커뮤니케이션이나 프로파일에 관계된 API들을 포함하고 있다. Microsoft.Xna.Framework.Graphics 네임스페이스는 2D, 3D 객체들을 화면상에 그리기위한 메쏘드들과 하드웨어 가속을 받기 위한 저수준 API들이 구현되어 있다. Microsoft.Xna.Framework.Input 네임스페이스는 키보드, 마우스, Xbox 360 컨트롤러의 입력을 받을 수 있는 클래스가 구현되어 있다. Microsoft.Xna.Framework.Net 네임스페이스는 Xbox LIVE, 멀티플레이어, XNA Framework 게임을 위한 네트워크의 지원을 담당하고 있으며 Microsoft.Xna.Framework.Storage 네임스페이스는 파일 입/출력을 담당한다.

이 외에도 서로의 타입들의 변환을 용이하게 해주는 Microsoft.Xna.Framework.Design이라는 네임스페이스와 Microsoft.Xna.Framework.Graphics.PackedVector 네임스페이스가 있다.

 

namespace WindowsGame1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

 

Microsoft.Xna.Framework.Game클래스를 상속받은 Game1 클래스는 두 개의 맴버 변수를 가진다. GraphicsDeviceManager 클래스인 graphics 맴버 변수는 말 그대로 그래픽 디바이스에 관한 설정을 할 수 있다. spriteBatch 맴버변수는 스프라이트들을 한번에 그리기 위해 사용되는 클래스이다. 그래픽을 표현하기 위해 이 두 맴버 변수는 빈번하게 사용되므로 반드시 기억해두도록 하자.

 

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

 

Game1 클래스의 생성자는 두 가지 작업을 한다. 맴버변수인 graphics에 GraphicsDeviceManager를 새로 할당하고, Asset(자산-자원)을 관리하는 컨텐츠매니저의 디렉토리를 "Content"로 설정한다. 컨텐츠 매니저를 이용해 로드하는 모든 리소스들은 프로젝트폴더의 Content를 기본 위치로 검색하여 로드하게 된다.

 

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            base.Initialize();
        }

 

Initialize() 함수는 맴버변수들에게 메모리를 할당하거나, 컴포넌트를 초기화 하는 일을 한다. 현재 단계계에서는 아직 GraphicDeviceManager가 초기화 되지 않았으므로 리소스를 로드하거나 GraphicsDeviceManager 클래스를 사용하는 맴버들을 초기화하지 않도록 한다. 코드의 끝에서 호출하는 base.Initialize(); 를 빼먹으면 컴포넌트들이 초기화하지 못하는 경우가 생기므로 반드시 호출하도록 한다.

 

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            // TODO: use this.Content to load your game content here
        }

 

LoadContent() 함수에서는 리소스와 컨텐츠들을 로드한다. XNA에서 말하는 컨텐츠란 그래픽 리소스를 포함한 게임 내에서 쓰이는 모든 외부 자원들을 말한다. 여기에는 사운드, 이펙트, 스크립트 파일들이 당연히 포함된다. 앞서 만들었던 spriteBatch 맴버 변수에 GraphicsDevice를 인자로 제공하여 메모리를 할당한다. GraphicsDevice는 Game 클래스가 가진 GraphicsDeviceManager의 GraphicsDevice 맴버의 프로퍼티이다. GraphicsDeviceManager는 Initailize() 함수를 거치면서 초기화 되므로 이 함수부터는 마음껏 사용해도 된다.

 

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

 

UnloadContent()는 게임이 종료되면서 자원을 해제해야 하는 경우 직접 사용한다. 기본적으로 제공되는 컨텐츠를 사용할 경우 컨텐츠 매니저가 알아서 자원의 해제를 해주지만 반드시 해제 코드가 들어가야 하는 리소스를 로드했다면 여기에 해제 코드를 삽입해주도록 하자.

 

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>

        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

 

게임이 매 프레임마다 갱신될때 로직상으로 해줘야하는 일 들은 Update() 함수안에 위치하게 된다. Update() 함수로 전달되는 인자는 GameTime인데 GameTime은 전체 게임  시간과 현재 프레임의 게임 시간이 들어있으므로 애니메이션을 비롯한 다양한 작업을 하는데 이용될 수 있다. Update() 함수는 기본적으로 플레이어1의 Back 버튼이 눌러졌을 경우 게임을 종료(아예 프로그램을 종료해버린다)하는 코드가 들어있으며 함수의 마지막에 있는 base.Update(gameTime); 함수를 빼먹는다면 컴포넌트들의 Update() 함수는 불려지지 않을 것이다.

 

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>

        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            // TODO: Add your drawing code here
            base.Draw(gameTime);
        }
    }
}

 

마지막으로, Draw() 인데 함수명이 말해주듯이 그리기를 위한 코드가 이 함수에 위치하게 된다. graphics.GraphicsDevice.Clear() 함수는 화면 전체를 특정 색상으로 지워버린다. 매 프레임마다 Clear() 함수를 호출해주지 않는다면 지금까지 그린 것들이 화면에 남게 될 것이다. 그러니 매 프레임마다 Clear() 함수를 꼭 호출해주는 것이 좋다. 다른 합수들과 마찬가지로 base.Draw(gameTime); 함수를 빼먹는다면 다른 컴포넌트들의 Draw 함수가 불려지지 않게될 것이다.


글쓴이 링크 : http://www.gfc3.net/xna/ 

반응형

댓글