Subversion Repositories plumbers

Rev

Rev 20 | Rev 23 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit Game;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, Classes, Forms, GameBinStruct;
  7.  
  8. type
  9.   TPictureType = (ptDia, ptDecision);
  10.  
  11.   THotspotIndex = 0..2;
  12.  
  13.   TGame = class;
  14.   PHotspot = ^THotspot;
  15.   THotspot = record
  16.     game: TGame;
  17.     lpAction: PActionDef;
  18.     cHotspotTopLeft: TCoord;
  19.     cHotspotBottomRight: TCoord;
  20.   end;
  21.  
  22.   TShowPictureCallback = procedure(Game: TGame; AFilename: string; AType: TPictureType) of object;
  23.   TPlaySoundCallback = procedure(Game: TGame; AFilename: string) of object;
  24.   TSimpleCallback = procedure(Game: TGame) of object;
  25.   TWaitCallback = function(Game: TGame; AMilliseconds: integer): boolean of object;
  26.   TSetHotspotCallback = procedure(Game: TGame; AIndex: THotspotIndex; AHotspot: THotspot) of object;
  27.   TClearHotspotsCallback = procedure(Game: TGame) of object;
  28.  
  29.   TGame = class(TObject)
  30.   private
  31.     FPictureShowCallback: TShowPictureCallback;
  32.     FAsyncSoundCallback: TPlaySoundCallback;
  33.     FExitCallback: TSimpleCallback;
  34.     FWaitCallback: TWaitCallback;
  35.     FSetHotspotCallback: TSetHotspotCallback;
  36.     FClearHotspotsCallback: TClearHotspotsCallback;
  37.     FDirectory: string;
  38.     FScore: integer;
  39.     FCurDecisionScene: PSceneDef;
  40.     FPrevDecisionScene: PSceneDef;
  41.     procedure TryExit;
  42.     procedure PrevDecisionScene;
  43.   protected
  44.     GameData: TGameBinFile;
  45.     function Wait(AMilliseconds: integer): boolean;
  46.     procedure PlayScene(scene: PSceneDef; goToDecision: boolean);
  47.   public
  48.     procedure PerformAction(action: PActionDef);
  49.     property PictureShowCallback: TShowPictureCallback read FPictureShowCallback write FPictureShowCallback;
  50.     property AsyncSoundCallback: TPlaySoundCallback read FAsyncSoundCallback write FAsyncSoundCallback;
  51.     property ExitCallback: TSimpleCallback read FExitCallback write FExitCallback;
  52.     property WaitCallback: TWaitCallback read FWaitCallback write FWaitCallback;
  53.     property SetHotspotCallback: TSetHotspotCallback read FSetHotspotCallback write FSetHotspotCallback;
  54.     property ClearHotspotsCallback: TClearHotspotsCallback read FClearHotspotsCallback write FClearHotspotsCallback;
  55.     property Directory: string read FDirectory;
  56.     property Score: integer read FScore;
  57.     constructor Create(ADirectory: string);
  58.     procedure Run;
  59.   end;
  60.  
  61. implementation
  62.  
  63. { TGame }
  64.  
  65. constructor TGame.Create(ADirectory: string);
  66. var
  67.   fs: TFileStream;
  68.   gameBinFilename: string;
  69. begin
  70.   FDirectory := ADirectory;
  71.  
  72.   gameBinFilename := IncludeTrailingPathDelimiter(ADirectory) + 'GAME.BIN';
  73.   if not FileExists(gameBinFilename) then
  74.   begin
  75.     raise Exception.Create('Cannot find GAME.BIN');
  76.   end;
  77.  
  78.   fs := TFileStream.Create(gameBinFilename, fmOpenRead);
  79.   try
  80.     fs.ReadBuffer(GameData, SizeOf(GameData));
  81.   finally
  82.     FreeAndNil(fs);
  83.   end;
  84. end;
  85.  
  86. procedure TGame.TryExit;
  87. begin
  88.   if Assigned(ExitCallback) then ExitCallback(Self);
  89. end;
  90.  
  91. procedure TGame.PrevDecisionScene;
  92. begin
  93.   if Assigned(FPrevDecisionScene) then PlayScene(FPrevDecisionScene, true)
  94. end;
  95.  
  96. procedure TGame.PerformAction(action: PActionDef);
  97. var
  98.   nextScene: PSceneDef;
  99. begin
  100.   Inc(FScore, action^.scoreDelta);
  101.   if action^.nextSceneID = SCENEID_PREVDECISION then
  102.     PrevDecisionScene
  103.   else if action^.nextSceneID = SCENEID_ENDGAME then
  104.     TryExit
  105.   else
  106.   begin
  107.     nextScene := GameData.FindScene(action^.nextSceneID);
  108.     if Assigned(nextScene) then
  109.       PlayScene(nextScene, action^.sceneSegment=SEGMENT_DECISION)
  110.     (*
  111.     else
  112.       raise Exception.CreateFmt('Scene %d was not found in GAME.BIN', [action^.nextSceneID]);
  113.     *)
  114.   end;
  115. end;
  116.  
  117. function TGame.Wait(AMilliseconds: integer): boolean;
  118. begin
  119.   if Assigned(WaitCallback) then
  120.   begin
  121.     result := WaitCallback(Self, AMilliseconds)
  122.   end
  123.   else
  124.   begin
  125.     Sleep(AMilliseconds);
  126.     result := false; // don't cancel
  127.   end;
  128. end;
  129.  
  130. procedure TGame.PlayScene(scene: PSceneDef; goToDecision: boolean);
  131. var
  132.   i: integer;
  133.   hotspot: THotspot;
  134. begin
  135.   if Assigned(ClearHotspotsCallback) then
  136.   begin
  137.     ClearHotspotsCallback(Self);
  138.   end;
  139.   if not goToDecision then
  140.   begin
  141.     if Assigned(AsyncSoundCallback) then
  142.     begin
  143.       AsyncSoundCallback(Self, IncludeTrailingPathDelimiter(FDirectory) +
  144.         scene^.szSceneFolder + PathDelim + scene^.szDialogWav);
  145.     end;
  146.     for i := scene^.pictureIndex to scene^.pictureIndex + scene^.numPics - 1 do
  147.     begin
  148.       if Assigned(PictureShowCallback) then
  149.       begin
  150.         PictureShowCallback(Self, IncludeTrailingPathDelimiter(FDirectory) +
  151.           scene^.szSceneFolder + PathDelim + GameData.pictures[i].szBitmapFile, ptDia);
  152.       end;
  153.       if Wait(GameData.pictures[i].duration * 100) then
  154.       begin
  155.         // Wait was cancelled by VK_RETURN
  156.         AsyncSoundCallback(Self, '');
  157.         break;
  158.       end;
  159.       if Application.Terminated then Abort;
  160.     end;
  161.   end;
  162.   if scene^.szDecisionBmp <> '' then
  163.   begin
  164.     FPrevDecisionScene := FCurDecisionScene;
  165.     FCurDecisionScene := scene;
  166.     if Assigned(PictureShowCallback) then
  167.     begin
  168.       PictureShowCallback(Self, IncludeTrailingPathDelimiter(FDirectory) +
  169.         scene^.szSceneFolder + PathDelim + scene^.szDecisionBmp, ptDecision);
  170.     end;
  171.     if Assigned(SetHotspotCallback) then
  172.     begin
  173.       for i := 0 to scene^.numActions - 1 do
  174.       begin
  175.         hotspot.Game := Self;
  176.         hotspot.lpAction := @scene^.actions[i];
  177.         hotspot.cHotspotTopLeft.X := scene^.actions[i].cHotspotTopLeft.X;
  178.         hotspot.cHotspotTopLeft.Y := scene^.actions[i].cHotspotTopLeft.Y;
  179.         hotspot.cHotspotBottomRight.X := scene^.actions[i].cHotspotBottomRight.X;
  180.         hotspot.cHotspotBottomRight.Y := scene^.actions[i].cHotspotBottomRight.Y;        
  181.         SetHotspotCallback(Self, i, hotspot);
  182.       end;
  183.     end;
  184.   end
  185.   else
  186.   begin
  187.     if scene^.numActions > 0 then PerformAction(@scene^.actions[0]);
  188.   end;
  189. end;
  190.  
  191. procedure TGame.Run;
  192. begin
  193.   if GameData.numScenes = 0 then exit;
  194.   PlayScene(@GameData.Scenes[0], false);
  195. end;
  196.  
  197. end.
  198.