Subversion Repositories plumbers

Rev

Rev 8 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
unit Main;
2
 
3
// TODO: When the windows is only resized a little bit (A few pixels), the window should not centered
4
// Idea: Calc the width and height of ALL pictures, and then size the form to the biggest value?
5
// BUG: if bitmap is not existing, then the error "ReadBitmapFile(): Unable to open bitmap file" appears. Not good.
6
// BUG: If you drag the window, the dia show will stop playing, but the sound continues! This makes everything out of sync.
7
// TODO: Ini Parameter if fullscreen is applied or not
8
// TODO: Check out if hotspot coords should have their origin at the picture or the form position.
9
// Idea: Savestates. Speedup. Pause.
10
// Idea: Use Space bar to go to the next decision point.
11
 
12
interface
13
 
14
uses
15
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
16
  Dialogs, ExtCtrls, StdCtrls, Game;
17
 
18
type
19
  TMainForm = class(TForm)
20
    Image1: TImage;
21
    Panel1: TPanel;
22
    StartupTimer: TTimer;
23
    procedure FormCreate(Sender: TObject);
24
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
25
    procedure StartupTimerTimer(Sender: TObject);
26
    procedure ControlClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
27
    procedure FormDestroy(Sender: TObject);
28
  private
29
    FHotspots: array[0..2] of THotspot;
30
    FullscreenMode: boolean;
31
    procedure cbPictureShow(ASender: TGame; AFilename: string; AType: TPictureType);
32
    procedure cbAsyncSound(ASender: TGame; AFilename: string);
33
    procedure cbExit(ASender: TGame);
34
    procedure cbWait(ASender: TGame; AMilliseconds: integer);
35
    procedure cbSetHotspot(ASender: TGame; AIndex: THotspotIndex; AHotspot: THotspot);
36
    procedure cbClearHotspots(ASender: TGame);
37
    procedure ClickEvent(X, Y: Integer);
38
  public
39
    game: TGame;
40
  end;
41
 
42
var
43
  MainForm: TMainForm;
44
 
45
implementation
46
 
47
{$R *.dfm}
48
 
49
uses
50
  MMSystem, IniFiles, Math;
51
 
52
procedure Delay(const Milliseconds: DWord);
53
var
54
  FirstTickCount: DWord;
55
begin
56
  FirstTickCount := GetTickCount; // TODO: Attention, GetTickCount can overflow
57
  while not Application.Terminated and ((GetTickCount - FirstTickCount) < Milliseconds) do
58
  begin
59
    Application.ProcessMessages;
60
    Sleep(0);
61
  end;
62
end;
63
 
64
function AddThouSeps(const S: string): string;
65
var
66
  LS, L2, I, N: Integer;
67
  Temp: string;
68
begin
69
  // http://www.delphigroups.info/2/11/471892.html
70
  result := S ;
71
  LS := Length(S);
72
  N := 1 ;
73
  if LS > 1 then
74
  begin
75
    if S [1] = '-' then  // check for negative value
76
    begin
77
      N := 2;
78
      LS := LS - 1;
79
    end;
80
  end;
81
  if LS <= 3 then exit;
82
  L2 := (LS - 1) div 3;
83
  Temp := '';
84
  for I := 1 to L2 do
85
  begin
86
    Temp := ThousandSeparator + Copy (S, LS - 3 * I + 1, 3) + Temp;
87
  end;
88
  Result := Copy (S, N, (LS - 1) mod 3 + 1) + Temp;
89
  if N > 1 then Result := '-' + Result;
90
end;
91
 
92
{ TMainForm }
93
 
94
procedure TMainForm.cbPictureShow(ASender: TGame; AFilename: string; AType: TPictureType);
95
begin
96
  if FileExists(AFilename) then
97
  begin
98
    Image1.Visible := false;
99
    try
100
      Image1.Picture.LoadFromFile(AFilename);
101
      Image1.Autosize := true;
102
    finally
103
      // This speeds up the picture loading on very old computers
104
      Image1.Visible := true;
105
    end;
106
 
107
    // Make form bigger if necessary
108
    if Image1.Width > ClientWidth then
109
    begin
110
      ClientWidth := Image1.Width;
111
      if (ClientWidth >= Screen.Width) then FullscreenMode := true;
112
      Position := poScreenCenter;
113
    end;
114
    if Image1.Height > ClientHeight then
115
    begin
116
      ClientHeight := Image1.Height;
117
      if (ClientHeight >= Screen.Height) then FullscreenMode := true;
118
      Position := poScreenCenter;
119
    end;
120
 
121
    // Center image
122
    Image1.Left := ClientWidth div 2 - Image1.Width div 2;
123
    Image1.Top := ClientHeight div 2 - Image1.Height div 2;
124
  end
125
  else
126
  begin
127
    Image1.Picture := nil;
128
  end;
129
 
130
  if FullScreenMode then
131
  begin
132
    BorderStyle := bsNone;
133
    FormStyle := fsStayOnTop;
134
    Case AType of
135
      ptDia: Screen.Cursor := -1;
136
      ptDecision: Screen.Cursor := 0;
137
    End;
138
  end;
139
 
140
  Panel1.Caption := Format('Your score is: %s', [AddThouSeps(IntToStr(ASender.Score))]);
141
  Panel1.Left := 8;
142
  Panel1.Top := Min(ClientHeight, Screen.Height) - Panel1.Height - 8;
143
  Panel1.Visible := AType = ptDecision;
144
end;
145
 
146
procedure TMainForm.cbAsyncSound(ASender: TGame; AFilename: string);
147
begin
148
  PlaySound(nil, hinstance, 0);
149
  if FileExists(AFilename) then
150
  begin
151
    PlaySound(PChar(AFilename), hinstance, SND_FILENAME or SND_ASYNC);
152
  end;
153
end;
154
 
155
procedure TMainForm.cbSetHotspot(ASender: TGame; AIndex: THotspotIndex; AHotspot: THotspot);
156
begin
157
  FHotspots[AIndex] := AHotspot;
158
end;
159
 
160
procedure TMainForm.cbClearHotspots(ASender: TGame);
161
var
162
  i: Integer;
163
begin
164
  for i := Low(FHotspots) to High(FHotspots) - 1 do
165
  begin
166
    FHotspots[i].lpAction := nil;
167
  end;
168
end;
169
 
170
procedure TMainForm.cbExit(ASender: TGame);
171
begin
172
  Application.Terminate;
173
end;
174
 
175
procedure TMainForm.cbWait(ASender: TGame; AMilliseconds: integer);
176
begin
177
  //Cursor := crHourglass;
178
  try
179
    Delay(AMilliseconds);
180
  finally
181
    //Cursor := crDefault;
182
  end;
183
end;
184
 
185
procedure TMainForm.FormCreate(Sender: TObject);
186
var
187
  ini: TMemIniFile;
188
  iniFilename: string;
189
begin
190
  iniFilename := ChangeFileExt(ExtractFileName(ParamStr(0)), '.ini');
191
 
192
  DoubleBuffered := true;
193
 
194
  if FileExists(iniFilename) then
195
  begin
196
    ini := TMemIniFile.Create(iniFilename);
197
    try
198
      Caption := ini.ReadString('Config', 'Title', '');
199
    finally
200
      FreeAndNil(ini);
201
    end;
202
  end;
203
 
204
  try
205
    Game := TGame.Create('.');
206
    Game.PictureShowCallback := cbPictureShow;
207
    Game.AsyncSoundCallback := cbAsyncSound;
208
    Game.ExitCallback := cbExit;
209
    Game.WaitCallback := cbWait;
210
    Game.SetHotspotCallback := cbSetHotspot;
211
    Game.ClearHotspotsCallback := cbClearHotspots;
212
    StartupTimer.Enabled := true;
213
  except
214
    Application.Terminate;
215
  end;
216
end;
217
 
218
procedure TMainForm.FormDestroy(Sender: TObject);
219
begin
220
  // Without this, some audio drivers could crash if you press ESC to end the game.
221
  // (VPC 2007 with Win95; cpsman.dll crashes sometimes)
222
  PlaySound(nil, hinstance, 0);
223
end;
224
 
225
procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
226
  Shift: TShiftState);
227
begin
228
  if Key = VK_ESCAPE then Close;
229
end;
230
 
231
procedure TMainForm.ClickEvent(X, Y: Integer);
232
var
233
  i: integer;
234
begin
235
  // TODO: if hotspots are overlaying; which hotspot will be prefered? the top ones? check out the original game.
236
  for i := Low(FHotspots) to High(FHotspots) do
237
  begin
238
    if Assigned(FHotspots[i].lpAction) and
239
       (X >= FHotspots[i].cHotspotTopLeft.X) and
240
       (Y >= FHotspots[i].cHotspotTopLeft.Y) and
241
       (X <= FHotspots[i].cHotspotBottomRight.X) and
242
       (Y <= FHotspots[i].cHotspotBottomRight.Y) then
243
    begin
244
      FHotspots[i].Game.PerformAction(FHotspots[i].lpAction);
245
      Exit;
246
    end;
247
  end;
248
end;
249
 
250
procedure TMainForm.ControlClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
251
begin
252
  ClickEvent(X+TControl(Sender).Left, Y+TControl(Sender).Top);
253
end;
254
 
255
procedure TMainForm.StartupTimerTimer(Sender: TObject);
256
begin
257
  StartupTimer.Enabled := false;
258
  Game.Run;
259
end;
260
 
261
end.