watermain.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:11k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  CAST II Engine water demo main unit
  3.  The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
  4.  (C) 2007 George "Mirage" Bakhtadze
  5. *)
  6. {$I GDefines.inc}
  7. {$I C2Defines.inc}
  8. unit WaterMain;
  9. interface
  10. uses
  11.   SysUtils,
  12.   TextFile, Basics, AppsInit, OSUtils,
  13.   Resources, BaseGraph, BaseTypes, BaseMsg, Base3D,
  14.   C2Res, C2VisItems, C2Anim, C22D, C2FX, C2Land, C2TileMaps,
  15.   ACS, ACSAdv, C2GUI,
  16.   C2Affectors, C2ParticleAdv,
  17.   C2Render, {$IFDEF DIRECT3D8} C2DX8Render, {$ENDIF}
  18.   Input, WInput,
  19.   CAST2, C2Core,
  20.   Timer;
  21. const
  22.   // These constants can be adjusted
  23.   RunFullScreen = False;                      // Fullscreen mode
  24.   SceneFileName = 'water.cbf';                // Scene to load
  25.   CameraRotateSpeed = 0.003;                  // Camera rotation sensitivity
  26.   CameraMoveAccel   = 0.05;                   // Camera movement sensitivity
  27.   BreakFactor       = 0.85;                   // How far camera can move
  28.   CameraMoveRadius  = 100;
  29.   TimerDelay        = 1/60;                   // Delay between timer events
  30.   KeyLeftBind    = 'A';                       // Key binding to move camera left
  31.   KeyRightBind   = 'D';                       // Key binding to move camera right
  32.   KeyUpBind      = 'Q';                       // Key binding to move camera up
  33.   KeyDownBind    = 'E';                       // Key binding to move camera down
  34.   KeyBackBind    = 'W';                       // Key binding to move camera back
  35.   KeyForwardBind = 'S';                       // Key binding to move camera forward
  36.   // Do not change
  37.   keyLeft    = 0;                             // Left key
  38.   keyRight   = 1;                             // Right key
  39.   keyUp      = 2;                             // Up key
  40.   keyDown    = 3;                             // Down key
  41.   keyBack    = 4;                             // Back key
  42.   keyForward = 5;                             // Forward key
  43.   keyMax     = 5;                             // Max key index
  44. type
  45.   TWaterDemo = class
  46.   private
  47.     OldFramesRendered: Integer;
  48.     KeyPressed: array[0..keyMax] of Boolean;  // Bound keys current state
  49.     Velocity: TVector3s;                      // Current movement speed
  50.     Core: TCore;
  51.     function LoadScene(const FileName: string): Boolean;
  52.   public
  53.     constructor Create;
  54.     destructor Destroy; override;
  55.     procedure Process;
  56.     procedure HandleMouse(EventData: Integer; CustomData: SmallInt);
  57.     procedure HandleTimer(EventID: Integer; const ErrorDelta: TTimeUnit);     // Timer event
  58.     procedure HandleMessage(const Msg: TMessage);                             // Message handler
  59.     procedure HandleKeys(EventData: Integer; CustomData: Smallint);           // Keys handle delegate
  60.   end;
  61. var
  62.   Starter: TAppStarter;                                        // Application starter
  63. implementation
  64. function TWaterDemo.LoadScene(const FileName: string): Boolean;
  65. var Stream: TFileStream;
  66. begin
  67.   Stream := TFileStream.Create(Filename);
  68.   Result := Core.LoadScene(Stream);
  69.   if not Result then Log.Log(Self.ClassName + '.Create: Error loading file "' + FileName + '"', lkError);
  70.   Stream.Free;
  71. end;
  72. constructor TWaterDemo.Create;
  73. var HandleKeysProc: TInputDelegate;
  74. begin
  75.   Starter.Terminated := True;                                      // Terminate the application if an error occurs
  76.   // Create engine core
  77.   Core := TCore.Create;
  78.   // Register item classes
  79.   Core.RegisterItemClasses(Resources.GetUnitClassList);            // Base resources
  80.   Core.RegisterItemClasses(BaseGraph.GetUnitClassList);            // Base graphics
  81.   // Engine classes
  82.   Core.RegisterItemClasses(C2Core.GetUnitClassList);               // Engine general classes
  83.   Core.RegisterItemClasses(C2Res.GetUnitClassList);                // CAST II resource
  84.   Core.RegisterItemClasses(C2VisItems.GetUnitClassList);           // Some visible item classes
  85.   Core.RegisterItemClasses(C2Anim.GetUnitClassList);               // Animated item classes
  86.   Core.RegisterItemClasses(C22D.GetUnitClassList);                 // 2D via CAST II wrapper classes
  87.   Core.RegisterItemClasses(C2FX.GetUnitClassList);                 // Some visual effects classes
  88.   Core.RegisterItemClasses(C2Land.GetUnitClassList);               // Landscape classes
  89. //  Core.RegisterItemClasses(C2TileMaps.GetUnitClassList);           // Tilemap classes
  90.   // ACS classes
  91.   Core.RegisterItemClasses(ACS.GetUnitClassList);                  // Base controls
  92.   Core.RegisterItemClasses(ACSAdv.GetUnitClassList);               // Advanced controls
  93.   Core.RegisterItemClasses(C2GUI.GetUnitClassList);                // CAST II wrapper classes
  94.   // Partcile system classes
  95.   Core.RegisterItemClasses(C2Affectors.GetUnitClassList);          // Base particle system related classes
  96.   Core.RegisterItemClasses(C2ParticleAdv.GetUnitClassList);        // Advanced particle system related classes
  97.   Core.MessageHandler    := {$IFDEF OBJFPCEnable}@{$ENDIF}HandleMessage;      // Set message handler
  98.   Starter.MessageHandler := {$IFDEF OBJFPCEnable}@{$ENDIF}Core.HandleMessage; // Redirect window messages to engine
  99.   // Create renderer
  100.   {$IFDEF DIRECT3D8}
  101.   Core.Renderer := TDX8Renderer.Create(Core);
  102.   {$ENDIF}
  103.   if not Assigned(Core.Renderer) or (Core.Renderer.State = rsNotInitialized) then begin             // Error
  104.     Starter.PrintError('Can''t start renderer', lkFatalError);
  105.     Exit;
  106.   end;
  107.   ActivateWindow(Starter.WindowHandle);                            // Bring the application to foreground
  108.   // Initialize render device
  109.   if not Core.Renderer.CreateDevice(Starter.WindowHandle, 0, RunFullScreen) then begin
  110.     Starter.PrintError('Failed to initiaize render device', lkFatalError);
  111.     Exit;
  112.   end;
  113.   // Initialize input subsystem
  114.   Core.Input := TOSController.Create(Starter.WindowHandle, {$IFDEF OBJFPCEnable}@{$ENDIF}Core.HandleMessage);
  115.   Core.Input.BindCommand('ESC', TForceQuitMsg);                    // Bind exit to ESC key
  116.   Core.Input.BindCommand('ALT+Q', TForceQuitMsg);                  // Bind exit to ALT+Q key combination
  117.   // Bind movements keys to delegate supplying in custom data key index with set 8-th bit if key was pressed down.
  118.   HandleKeysProc := {$IFDEF OBJFPCEnable}@{$ENDIF}HandleKeys;
  119.   Core.Input.BindDelegate(KeyLeftBind  + '+', HandleKeysProc, keyLeft  or $100);
  120.   Core.Input.BindDelegate(KeyLeftBind  + '-', HandleKeysProc, keyLeft);
  121.   Core.Input.BindDelegate(KeyRightBind + '+', HandleKeysProc, keyRight or $100);
  122.   Core.Input.BindDelegate(KeyRightBind + '-', HandleKeysProc, keyRight);
  123.   Core.Input.BindDelegate(KeyUpBind   + '+', HandleKeysProc, keyUp   or $100);
  124.   Core.Input.BindDelegate(KeyUpBind   + '-', HandleKeysProc, keyUp);
  125.   Core.Input.BindDelegate(KeyDownBind + '+', HandleKeysProc, keyDown or $100);
  126.   Core.Input.BindDelegate(KeyDownBind + '-', HandleKeysProc, keyDown);
  127.   Core.Input.BindDelegate(KeyBackBind    + '+', HandleKeysProc, keyBack    or $100);
  128.   Core.Input.BindDelegate(KeyBackBind    + '-', HandleKeysProc, keyBack);
  129.   Core.Input.BindDelegate(KeyForwardBind + '+', HandleKeysProc, keyForward or $100);
  130.   Core.Input.BindDelegate(KeyForwardBind + '-', HandleKeysProc, keyForward);
  131. //  Core.Input.MouseCapture := True;
  132. //  Core.CatchAllInput := True;
  133.   Core.Input.BindDelegate('MouseMove^', {$IFDEF OBJFPCEnable}@{$ENDIF}HandleMouse, 0);
  134.   // Load scene
  135.   if not LoadScene(SceneFileName) then begin
  136.     Starter.PrintError('Can''t open scene file "' + SceneFileName + '"', lkFatalError);
  137.     Exit;
  138.   end;
  139.   Starter.Terminated := False;                                     // No errors
  140.   Core.Timer.SetRecurringEvent(TimerDelay, {$IFDEF OBJFPCEnable}@{$ENDIF}HandleTimer, 0);
  141. end;
  142. destructor TWaterDemo.Destroy;
  143. begin
  144.   FreeAndNil(Core);
  145.   inherited;
  146. end;
  147. // PerfHUD
  148. const
  149.   Stride = 4;
  150.   Width = 100 * Stride; Height = 100;
  151.   X = -Width; Y = -Height;
  152.   viFrame = 0; viRender = 1;
  153. var
  154.   Ofs: Integer = 0;
  155.   MaxValue: Single = epsilon;
  156.   Values: array[0..3, 0..Width-1] of Single;
  157.   Count: Integer = 0;
  158. procedure TWaterDemo.Process;
  159.   procedure DrawPerfHUD;
  160.   var i: Integer;
  161.   begin
  162.     if Count >= Width div Stride then begin
  163.       Count := 0;
  164.       MaxValue := epsilon;
  165.     end;
  166.     Values[viFrame,  Count] := Core.PerfProfile.Times[ptFrame];
  167.     Values[viRender, Count] := Core.PerfProfile.Times[ptRender];
  168.     if Values[viFrame, Count] > MaxValue then MaxValue := Values[viFrame, Count];
  169.     Inc(Count);
  170.     Screen.ResetViewport;
  171.     Screen.Clear;
  172. {    Screen.MoveTo(0, 0);
  173.     Screen.LineTo(100, 100);
  174.     Screen.LineTo(100, 200);}
  175.     
  176.     Screen.Color.C := $40000080;
  177.     Screen.Bar(Screen.Width + X, Screen.Height + Y, Screen.Width + X + Width, Screen.Height + Y + Height);
  178.     Screen.Color.C := $40F00000;
  179.     for i := 0 to Count-1 do Screen.Bar(Screen.Width + X+i*Stride, Screen.Height + Y + Height,
  180.                                         Screen.Width + X+i*Stride+Stride-1, Screen.Height + Y + Height - Values[viRender, i]/MaxValue*Height);
  181.     Screen.Color.C := $4000F000;
  182.     for i := 0 to Count-1 do Screen.Bar(Screen.Width + X+i*Stride, Screen.Height + Y + Height - Values[viRender, i]/MaxValue*Height,
  183.                                         Screen.Width + X+i*Stride+Stride-1, Screen.Height + Y + Height - Values[viFrame, i]/MaxValue*Height);
  184.   end;
  185. begin
  186.   Core.Process;
  187.   DrawPerfHUD;
  188. end;
  189. procedure TWaterDemo.HandleMessage(const Msg: TMessage);
  190. var CapMX, CapMY: Integer;
  191. begin
  192.   ObtainCursorPos(CapMX, CapMY);
  193.   if Msg.ClassType = TForceQuitMsg then Starter.Terminate;
  194. end;
  195. procedure TWaterDemo.HandleKeys(EventData: Integer; CustomData: Smallint);
  196. begin
  197.   KeyPressed[CustomData and $FF] := CustomData and $100 > 0;
  198. end;
  199. procedure TWaterDemo.HandleTimer(EventID: Integer; const ErrorDelta: TTimeUnit);
  200. var FPS, Scale: Single;
  201. begin
  202.   Scale := (TimerDelay + ErrorDelta)/TimerDelay;
  203.   Core.Renderer.MainCamera.Move(Velocity.X * scale, Velocity.Y * scale, Velocity.Z * scale);
  204.   Velocity := ScaleVector3s(Velocity, 1-(1-BreakFactor)*scale);
  205.   Velocity := AddVector3s(Velocity, GetVector3s( (Ord(KeyPressed[keyRight]) - Ord(KeyPressed[keyLeft]))    * CameraMoveAccel * Scale,
  206.                                                  (Ord(KeyPressed[keyUp])    - Ord(KeyPressed[keyDown]))    * CameraMoveAccel * Scale,
  207.                                                  (Ord(KeyPressed[keyBack])  - Ord(KeyPressed[keyForward])) * CameraMoveAccel * Scale));
  208.   if SqrMagnitude(Core.Renderer.MainCamera.Position) > Sqr(CameraMoveRadius) then
  209.     Core.Renderer.MainCamera.Position := NormalizeVector3s(Core.Renderer.MainCamera.Position, CameraMoveRadius);
  210.   FPS := (Core.Renderer.FramesRendered - OldFramesRendered) / (TimerDelay + ErrorDelta);
  211.   OldFramesRendered := Core.Renderer.FramesRendered;
  212.   OSUtils.SetWindowCaption(Starter.WindowHandle, Format('%3.3F - %3.3F, %3.3F', [Core.PerfProfile.FramesPerSecond, FPS, Scale]));
  213. end;
  214. procedure TWaterDemo.HandleMouse(EventData: Integer; CustomData: SmallInt);
  215. var MX, MY: Integer;
  216. begin
  217.   MX := Smallint(EventData and $FFFF);
  218.   MY := Smallint((EventData div $10000) and $FFFF);
  219.   with Core.Renderer.MainCamera do
  220.     Orientation := MulQuaternion(GetQuaternion(MX*CameraRotateSpeed, GetVector3s(0, 1, 0)),
  221.                                  MulQuaternion(GetQuaternion(MY*CameraRotateSpeed, RightVector),
  222.                                                Orientation));
  223. end;
  224. end.