Subversion Repositories plumbers

Rev

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