using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using Microsoft.DirectX.DirectInput; using WinFont = System.Drawing.Font; using D3DFont = Microsoft.DirectX.Direct3D.Font; using Device=Microsoft.DirectX.Direct3D.Device; using DeviceType=Microsoft.DirectX.Direct3D.DeviceType; using DInput = Microsoft.DirectX.DirectInput; using Manager=Microsoft.DirectX.Direct3D.Manager; namespace blue_dish_te { public struct Hrac { public float x; public float y; } /// /// Formular, ktery vytvori D3D device a ve smycce se prekresluje /// public class RenderForm : Form { // promenne private static Device device = null; private Svet svet = null; private Kolize kolize = null; private Microsoft.DirectX.DirectInput.Device mouse = null; private Microsoft.DirectX.DirectInput.Device keyboard = null; private int mouseX = 0; private int mouseY = 10; private bool drzKrysu = false; private long tick = 0; private long LastTick = 0; private int loopsCount = 0; private int fps = 0; private float dobaVykreslovani = 0.5F; private bool invertMouse = false; private WinFont frameRateWinFont; private D3DFont frameRateD3DFont; private Material material; private const float camFov = (float) Math.PI / 4; private const float camNear = 0.4f; private const float camFar = 200f; private Hrac hrac; /// /// uhly pohledu na scenu /// private float azimuth; private float zenith; /// /// Konstruktor nastavi velikost a vlastnosti okna /// public RenderForm() { ComponentResourceManager resources = new ComponentResourceManager(typeof(RenderForm)); ClientSize = new Size(640, 480); //velikost okna Text = "Blue-dish-te ver 0.1 pre-Alpha"; Icon = ((Icon) (resources.GetObject("$this.Icon"))); //this.FormBorderStyle = FormBorderStyle.FixedSingle; //styl ramecku okna //MaximizeBox = false; //minim. a maxim. tlacitko schovane //MinimizeBox = false; BringToFront(); } /** * Zjisteni zda grafika podporuje Hardwarovou akceleraci * Caps caps = Manager.GetDeviceCaps(0,DeviceType.Hardware ); * if (caps.DeviceCaps.SupportsHardwareTransformAndLight) { * ano; * else * ne; **/ /// /// Metoda se pokusi inicializovat D3D. V pripade neuspechu vypise na konzoli chybu /// /// V pripade neuspechu vraci FALSE jinak TRUE private bool D3DInit() { try { //otestujeme schopnosti grafiky Caps DevCaps = Manager.GetDeviceCaps(0, DeviceType.Hardware); DeviceType DevType = DeviceType.Reference; CreateFlags DevFlags = CreateFlags.SoftwareVertexProcessing; if ((DevCaps.VertexShaderVersion >= new Version(2, 0)) && (DevCaps.PixelShaderVersion >= new Version(2, 0))) { DevType = DeviceType.Hardware; if (DevCaps.DeviceCaps.SupportsHardwareTransformAndLight) { DevFlags = CreateFlags.HardwareVertexProcessing; Console.WriteLine("true"); } } DevFlags |= CreateFlags.MultiThreaded; //pripravime parametry PresentParameters param = new PresentParameters(); param.EnableAutoDepthStencil = true; param.AutoDepthStencilFormat = DepthFormat.D16; param.SwapEffect = SwapEffect.Discard; param.BackBufferCount = 1; param.BackBufferWidth = this.Size.Width; param.BackBufferHeight = this.Size.Height; param.PresentationInterval = PresentInterval.Immediate; param.BackBufferFormat = Manager.Adapters[0].CurrentDisplayMode.Format; param.Windowed = true; //a vytvorime device device = new Device(0, DevType, this, DevFlags, param); //osetreni resetovani Device device.DeviceReset += new EventHandler(DeviceResetEvent); device.RenderState.CullMode = Cull.CounterClockwise; //orezavani odvracenych sten device.RenderState.ZBufferEnable = true; device.RenderState.Lighting = true; //zapnuti svetel device.RenderState.Ambient = Color.FromArgb(0x40, 0x40, 0x40); device.RenderState.SpecularEnable = true; //zapnuti spekularnich odlesku //nastaveni projekcni matice device.Transform.Projection = Matrix.PerspectiveFovLH(camFov, (float) ClientSize.Width / ClientSize.Height, camNear, camFar); //zapnuti vyhlazovani textury device.SamplerState[0].MinFilter = TextureFilter.Anisotropic; device.SamplerState[0].MagFilter = TextureFilter.Anisotropic; device.SamplerState[0].AddressU = TextureAddress.Mirror; device.SamplerState[0].AddressV = TextureAddress.Mirror; //vytvorime svetla CreateLights(); //inicializace fontu pro fps frameRateWinFont = new WinFont(FontFamily.GenericSansSerif, 12); frameRateD3DFont = new D3DFont(device, frameRateWinFont); //nacteme svet svet = new Svet(device); svet.LoadMap("semestralka.map"); hrac.x = -(svet.startX * 2 + 1); hrac.y = -(svet.startY * 2 + 1); //inicializace detekce kolizi kolize = new Kolize(svet); //inicializace materialu material = new Material(); material.Diffuse = Color.White; //nastaveni difuzni barvy materialu //material.Specular = Color.White; //nastaveni spekularni barvy materialu material.Ambient = Color.White; //nastaveni ambientni barvy materialu material.Emissive = System.Drawing.Color.FromArgb(10, 10, 10); //material.SpecularSharpness = .2f; Cursor.Position = new Point(Left + Width / 2, Top + Height / 2); Cursor.Hide(); drzKrysu = true; return true; } catch(DirectXException e) //pokud doslo k vyjimce vrat FALSE { Console.WriteLine(e); return false; } } private void DeviceResetEvent(object caller, EventArgs args) { device.RenderState.CullMode = Cull.CounterClockwise; //orezavani odvracenych sten device.RenderState.ZBufferEnable = true; device.RenderState.Lighting = true; //zapnuti svetel device.RenderState.Ambient = Color.FromArgb(0x40, 0x40, 0x40); device.RenderState.SpecularEnable = true; //zapnuti spekularnich odlesku //zapnuti vyhlazovani textury device.SamplerState[0].MinFilter = TextureFilter.Anisotropic; device.SamplerState[0].MagFilter = TextureFilter.Anisotropic; device.SamplerState[0].AddressU = TextureAddress.Mirror; device.SamplerState[0].AddressV = TextureAddress.Mirror; //nastaveni projekcni matice device.Transform.Projection = Matrix.PerspectiveFovLH(camFov, (float) ClientSize.Width / ClientSize.Height, camNear, camFar); //vytvorime znova vsechny objekty, cimz se se znova inicializuji vertexy svet.ReInitialize(device); //znovu nastavime svetla CreateLights(); } public void CreateLights() { //nastaveni svitu z baterky device.Lights[0].Enabled = true; device.Lights[0].Type = LightType.Spot; //nastaveni typu svetla na spot device.Lights[0].Position = new Vector3(-hrac.x - 6 * (float) Math.Sin(-azimuth), 2.05f - 6 * (float) Math.Sin(zenith), -hrac.y - 6 * (float) Math.Cos(-azimuth)); device.Lights[0].Direction = new Vector3((float) Math.Sin(-azimuth), (float) Math.Sin(zenith - 2 * Math.PI / 180), (float) Math.Cos(-azimuth)); device.Lights[0].Diffuse = Color.White; //nastaveni difuzni barvy svetla device.Lights[0].Specular = Color.Silver; //nastaveni spekularni barvy svetla device.Lights[0].Ambient = Color.FromArgb(0x40, 0x40, 0x40); device.Lights[0].Attenuation0 = 0.00025f; device.Lights[0].Attenuation2 = 0.009f; device.Lights[0].Falloff = 4f; device.Lights[0].InnerConeAngle = 32 * (float) Math.PI / 180; //vrcholovy uhel vnitrniho kuzele device.Lights[0].OuterConeAngle = 36 * (float) Math.PI / 180; //vrcholovy uhel vnejsiho kuzele device.Lights[0].Falloff = 1; //druh opadu svetla mezi kuzely device.Lights[0].Range = camFar; //dosah svetla device.Lights[0].Update(); } /// /// Vycisti okno a vykresli scenu /// private void Render() { try { // nejdriv provedeme vypocet fps // spustime tick, pokud neni if (tick == 0) tick = Environment.TickCount; dobaVykreslovani = ((float) (Environment.TickCount - LastTick)) / 1000; LastTick = Environment.TickCount; // vyprsela 1 vterina? float delay = (float) Math.Abs((Environment.TickCount - tick) / 1000); if (delay > 0.5f) { fps = (int) (loopsCount / delay); loopsCount = 0; tick = Environment.TickCount; } //nacteni z klavesnice a mysi UpdateKeyboard(); UpdateMouse(); device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1, 0); /// vycisti pamet hloubky a barev device.BeginScene(); /// zacatek sceny //upravime pozice a smer svitu baterky device.Lights[0].Position = new Vector3(-hrac.x - 4 * (float) Math.Sin(-azimuth), 2.05f - 4 * (float) Math.Sin(zenith), -hrac.y - 4 * (float) Math.Cos(-azimuth)); device.Lights[0].Direction = new Vector3((float) Math.Sin(-azimuth), (float) Math.Sin(zenith - 2 * Math.PI / 180), (float) Math.Cos(-azimuth)); device.Lights[0].Update(); //nastavime matici view device.Transform.View = Matrix.Identity; device.Transform.View *= Matrix.Translation(hrac.x, -1.85f, hrac.y); device.Transform.View *= Matrix.RotationY(azimuth); device.Transform.View *= Matrix.RotationX(zenith); //nastavime material vsech ploch device.Material = material; //vykreslime svet svet.Render(); //zobrazime fps printFPS(fps); device.EndScene(); //konec sceny device.Present(); //vykresleni loopsCount++; } catch(Exception e) { Console.WriteLine(e); } } public bool InputInit() { //create keyboard device. keyboard = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard); if (keyboard == null) { Console.WriteLine("No keyboard found."); return false; } //create mouse device. mouse = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Mouse); if (mouse == null) { Console.WriteLine("No mouse found."); return false; } //Set mouse axis mode absolute. mouse.Properties.AxisModeAbsolute = true; //set cooperative level. keyboard.SetCooperativeLevel(this, CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Background); mouse.SetCooperativeLevel(this, CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Background); mouse.SetDataFormat(DeviceDataFormat.Mouse); //Acquire devices for capturing. keyboard.Acquire(); mouse.Acquire(); return true; } protected override void OnKeyPress(KeyPressEventArgs e) { if (e.KeyChar == 'h') { //nastvime hrace na startovni pozici hrac.x = -(svet.startX * 2 + 1); hrac.y = -(svet.startY * 2 + 1); azimuth = 0; zenith = 0; mouseX = 0; mouseY = 10; } else if (e.KeyChar == 'x') { //ukonceni enginu Close(); Application.Exit(); } else if (e.KeyChar == 'k') { //drzet / nedrzet krysu (mys) MouseState state = mouse.CurrentMouseState; drzKrysu = !drzKrysu; if (drzKrysu) Cursor.Hide(); else Cursor.Show(); } else if (e.KeyChar == 'u') { //invertace mysi invertMouse = !invertMouse; } else if (e.KeyChar == 'l') { //nacteni nove mapy try { if (drzKrysu) Cursor.Show(); drzKrysu = false; OpenFileDialog dialog = new OpenFileDialog(); dialog.Title = "Load map"; dialog.Filter = "Map file|*.map"; dialog.FilterIndex = 0; if (dialog.ShowDialog() == DialogResult.OK) { svet = new Svet(device); svet.LoadMap(dialog.FileName); kolize = new Kolize(svet); hrac.x = -(svet.startX * 2 + 1); hrac.y = -(svet.startY * 2 + 1); azimuth = 0; zenith = 0; mouseX = 0; mouseY = 10; } drzKrysu = true; Cursor.Hide(); } catch (Exception ex) { Console.WriteLine("Nastala chyba s dialogem..."); Console.WriteLine(ex); } } } private void UpdateKeyboard() { int kombinace_klaves = 0; Hrac hrac_novy = hrac; float rychlostPohybu = 2.5f * dobaVykreslovani; Key[] keys = keyboard.GetPressedKeys(); if (!drzKrysu) return; //Capture pressed keys. foreach(Key k in keys) { if (k == Key.W) { hrac_novy.y -= rychlostPohybu * (float) Math.Cos(azimuth); hrac_novy.x += rychlostPohybu * (float) Math.Sin(azimuth); kombinace_klaves |= 1; } else if (k == Key.S) { hrac_novy.y += rychlostPohybu * (float) Math.Cos(azimuth); hrac_novy.x -= rychlostPohybu * (float) Math.Sin(azimuth); kombinace_klaves |= 1; } else if (k == Key.A) { hrac_novy.y += rychlostPohybu * (float) (Math.Cos(azimuth - Math.PI / 2)); hrac_novy.x -= rychlostPohybu * (float) (Math.Sin(azimuth - Math.PI / 2)); kombinace_klaves |= 2; } else if (k == Key.D) { hrac_novy.y += rychlostPohybu * (float) (Math.Cos(azimuth + Math.PI / 2)); hrac_novy.x -= rychlostPohybu * (float) (Math.Sin(azimuth + Math.PI / 2)); kombinace_klaves |= 2; } } if (kombinace_klaves == 0) return; if ((kombinace_klaves & 1) == 1 && (kombinace_klaves & 2) == 2) { hrac_novy.x = hrac.x + (hrac_novy.x - hrac.x) / (float) Math.Sqrt(2); hrac_novy.y = hrac.y + (hrac_novy.y - hrac.y) / (float) Math.Sqrt(2); } hrac = kolize.UpravPohyb(hrac, hrac_novy); //hrac = hrac_novy; } private void UpdateMouse() { if (!drzKrysu) return; //Get Mouse State. MouseState state = mouse.CurrentMouseState; if (state.X == 0 && state.Y == 0) return; if (state.X != 0) { mouseX += state.X; azimuth = (float) (-((float) mouseX / (Width)) * (2 * Math.PI)); /// vypocet azimutu a zenitu na zaklade abs. polohy kurzoru } if (state.Y != 0) { mouseY += state.Y; zenith = (float) (-((float) mouseY / (Height)) * Math.PI / 2); if (invertMouse) zenith = -zenith; if (zenith > Math.PI / 2) { zenith = (float) Math.PI / 2; mouseY -= state.Y; } if (zenith < -Math.PI / 2) { zenith = (float) -Math.PI / 2; mouseY -= state.Y; } } if (drzKrysu && (state.X != 0 || state.Y != 0)) Cursor.Position = new Point(Left + Width / 2, Top + Height / 2); } private void printFPS(int fps) { frameRateD3DFont.DrawText(null, //Advanced parameter "FPS: " + fps /*+ "; x: " + (-hrac.x) + "; y:" + (-hrac.y) + "; map: " + svet.map[(int) (-hrac.x)/2][(int) (-hrac.y)/2] + "; lx: " + (float) Math.Cos(-azimuth) + "; ly: " + (float) Math.Sin(zenith) + "; lz: " + (float) Math.Sin(-azimuth)*/, // Text to render ClientRectangle, //Clip text to this rectangle DrawTextFormat.Left | //Align text to the left of the window DrawTextFormat.Top | //and to the top DrawTextFormat.WordBreak, //And break lines if necessary Color.GreenYellow); //What color to draw the text in } /// /// Po spusteni se pokusi inicializovat Direct3D. V pripade uspechu /// Prekresluje okno a zpracovava zpravy, dokud existuje okno. /// [STAThreadAttribute] public static void Main() { RenderForm frm = new RenderForm(); //vytvoreni formulare if (frm.D3DInit() && frm.InputInit()) //pokud se podari inicializovat d3d { frm.Show(); //zobrazeni formu while(frm.Created) //a dokud form existuje { frm.Render(); //vykreslovat scenu Application.DoEvents(); //a zpracovavat zpravy //System.Threading.Thread.Sleep(400); } } if (device != null) device.Dispose(); } } }