Laden...

[Tutorial] Spieleprogrammierung Noobguide: Irrlicht.Net

Erstellt von BattleKing vor 15 Jahren Letzter Beitrag vor 15 Jahren 26.221 Views
B
BattleKing Themenstarter:in
15 Beiträge seit 2008
vor 15 Jahren
[Tutorial] Spieleprogrammierung Noobguide: Irrlicht.Net

NOOBGUIDE : IRRLICHT.Net ENGINE
by BattleKing

Aus diesen Topic darf nichts ohne meine Zustimmung kopiert oder wo anders veröffentlicht werden.

In diesen Guide befassen wir uns mit einen simplen Einstieg in die Spieleentwicklung und der Irrlicht Engine. Am Anfang werden wir ein Device erstellen und initialisieren, später fügen wir dann 3D Modelle und Texturen hinzu, dann verwenden wir Licht und Particle Effects und zum Schluss fügen wir noch Parallax Mapping ein.
Keine Angst hört sich schwieriger an als es ist. Nun gut fangen wir an.

Wenn ihr euch an das Tutorial haltet, solltet das zum Schluss so aussehen:

Siehe Anhang

Was wird benötigt:
*Irrlicht.dll(1.1) *IrrlichtNETCP pack *Visual C# Express *3d raum (nicht im starterkit dabei) *Particel bild(nicht im starterkit dabei)

Entweder sucht ihr euch das alles zusammen oder ihr nehmt das von mir zusammen gestellte Starter Kit

Welcher Skill wird benötigt:
*Gute C# Kenntnisse *Vector3 *Vector2 *Dimenson2D

Beginn:

Zuerst schauen wir uns mal den gesamten Code an:

#region Using Statements

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using IrrlichtNETCP;
using IrrlichtNETCP.Inheritable;


#endregion

namespace Light
{
   
   class test
   {
      
      [STAThread]
      static void Main(string[] args)
      {
         DriverType driverType;
         IrrlichtDevice device;
         StringBuilder sb = new StringBuilder();
         sb.AppendLine("Wähle einen Driver aus:");
         sb.AppendLine("(a) Direct3D 9.0c\n(b) Direct3D 8.1\n(c) OpenGL 1.5");
         sb.AppendLine("(d) Software Renderer\n(e)Apfelbaum Software Renderer");
         sb.AppendLine("(f) Null Device\n(otherKey) exit\n\n");
         
         TextReader tIn = Console.In;
         TextWriter tOut = Console.Out;
         tOut.Write(sb.ToString());
         string input = tIn.ReadLine();
         
         switch (input)
         {
            case "a":
               driverType = DriverType.Direct3D9;
               break;
            case "b":
               driverType = DriverType.Direct3D8;
               break;
            case "c":
               driverType = DriverType.OpenGL;
               break;
            case "d":
               driverType = DriverType.Software;
               break;
            case "e":
               driverType = DriverType.Software2;
               break;
            case "f":
               driverType = DriverType.Null;
               break;
            default:
               return;
         }
         
         device = new IrrlichtDevice(driverType, new Dimension2D(1024, 768), 32, true, true, true, true);
         if (device == null)
         {
            tOut.Write("Device creation failed.");
            return;
         }
         
         SceneManager smgr = device.SceneManager;
         VideoDriver driver = device.VideoDriver;
         driver.SetTextureFlag(TextureCreationFlag.Always32Bit, true);
         Texture d = driver.GetTexture(Application.StartupPath.ToString() + @"\media\wall.bmp");
         Texture s = driver.GetTexture(Application.StartupPath.ToString() + @"\media\wall_s.bmp");
         driver.MakeNormalMapTexture(s, 10.0f);
         
         AnimatedMesh mesh = smgr.GetMesh(Application.StartupPath.ToString() + @"\media\room.3ds");
         smgr.ShadowColor = new IrrlichtNETCP.Color(220, 10, 10, 10);
         
         smgr.MeshManipulator.MakePlanarTextureMapping(mesh.GetMesh(0), 0.003f);
         Mesh tangetmesh = smgr.MeshManipulator.CreateMeshWithTangents(mesh.GetMesh(0));
         
         
         SceneNode node = smgr.AddMeshSceneNode(tangetmesh, null, 1);
         node.SetMaterialTexture(0, d);
         node.SetMaterialTexture(1, s);
         node.GetMaterial(0).AnisotropicFilter = true;
         node.GetMaterial(0).SpecularColor.Set(0, 200, 200, 200);
         node.SetMaterialFlag(MaterialFlag.FogEnable, true);
         node.SetMaterialType(MaterialType.ParallaxMapSolid);
         node.GetMaterial(0).Lighting = true;
         node.GetMaterial(0).MaterialTypeParam = 0.035f;
         
         CameraSceneNode camera =
         smgr.AddCameraSceneNodeFPS(null, 50.0f, 600.0f, false);
         camera.Position = new Vector3D(1900 * 2, 10000, 8000 * 2);
         camera.Target = new Vector3D(2397 * 2, 343 * 2, 2700 * 2);
         camera.FarValue = 12000.0f;
         
         node = smgr.AddLightSceneNode(null, new Vector3D(0, 0, 0),
         new Colorf(0.5f, 0.1f, 0.1f, 1.0f), 5000.0f, 0);
         Animator anim = smgr.CreateFlyCircleAnimator(new Vector3D(0,200, 0), 200.0f, 0.0005f);
         node.AddAnimator(anim);
         
         // attach billboard to light
         node = smgr.AddBillboardSceneNode(node, new Dimension2Df(250, 250), 0);
         node.SetMaterialFlag(MaterialFlag.Lighting, false);
         node.SetMaterialType(MaterialType.TransparentAddColor);
         node.SetMaterialTexture(0,
         driver.GetTexture(Application.StartupPath.ToString() + @"\media\particle.bmp"));
         
         ParticleSystemSceneNode ps = smgr.AddParticleSystemSceneNode(
         false, null, 0);
         ps.ParticleSize = new Dimension2Df(50, 125);
         
         ParticleEmitter em = ps.CreateBoxEmitter(
         new Box3D(-7, 0, -7, 7, 1, 7), new Vector3D(0.0f, 0.03f, 0.0f),
         80, 100,
         new IrrlichtNETCP.Color(0, 150, 150, 0), new IrrlichtNETCP.Color(0, 255, 0, 0),
         1500, 2000, 0);
         
         ps.SetEmitter(em);
         
         ParticleAffector paf =
         ps.CreateFadeOutParticleAffector(new IrrlichtNETCP.Color(), 2500);
         
         ps.AddAffector(paf);
         
         ps.SetMaterialFlag(MaterialFlag.Lighting, false);
         ps.SetMaterialTexture(0,
         driver.GetTexture(Application.StartupPath.ToString() + @"\media\particle.bmp"));
         
         ps.SetMaterialType(MaterialType.TransparentVertexAlpha);
         ps.AddAnimator(anim);
         
         
         camera.Position = new Vector3D(-50, 100, 0);
         
         device.CursorControl.Visible = false;
         int lastFPS = -1;
         while (device.Run() && driver != null)
         {
            if (device.WindowActive)
            {
               ps.Position = node.Position;
               uint time = device.Timer.Time;
               driver.BeginScene(true, true, new IrrlichtNETCP.Color(0,0,0,0));
               device.SceneManager.DrawAll();
               
               driver.EndScene();
               
               int fps = device.VideoDriver.FPS;
               if (lastFPS != fps)
               {
                  device.WindowCaption = "IrrlichtNETCP Engine - Parallax Mapping .NET [" +
                  device.VideoDriver.Name + "] FPS:" + fps.ToString();
                  lastFPS = fps;
               }
            }
         }
         /*
         Ende des Irrlicht.Net Devices
         */
         // C++ Verwendet Device->Drop wir verwenden:
         GC.Collect();
      }
      
      
   }
}

So nun schauen wir uns mal einige Zeilen an.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using IrrlichtNETCP;
using IrrlichtNETCP.Inheritable;

Das sind die using Statements, die wir brauchen. Einmal die normalen .Net Komponenten und dann die Irrlicht Namespaces. Es muss die Irrlicht.Net.dll verwiesen werden. Die anderen dlls müssen dann im Release\Debug Ordner sein genau so wie die Medien (Models\Texturen).


DriverType driverType; // Definiert den Driver
IrrlichtDevice device; // Definiert die Grafikkarte
StringBuilder sb = new StringBuilder(); // Stringbuilder für die Treiberauswahl
sb.AppendLine("Wähle einen Driver aus:");
sb.AppendLine("(a) Direct3D 9.0c\n(b) Direct3D 8.1\n(c) OpenGL 1.5");
sb.AppendLine("(d) Software Renderer\n(e)Apfelbaum Software Renderer");
sb.AppendLine("(f) Null Device\n(otherKey) exit\n\n");

TextReader tIn = Console.In;
TextWriter tOut = Console.Out;
tOut.Write(sb.ToString());
string input = tIn.ReadLine();

switch (input) // switch zum Bestimmen
{
   case "a":
      driverType = DriverType.Direct3D9; // Treiber = DX9
      break;
   case "b":
      driverType = DriverType.Direct3D8; // Treiber = DX8
      break;
   case "c":
      driverType = DriverType.OpenGL; // Treiber = OpenGL usw...
      break;
   case "d":
      driverType = DriverType.Software;
      break;
   case "e":
      driverType = DriverType.Software2;
      break;
   case "f":
      driverType = DriverType.Null;
      break;
   default:
      return;
}


So, da werde ich jetzt nicht soviel erklären, da ich es kommentiert hab. Noch zur Software, Software ist der Irrlicht Software Renderer und Software2 ist der Apfelbaum Renderer.

device = new IrrlichtDevice(driverType, new Dimension2D(1024, 768), 32, true, true, true, true);
if (device == null)
{
   tOut.Write("Device creation failed.");
   return;
}

Jetzt wirds interessant. An diesen Punkt wird die Grafikkarte initialisiert. Hier ein Beispiel zu den Überladungen:

"new IrrlichtDevice(Name des Treibers(DX9...), Die Auflösung, Farbtiefe, Fullscreen, Stencil, V-Sinc, Antialise)"

Also nochmal, erst der Treiber, dann die Auflösung in Form einer Dimension2D, danach die Farbtiefe, dann Vollbild, dann Stencil(Schatten), danach V-Sinc und zum Schluss AntiAlise.
Mit der Überprüfung, ob device null ist kann man schauen, ob Fehler bei der Init aufgetreten sind.

SceneManager smgr = device.SceneManager;
VideoDriver driver = device.VideoDriver;
driver.SetTextureFlag(TextureCreationFlag.Always32Bit, true);
Texture d = driver.GetTexture(Application.StartupPath.ToString() + @"\media\wall.bmp");
Texture s = driver.GetTexture(Application.StartupPath.ToString() + @"\media\wall_s.bmp");
driver.MakeNormalMapTexture(s, 10.0f);

Der SceneManager erklärt sich selbst; er wird durch device.SceneManager deklariert. Der VideoDriver ist nichts anderes als der Grafikkartentreiber. Mit den Befehl driver.SetTextureFlag bestimmen wir, dass alle Texturen intern in Tga mit 32bit umgewandelt werden, das heißt dass sie einen Alpha bekommen.
Danach deklarieren wir 2 Texturen, einmal die Diffuse und die Speculary/Heightmap, danach wird die Heightmap in eine NormalTexture gemacht.

AnimatedMesh mesh = smgr.GetMesh(Application.StartupPath.ToString() + @"\media\room.3ds");
smgr.ShadowColor = new IrrlichtNETCP.Color(220, 10, 10, 10);

smgr.MeshManipulator.MakePlanarTextureMapping(mesh.GetMesh(0), 0.003f);
Mesh tangetmesh = smgr.MeshManipulator.CreateMeshWithTangents(mesh.GetMesh(0));



SceneNode node = smgr.AddMeshSceneNode(tangetmesh, null, 1);
node.SetMaterialTexture(0, d); // Diffuse Texture
node.SetMaterialTexture(1, s); // Heightmap
node.GetMaterial(0).AnisotropicFilter = true; // Schaltet Anisotropic Filter ein
node.GetMaterial(0).SpecularColor.Set(0, 200, 200, 200); // Bestimmt die Specular Farbe
node.SetMaterialFlag(MaterialFlag.FogEnable, true); // Aktiviert das Fogging
node.SetMaterialType(MaterialType.ParallaxMapSolid); // Bestimmt, dass die Texturen Parallax gemapppt werden sollen
node.GetMaterial(0).Lighting = true; // Schaltet die Basisbeleutung ein
node.GetMaterial(0).MaterialTypeParam = 0.035f; // Bestimmt den Effekt des Parallax Mapping

Am Anfang laden wir das Mesh Room.3ds danach bestimmen wir die Schattenfarbe, mit den MeshManipulator sagen wir das room.3ds die Textur PlanarMappen soll dies wird für das Parallax Mapping benötigt genau so wie das tangetmesh aus nächster erstellen wir die SceneNode Node und fügen unser vorher geladenes Mesh ein.

 CameraSceneNode camera =
smgr.AddCameraSceneNodeFPS(null, 50.0f, 600.0f, false);
camera.Position = new Vector3D(1900 * 2, 10000, 8000 * 2);
camera.Target = new Vector3D(2397 * 2, 343 * 2, 2700 * 2);
camera.FarValue = 12000.0f;

Mit der CameraSceneNode fügen wir unseren kleinen "Spiel" eine man - glaubts kaum - Kamera hinzu. Hier verwenden wir die FPS Vorgabe. Danach geben wir nur Position, Blickwinkel und die FearValue an.


node = smgr.AddLightSceneNode(null, new Vector3D(0, 0, 0),
new Colorf(0.5f, 0.1f, 0.1f, 1.0f), 5000.0f, 0);
Animator anim = smgr.CreateFlyCircleAnimator(new Vector3D(0,200, 0), 200.0f, 0.0005f);
node.AddAnimator(anim);

// attach billboard to light
node = smgr.AddBillboardSceneNode(node, new Dimension2Df(250, 250), 0);
node.SetMaterialFlag(MaterialFlag.Lighting, false);
node.SetMaterialType(MaterialType.TransparentAddColor);
node.SetMaterialTexture(0,
driver.GetTexture(Application.StartupPath.ToString() + @"\media\particle.bmp"));

Nun erstellen wir ein Licht und fügen einen Animator hinzu, der sagt, dass unser Licht sich immer im Kreis drehen soll.
So jetzt fügen wir ein Billboard hizu. Das heißt soviel wie wir fügen ein Bild an der Stelle des Lichts ein und bestimmen das Material, so wie beim Raum wichtig. Hier ist das der Material Type TransparentAddColor, damit wir später nur das eigentliche Bild sehn und nicht auch das schwarze Viereck.

ParticleSystemSceneNode ps = smgr.AddParticleSystemSceneNode(
false, null, 0);
ps.ParticleSize = new Dimension2Df(50, 125);

ParticleEmitter em = ps.CreateBoxEmitter(
new Box3D(-7, 0, -7, 7, 1, 7), new Vector3D(0.0f, 0.03f, 0.0f),
80, 100,
new IrrlichtNETCP.Color(0, 150, 150, 0), new IrrlichtNETCP.Color(0, 255, 0, 0),
1500, 2000, 0);

ps.SetEmitter(em);

ParticleAffector paf =
ps.CreateFadeOutParticleAffector(new IrrlichtNETCP.Color(), 2500);

ps.AddAffector(paf);

ps.SetMaterialFlag(MaterialFlag.Lighting, false);
ps.SetMaterialTexture(0,
driver.GetTexture(Application.StartupPath.ToString() + @"\media\particle.bmp"));

ps.SetMaterialType(MaterialType.TransparentVertexAlpha);
ps.AddAnimator(anim);

Nun fügen wir ein ParticleSystem ein, das heißt wir erstellen Particle, dann schalten wir die Größe jedes Particle auf 50x125, dann erstellen wir einen Box Emitter und fügen ihm unseren ps hinzu, aber in einen anderen Tutorial mehr. Nun erstellen wir wieder ein Material für das Paricle System und zu guter Letzt fügen wir den selben Animator, den unser Licht hat, auch den Particle System hinzu.

while (device.Run() && driver != null)
{
   if (device.WindowActive)
   {
      ps.Position = node.Position;
      uint time = device.Timer.Time;
      driver.BeginScene(true, true, new IrrlichtNETCP.Color(0,0,0,0));
      device.SceneManager.DrawAll();
      
      driver.EndScene();
      
      int fps = device.VideoDriver.FPS;
      if (lastFPS != fps)
      {
         device.WindowCaption = "IrrlichtNETCP Engine - Parallax Mapping .NET [" +
         device.VideoDriver.Name + "] FPS:" + fps.ToString();
         lastFPS = fps;
      }
   }
}

Jetzt beginnen wir die Hauptschleife, die solange aktiv ist, solange die Grafikkarte Irrlicht zugewiesen ist und der Driver läuft.
Dann überprüfen wir, ob die Grafikkarte auch auf unser Fenster den Fokus hat und schalten die Particel Position zu der Licht Position, dann beginnen wir die Scene,
sagen Irrlicht das alles, was wir vorhin angegeben haben, auch auf einmal dargestellt werden soll und beenden die Scene wieder. Den Rest könnt ihr euch anschauen, wenn ihr den Fullscreen auf false schaltet.

So das wars. Ich bitte um Feedback. Ihr könnt gerne mit den Code rumspielen und dann Screens hier Posten bei Problemen oder sonstigen alles hier melden, ich helfe euch dann.

MfG BK

So Bin ich

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo BattleKing,

danke für den Guide. Ich habe ihn mal nach Artikel verschoben. Ich denke, das ist in deinem Sinne.

Hallo zusammen,

bei Problemen oder sonstigen alles hier melden, ich helfe euch dann.

Bitte nur Fragen und Kommentare direkt zum Tutorial in diesem Thread stellen. Für Fragen zur Irrlicht-Programmierung oder zu Problemen damit macht bitte jeweils einen neuen Thread in Grafik und Sound auf.

herbivore