fPong.pas 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. unit fPong;
  2. interface
  3. uses
  4. System.Classes,
  5. System.UITypes,
  6. System.SysUtils,
  7. System.Math,
  8. Vcl.Forms,
  9. Vcl.ExtCtrls,
  10. Vcl.Controls,
  11. Vcl.Dialogs,
  12. GLS.Scene,
  13. GLS.VectorTypes,
  14. GLS.Objects,
  15. GLS.Texture,
  16. GLS.VectorGeometry,
  17. GLS.Cadencer,
  18. GLS.SceneViewer,
  19. GLS.SpaceText,
  20. GLS.ShadowPlane,
  21. GLS.ShadowVolume,
  22. GLS.Material,
  23. GLS.Coordinates,
  24. GLS.BaseClasses;
  25. type
  26. TFormPong = class(TForm)
  27. GLScene1: TGLScene;
  28. GLSceneViewer1: TGLSceneViewer;
  29. GLCamera1: TGLCamera;
  30. Plane1: TGLPlane;
  31. Cube1: TGLCube;
  32. Cube2: TGLCube;
  33. Cube3: TGLCube;
  34. Ball: TGLSphere;
  35. DummyCube1: TGLDummyCube;
  36. GLLightSource1: TGLLightSource;
  37. GLMaterialLibrary1: TGLMaterialLibrary;
  38. Pad: TGLCube;
  39. SpaceText1: TGLSpaceText;
  40. Timer1: TTimer;
  41. GLCadencer1: TGLCadencer;
  42. GLShadowVolume: TGLShadowVolume;
  43. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  44. X, Y: Integer);
  45. procedure FormCreate(Sender: TObject);
  46. procedure Timer1Timer(Sender: TObject);
  47. procedure GLCadencer1Progress(Sender: TObject; const deltaTime,
  48. newTime: Double);
  49. private
  50. ballVector : TAffineVector;
  51. score : Integer;
  52. gameOver : Boolean;
  53. procedure ResetGame;
  54. end;
  55. var
  56. FormPong: TFormPong;
  57. implementation
  58. {$R *.DFM}
  59. procedure TFormPong.FormCreate(Sender: TObject);
  60. begin
  61. Randomize;
  62. GLSceneViewer1.Cursor:=crNone;
  63. ResetGame;
  64. end;
  65. procedure TFormPong.ResetGame;
  66. var
  67. angle : Single;
  68. begin
  69. // places the ball in the mat center, resets score and ball speed
  70. angle:=DegToRad(45+Random(90));
  71. MakeVector(ballVector, 4*cos(angle), 4*sin(angle), 0);
  72. score:=0;
  73. gameOver:=False;
  74. Ball.Position.AsVector:=NullHmgPoint;
  75. end;
  76. procedure TFormPong.GLSceneViewer1MouseMove(Sender: TObject;
  77. Shift: TShiftState; X, Y: Integer);
  78. const
  79. cPadMinMax = 6.25;
  80. var
  81. px : Single;
  82. begin
  83. // the pad's position is directly calculated from the mouse position
  84. px:=(x-(GLSceneViewer1.Width/2))*0.035;
  85. if px<-cPadMinMax then
  86. px:=-cPadMinMax
  87. else if px>cPadMinMax then
  88. px:=cPadMinMax;
  89. Pad.Position.X:=px;
  90. // GLCadencer1.Reset;
  91. // update the whole stuff now!
  92. GLCadencer1.Progress;
  93. end;
  94. procedure TFormPong.GLCadencer1Progress(Sender: TObject; const deltaTime,
  95. newTime: Double);
  96. var
  97. newBallPos : TGLVector;
  98. begin
  99. // gameOver is True as soon as the ball is behind the pad, but we don't end
  100. // the game immediately so the user can realize he has lost
  101. if (not gameOver) and (deltaTime>0) then begin
  102. // calc expected new ball pos (if no bump occurs)
  103. // ( note : VectorCombine(v1, v2, f1, f2)=v1*f1+v2*f2 )
  104. newBallPos:=VectorCombine(Ball.Position.AsVector, ballVector, 1, deltaTime);
  105. // check collision with edges
  106. if newBallPos.X<-7.05 then
  107. ballVector.X:=-ballVector.X
  108. else if newBallPos.X>7.05 then
  109. ballVector.X:=-ballVector.X
  110. else if newBallPos.Y>4.55 then
  111. ballVector.Y:=-ballVector.Y;
  112. // check collision with pad
  113. if newBallPos.Y<-4 then begin
  114. if (newBallPos.X>Pad.Position.X-1.25) and (newBallPos.X<Pad.Position.X+1.25) then begin
  115. // when ball bumps the pad, it is accelerated and the vector
  116. // is slightly randomized
  117. ballVector.Y:=-ballVector.Y;
  118. ballVector.X:=ballVector.X+(Random(100)-50)/50;
  119. ballVector.Y:=ballVector.Y+0.1;
  120. // ...and of course a point is scored !
  121. Inc(score);
  122. SpaceText1.Text:=Format('%.3d', [score]);
  123. end else begin
  124. // ball missed !
  125. gameOver:=True;
  126. Exit;
  127. end
  128. end;
  129. end;
  130. // move the ball
  131. with Ball.Position do
  132. AsVector:=VectorCombine(AsVector, ballVector, 1, deltaTime);
  133. end;
  134. procedure TFormPong.Timer1Timer(Sender: TObject);
  135. begin
  136. // update performance monitor
  137. //%s : Name,
  138. Caption:=Format('%.2f FPS', [GLSceneViewer1.FramesPerSecond]);
  139. GLSceneViewer1.ResetPerformanceMonitor;
  140. // display score window when game is over and the ball is well out of the board
  141. if gameOver and (Ball.Position.Y<-6) then begin
  142. // stop the timer to avoid stacking up Timer events
  143. // while the user makes up his mind...
  144. Timer1.Enabled:=False;
  145. if MessageDlg('Score : '+IntToStr(score)+#13#10#13#10+'Play again ?',
  146. mtInformation, [mbYes, mbNo], 0)=mrYes then begin
  147. ResetGame;
  148. Timer1.Enabled:=True;
  149. end else Close;
  150. end;
  151. end;
  152. end.