Subversion Repositories plumbers

Rev

Rev 8 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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.
  262.