Subversion Repositories plumbers

Rev

Rev 12 | 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 = procedure(Game: TGame; AMilliseconds: integer) 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.     CurDecisionScene, LastDecisionScene: PSceneDef;
  40.     procedure TryExit;
  41.     procedure PrevDecisionScene;
  42.   protected
  43.     GameData: TGameBinFile;
  44.     function FindScene(ASceneID: integer): PSceneDef;
  45.     procedure Wait(AMilliseconds: integer);
  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. function TGame.FindScene(ASceneID: integer): PSceneDef;
  87. var
  88.   i: integer;
  89. begin
  90.   for i := 0 to GameData.numScenes - 1 do
  91.   begin
  92.     if GameData.scenes[i].szSceneFolder = Format('SC%.2d', [ASceneID]) then
  93.     begin
  94.       result := @GameData.scenes[i];
  95.       exit;
  96.     end;
  97.   end;
  98.   result := nil;
  99. end;
  100.  
  101. procedure TGame.TryExit;
  102. begin
  103.   if Assigned(ExitCallback) then ExitCallback(Self);
  104. end;
  105.  
  106. procedure TGame.PrevDecisionScene;
  107. begin
  108.   if Assigned(LastDecisionScene) then PlayScene(LastDecisionScene, true)
  109. end;
  110.  
  111. procedure TGame.PerformAction(action: PActionDef);
  112. var
  113.   nextScene: PSceneDef;
  114. begin
  115.   Inc(FScore, action^.scoreDelta);
  116.   if action^.nextSceneID = SCENEID_PREVDECISION then
  117.     PrevDecisionScene
  118.   else if action^.nextSceneID = SCENEID_ENDGAME then
  119.     TryExit
  120.   else
  121.   begin
  122.     nextScene := FindScene(action^.nextSceneID);
  123.     if Assigned(nextScene) then
  124.       PlayScene(nextScene, action^.sceneSegment=1)
  125.     (*
  126.     else
  127.       raise Exception.CreateFmt('Scene %d was not found in GAME.BIN', [action^.nextSceneID]);
  128.     *)
  129.   end;
  130. end;
  131.  
  132. procedure TGame.Wait(AMilliseconds: integer);
  133. begin
  134.   if Assigned(WaitCallback) then
  135.     WaitCallback(Self, AMilliseconds)
  136.   else
  137.     Sleep(AMilliseconds);
  138. end;
  139.  
  140. procedure TGame.PlayScene(scene: PSceneDef; goToDecision: boolean);
  141. var
  142.   i: integer;
  143.   hotspot: THotspot;
  144. begin
  145.   if Assigned(ClearHotspotsCallback) then
  146.   begin
  147.     ClearHotspotsCallback(Self);
  148.   end;
  149.   if not goToDecision then
  150.   begin
  151.     if Assigned(AsyncSoundCallback) then
  152.     begin
  153.       AsyncSoundCallback(Self, IncludeTrailingPathDelimiter(FDirectory) +
  154.         scene^.szSceneFolder + PathDelim + scene^.szDialogWav);
  155.     end;
  156.     for i := scene^.pictureIndex to scene^.pictureIndex + scene^.numPics - 1 do
  157.     begin
  158.       if Assigned(PictureShowCallback) then
  159.       begin
  160.         PictureShowCallback(Self, IncludeTrailingPathDelimiter(FDirectory) +
  161.           scene^.szSceneFolder + PathDelim + GameData.pictures[i].szBitmapFile, ptDia);
  162.       end;
  163.       Wait(GameData.pictures[i].duration * 100);
  164.       if Application.Terminated then Abort;
  165.     end;
  166.   end;
  167.   if scene^.szDecisionBmp <> '' then
  168.   begin
  169.     LastDecisionScene := CurDecisionScene;
  170.     CurDecisionScene := scene;
  171.     if Assigned(PictureShowCallback) then
  172.     begin
  173.       PictureShowCallback(Self, IncludeTrailingPathDelimiter(FDirectory) +
  174.         scene^.szSceneFolder + PathDelim + scene^.szDecisionBmp, ptDecision);
  175.     end;
  176.     if Assigned(SetHotspotCallback) then
  177.     begin
  178.       for i := 0 to scene^.numActions - 1 do
  179.       begin
  180.         hotspot.Game := Self;
  181.         hotspot.lpAction := @scene^.actions[i];
  182.         hotspot.cHotspotTopLeft.X := scene^.actions[i].cHotspotTopLeft.X;
  183.         hotspot.cHotspotTopLeft.Y := scene^.actions[i].cHotspotTopLeft.Y;
  184.         hotspot.cHotspotBottomRight.X := scene^.actions[i].cHotspotBottomRight.X;
  185.         hotspot.cHotspotBottomRight.Y := scene^.actions[i].cHotspotBottomRight.Y;        
  186.         SetHotspotCallback(Self, i, hotspot);
  187.       end;
  188.     end;
  189.   end
  190.   else
  191.   begin
  192.     if scene^.numActions > 0 then PerformAction(@scene^.actions[0]);
  193.   end;
  194. end;
  195.  
  196. procedure TGame.Run;
  197. begin
  198.   if GameData.numScenes = 0 then exit;
  199.   PlayScene(@GameData.Scenes[0], false);
  200. end;
  201.  
  202. end.
  203.