Subversion Repositories plumbers

Rev

Rev 19 | Rev 21 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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