MonoGame #3 – pierwszy sprite na ekranie

Mam już poprawnie skonfigurowany projekt MonoGame, który mogę bez problemów testować na emulatorze. Czas zacząć coś tworzyć!Po utworzeniu projektu dostajemy na start klasę, która dziedziczy po klasie Game. Jest to punkt wyjściowy naszej aplikacji i to tutaj wprawiamy tryby naszej gry w ruch. Framework przewiduje kilka domyślnych metod, które opisują to co dzieje się w naszym programie:

  • Konstruktor naszej klasy gry (u mnie zmyślnie nazwana Game1)
  • Initialize czyli moment, w którym robimy wszystko to co potrzebujemy przed startem gry (uwaga, do ładowania zasobów jest inna metoda)
  • LoadContent to odpowiednia chwila na załadowanie wszelkich danych związanych z grą, tj. grafiki, mapy, poziomy. Należy wyraźnie rozróżnić ją od wyżej wspomnianej Initialize, która służy do ładowania naszego silnika gry, konfiguracji i innych parametrów.
  • UnloadContent posłuży nam do usuwania zasobów i zwalniania pamięci
  • Update jest wykonywana w każdej klatce i służy do aktualizacji stanu (logicznego) gry
  • Draw służy do rysowania na ekranie naszej aplikacji

Czyli porównując do XNA, koncept został ten sam i z mojego punktu widzenia – bardzo dobrze. Każda metoda odpowiada za oddzielny moment cyklu życia gry, co pozwala zachować porządek w kodzie.

W kolejnym kroku spróbuję napisać minimalną ilość kodu, która pozwoli mi wyświetlić Sprite czyli obrazek) na ekranie. Tworzę więc w oddzielnym pliku klasę Actor. Bardzo cenię sobie koncept, w którym wszelkie obiekty na scenie są rozumiane jako aktorzy. Pozwala wprowadzić to ład w toku myślenia, a przy okazji daje solidny pomysł na stosowane w kodzie nazwy obiektów i metod.


using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MonoAndroid.src
{
	public class Actor
	{
		private Texture2D _sprite;
		private Vector2 _position;

		public Actor(Texture2D sprite)
		{
			_sprite = sprite;
			_position = new Vector2(50, 50);
		}

		public void Draw(SpriteBatch batch)
		{
			batch.Draw(_sprite, _position, null, Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0f);
		}
	}

}

Wiele parametrów takich jak pozycja na ekranie, kolor czy skala ustawiłem na szybko z losowymi wartościami, gdyż tak jak wspomniałem wcześniej, miała być to minimalna działająca wersja.

Następnie wracam do głównej klasy gry i tworzę w niej pole typu Actor o nazwie… _actor.
W metodzie służącej do inicjalizacji gry (Initialize) tworzę nowy obiekt aktora:

_actor = new Actor(Content.Load<Texture2D>("Sprites\\Hero"));

Tworząc pierwszego aktora podaję ścieżkę do obrazka, który chcemy wyświetlić. Umieszczam go więc w projekcie pod zadaną ścieżką:

monogame_3_3

Pozostaje mi jeszcze rozkazać Mono by mój aktor był odrysowywany na ekranie w każdej klatce:

protected override void Draw(GameTime gameTime)
{
	GraphicsDevice.Clear(Color.CornflowerBlue);

	_spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp);
	_actor.Draw(_spriteBatch);
	_spriteBatch.End();

	base.Draw(gameTime);
}

SpriteBatch służy do wyświetlania sprite’ów na ekranie. Warto zwrócić uwagę na fakt, że ustawiłem próbkowanie na punktowe (PointClamp) żeby uniknąć automatycznego wygładzania grafiki pikselowej. Pierwsze dwa argumenty metody Begin to po prostu wartości domyślne.
W efekcie nasz aktor pojawia się na ekranie po uruchomieniu (Deploy) aplikacji:

monogame_3_2

No i jest. Nie jest to najpiękniejszy kod pod Słońce, ale działa. W kolejnej części postaram się to wszystko poukładać w bardziej zmyślny sposób. 🙂