Subversion Repositories plumbers

Rev

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