Rev 2 | Rev 19 | 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; |
||
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 | procedure Wait(AMilliseconds: integer); |
||
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 |
||
12 | daniel-mar | 106 | nextScene := GameData.FindScene(action^.nextSceneID); |
2 | daniel-mar | 107 | if Assigned(nextScene) then |
12 | daniel-mar | 108 | PlayScene(nextScene, action^.sceneSegment=SEGMENT_DECISION) |
2 | daniel-mar | 109 | (* |
110 | else |
||
111 | raise Exception.CreateFmt('Scene %d was not found in GAME.BIN', [action^.nextSceneID]); |
||
112 | *) |
||
113 | end; |
||
114 | end; |
||
115 | |||
116 | procedure TGame.Wait(AMilliseconds: integer); |
||
117 | begin |
||
118 | if Assigned(WaitCallback) then |
||
119 | WaitCallback(Self, AMilliseconds) |
||
120 | else |
||
121 | Sleep(AMilliseconds); |
||
122 | end; |
||
123 | |||
124 | procedure TGame.PlayScene(scene: PSceneDef; goToDecision: boolean); |
||
125 | var |
||
126 | i: integer; |
||
127 | hotspot: THotspot; |
||
128 | begin |
||
129 | if Assigned(ClearHotspotsCallback) then |
||
130 | begin |
||
131 | ClearHotspotsCallback(Self); |
||
132 | end; |
||
133 | if not goToDecision then |
||
134 | begin |
||
135 | if Assigned(AsyncSoundCallback) then |
||
136 | begin |
||
137 | AsyncSoundCallback(Self, IncludeTrailingPathDelimiter(FDirectory) + |
||
138 | scene^.szSceneFolder + PathDelim + scene^.szDialogWav); |
||
139 | end; |
||
140 | for i := scene^.pictureIndex to scene^.pictureIndex + scene^.numPics - 1 do |
||
141 | begin |
||
142 | if Assigned(PictureShowCallback) then |
||
143 | begin |
||
144 | PictureShowCallback(Self, IncludeTrailingPathDelimiter(FDirectory) + |
||
145 | scene^.szSceneFolder + PathDelim + GameData.pictures[i].szBitmapFile, ptDia); |
||
146 | end; |
||
147 | Wait(GameData.pictures[i].duration * 100); |
||
148 | if Application.Terminated then Abort; |
||
149 | end; |
||
150 | end; |
||
151 | if scene^.szDecisionBmp <> '' then |
||
152 | begin |
||
153 | LastDecisionScene := CurDecisionScene; |
||
154 | CurDecisionScene := scene; |
||
155 | if Assigned(PictureShowCallback) then |
||
156 | begin |
||
157 | PictureShowCallback(Self, IncludeTrailingPathDelimiter(FDirectory) + |
||
158 | scene^.szSceneFolder + PathDelim + scene^.szDecisionBmp, ptDecision); |
||
159 | end; |
||
160 | if Assigned(SetHotspotCallback) then |
||
161 | begin |
||
162 | for i := 0 to scene^.numActions - 1 do |
||
163 | begin |
||
164 | hotspot.Game := Self; |
||
165 | hotspot.lpAction := @scene^.actions[i]; |
||
166 | hotspot.cHotspotTopLeft.X := scene^.actions[i].cHotspotTopLeft.X; |
||
167 | hotspot.cHotspotTopLeft.Y := scene^.actions[i].cHotspotTopLeft.Y; |
||
168 | hotspot.cHotspotBottomRight.X := scene^.actions[i].cHotspotBottomRight.X; |
||
169 | hotspot.cHotspotBottomRight.Y := scene^.actions[i].cHotspotBottomRight.Y; |
||
170 | SetHotspotCallback(Self, i, hotspot); |
||
171 | end; |
||
172 | end; |
||
173 | end |
||
174 | else |
||
175 | begin |
||
176 | if scene^.numActions > 0 then PerformAction(@scene^.actions[0]); |
||
177 | end; |
||
178 | end; |
||
179 | |||
180 | procedure TGame.Run; |
||
181 | begin |
||
182 | if GameData.numScenes = 0 then exit; |
||
183 | PlayScene(@GameData.Scenes[0], false); |
||
184 | end; |
||
185 | |||
186 | end. |