1. Przygotowanie aplikacji

Szczawik

1 Wstęp
2 Tworzenie nowej aplikacji
          2.1 SharpDevelop
          2.2 Visual C#
3 Dodawanie referencji
4 Edycja kodu
5 Całość kodu źródłowego

Wstęp

Większość aplikacji, wykorzystujących do prezentacji interfejsu użytkownika, zamiast klasycznych kontrolek, wyłącznie DirectX, ma podobną budowę: korzysta z jednej formy, która jest miejscem docelowym renderowanego obrazu w trybie okienkowym lub pełnoekranowym.

Podczas ładowania tego okna inicjuje interfejs Direct3D, a reagując na zdarzenie odmalowania renderuje - a więc przetwarza na podstawie przestrzeni 2D lub 3D na obraz dwuwymiarowy. Dodatkowo - jeśli jest to aplikacji dynamiczna, nieustannie renderująca obraz - po odmalowaniu żąda ponownego odmalowania.

Przykłady niniejszego kursu będą oparte o szkielet aplikacji Windows Forms Application (Microsoft Visual C# 2008 Express Edition) lub C# → Aplikacja Windows (SharpDevelop 2.2.1). Warto zaznaczyć, że SharpDevelop podsiada dodatkowo zdefiniowany szkielet C# → Aplikacja Direct3D, jednak podczas tego kursu przedstawiona zostanie aplikacja tworzona od zera.

Początkowo kurs miał być przygotowany wyłącznie z myślą o tym środowisku, jednak - w związku ze znaczną przewagą oprogramowania firmy Microsoft w łatwości debugowania aplikacji - oba środowiska będą brane pod uwagę.

Tworzenie nowej aplikacji

SharpDevelop

Z menu głównego wybierz Plik → Nowy.. → Rozwiązanie.., a następnie utwórz projekt C# → Aplikacje Windows → Aplikacja Windows. Wybierz nazwę dla projektu - na przykład Kurs1, podaj ścieżkę i naciśnij Utwórz.

Visual C#

Z menu głównego wybierz File → New project, a następnie utwórz projekt Windows Forms Application. Wybierz nazwę dla projektu - na przykład Kurs1, podaj ścieżkę i naciśnij Utwórz.

Dodawanie referencji

W nowo stworzonej aplikacji wybierz z menu głównego Projekt → Dodaj referencję..; wybierz pliki:

  • Microsoft.DirectX,
  • Microsoft.DirectX.Direct3D,
  • Microsoft.DirectX.Direct3DX.
    Ostatni z plików nie jest niezbędny w pierwszych lekcjach kursu, jednak jego dodanie nie będzie stanowiło żadnego utrudnienia również na początku.

Edycja kodu

Na górze pliku z kodem tworzenia okna (SharpDevelop: MainForm.cs, Visual C#: Form1.cs) dodaj dwie kolejne przestrzenie nazw w następujący sposób:

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

Dla zachowania przejrzystości kodu, całość funkcjonalności będzie umieszczona w osobnej klasie. W istniejącej przestrzeni nazw (namespace), pod istniejącą klasą, opisującą okno, dodaj nową klasę o następującej budowie:

public class TDirectX
{
	private Device device;
	private Control parent;

	/// <summary>
	/// Konstruktor obiektu obsługującego DirectX
	/// </summary>
	/// <param name="parent">Okno, które będzie celem renderowania grafiki</param>
	/// <param name="windowed">W oknie (true) czy pełnoekranowo (false)?</param>
	public TDirectX(Control parent, bool windowed)
	{
		this.parent = parent;
		Initialize();
	}

	/// <summary>
	/// Tworzenie wszystkich elementów sceny
	/// </summary>
	private void Initialize()
	{
	}

	/// <summary>
	/// Wykonanie renderowania
	/// </summary>
	/// <param name="time">Czas działania aplikacji</param>
	public void Render(float time)
	{
	}
}

W klasie okna natomiast będzie potrzebne pole prywatne typu powyżej zdefiniowanej klasy: TDirectX directx. Dodatkowo należy dodać obsługę zdarzeń Load oraz Paint. Można to zrobić standardowo - automatycznie, przez panel właściwości formy, albo ręcznie, jak pokazano poniżej. W obu zdarzeniach należy umieścić dodatkowo odpowiedni kod (SharpDevelop: MainForm, Visual C#: Form1):

public partial class MainForm : Form
{
	private TDirectX directx;
	private int startTickCount = Environment.TickCount;

	public MainForm()
	{
		InitializeComponent();

		//Dwie poniższe linie konieczne tylko, gdy nie użyto panelu właściwości
		Load += new System.EventHandler(MainFormLoad);
		Paint += new System.Windows.Forms.PaintEventHandler(MainFormPaint);
		//
	}
		
	void MainFormLoad(object sender, EventArgs e)
	{
		SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
		directx = new TDirectX(this, true);
	}

	void MainFormPaint(object sender, PaintEventArgs e)
	{
		if (directx != null)
		{
			directx.Render(Environment.TickCount - startTickCount);
		}
		Invalidate();
	}
}

Ustawienie stylu (SetStyle) zapobiega migotaniu okna podczas odmalowywania przez renderowanie. Metoda Invalidate po dokonaniu odmalowania żąda wykonania kolejnego odmalowania, dzięki czemu aplikacja będzie mogła nieustannie renderować bieżący obraz sceny.

Całość kodu szkieletu aplikacji została umieszczona poniżej. Kod jest gotowy do skompilowania, choć w efekcie uruchomienia powinno pokazać się okno bez odmalowanego tła. Nie wykorzystuje jeszcze DirectX, ale już w pełni pozwala na używanie jego funkcji i definiowanie zmiennych dostępnych w nim typów.

Od tego momentu będziemy zajmowali się jedynie rozbudową klasy TDirectX, bez modyfikowania klasy okna.

Całość kodu źródłowego

Kod pliku obsługi okna (SharpDevelop: MainForm, Visual C#: Form1).

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Kurs1
{
	/// <summary>
	/// Okno główne aplikacji
	/// </summary>
	public partial class MainForm : Form
	{
		private TDirectX directx;
		private int startTickCount = Environment.TickCount;

		public MainForm()
		{
			InitializeComponent();

			//Dwie poniższe linie konieczne tylko, gdy nie użyto panelu właściwości
			Load += new System.EventHandler(MainFormLoad);
			Paint += new System.Windows.Forms.PaintEventHandler(MainFormPaint);
			//
		}

		void MainFormLoad(object sender, EventArgs e)
		{
			SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
			directx = new TDirectX(this, true);
		}

		void MainFormPaint(object sender, PaintEventArgs e)
		{
			if (directx != null)
			{
				directx.Render(Environment.TickCount - startTickCount);
			}
			Invalidate();
		}
	}

	public class TDirectX
	{
		private Device device;
		private Control parent;

		/// <summary>
		/// Konstruktor obiektu obsługującego DirectX
		/// </summary>
		/// <param name="parent">Okno, które będzie celem renderowania grafiki</param>
		/// <param name="windowed">W oknie (true) czy pełnoekranowo (false)?</param>
		public TDirectX(Control parent, bool windowed)
		{
			this.parent = parent;
			Initialize();
		}

		/// <summary>
		/// Tworzenie wszystkich elementów sceny
		/// </summary>
		private void Initialize()
		{
		}

		/// <summary>
		/// Wykonanie renderowania
		/// </summary>
		/// <param name="time">Czas działania aplikacji</param>
		public void Render(float time)
		{
		}
	}
}

10 komentarzy

Wypadałoby użyć stylu nazewnictwa z danego języka... TNazwy to w pascalu :P

POMOCY
Nie mam tych dwóch bibliotek
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

Do kursu nie jest potrzebny Windows 8 (Pytam bo kiedyś znalazłem podobny kurs,ale przykłady działały tylko na Win8) ?

Co masz w presentParameters, czy odpalasz to na emulatorze PC, czy masz akcelerator 3D? Zamiast jako komentarz zgłoś to na forum - lepiej tam prowadzić dłuższe dyskusje.

juz rozwiazalem... wytarczylo zamiast parametru CreateFlags.HardwareVertexProcessing wstawic CreateFlags.SoftwareVertexProcessing

:)

ja mam błąd podczas tworzenia
device = new Device(0, DeviceType.Hardware, parent, CreateFlags.HardwareVertexProcessing, presentParameters);
microsoft.directx.direct3d.invalidcallexception
error in application...

nie mam koncepcji:/

A czy dodałeś referencje, jak opisano w artykule? Jeśli tak, to chociaż napisz, jakie ostrzeżenie Ci wyrzuca, to może powiemy Ci gdzie zrobiłeś błąd.

Do późniejszych artykułów dołączony jest pełen, działający kod - na nim możesz sprawdzić, czy DirectX SDK masz poprawnie zainstalowane i projekt właściwie skonfigurowany.

Wysypuje mi sie treoche bledow z tym ze nie posiadam niby directx'a a instalowalem directx 9 sdk august a pozniej w tools option itd dodalem sciezki do include i library do directx'a i dalej nie idzie w czym moze tkwic problem?

;) Poprawione, dzięki.

File → Nowy project ;-)