Subversion Repositories plumbers

Rev

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

Rev Author Line No. Line
2 daniel-mar 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;
19 daniel-mar 25
  TWaitCallback = function(Game: TGame; AMilliseconds: integer): boolean of object;
2 daniel-mar 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;
21 daniel-mar 39
    FCurDecisionScene: PSceneDef;
40
    FPrevDecisionScene: PSceneDef;
2 daniel-mar 41
    procedure TryExit;
42
    procedure PrevDecisionScene;
43
  protected
44
    GameData: TGameBinFile;
19 daniel-mar 45
    function Wait(AMilliseconds: integer): boolean;
2 daniel-mar 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
21 daniel-mar 93
  if Assigned(FPrevDecisionScene) then PlayScene(FPrevDecisionScene, true)
2 daniel-mar 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
12 daniel-mar 107
    nextScene := GameData.FindScene(action^.nextSceneID);
2 daniel-mar 108
    if Assigned(nextScene) then
12 daniel-mar 109
      PlayScene(nextScene, action^.sceneSegment=SEGMENT_DECISION)
2 daniel-mar 110
    (*
111
    else
112
      raise Exception.CreateFmt('Scene %d was not found in GAME.BIN', [action^.nextSceneID]);
113
    *)
114
  end;
115
end;
116
 
19 daniel-mar 117
function TGame.Wait(AMilliseconds: integer): boolean;
2 daniel-mar 118
begin
119
  if Assigned(WaitCallback) then
19 daniel-mar 120
  begin
121
    result := WaitCallback(Self, AMilliseconds)
122
  end
2 daniel-mar 123
  else
19 daniel-mar 124
  begin
2 daniel-mar 125
    Sleep(AMilliseconds);
19 daniel-mar 126
    result := false; // don't cancel
127
  end;
2 daniel-mar 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;
19 daniel-mar 153
      if Wait(GameData.pictures[i].duration * 100) then
154
      begin
21 daniel-mar 155
        // Wait was cancelled by VK_RETURN
19 daniel-mar 156
        AsyncSoundCallback(Self, '');
157
        break;
158
      end;
2 daniel-mar 159
      if Application.Terminated then Abort;
160
    end;
161
  end;
162
  if scene^.szDecisionBmp <> '' then
163
  begin
21 daniel-mar 164
    FPrevDecisionScene := FCurDecisionScene;
165
    FCurDecisionScene := scene;
2 daniel-mar 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.