blocks.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. unit blocks;
  2. {$mode objfpc}
  3. interface
  4. uses gdk,gtk,classes;
  5. type
  6. TBlockList = Class;
  7. TBreakOut = Class;
  8. TGraphicalObject = Class(TObject)
  9. FRect : TGdkRectangle;
  10. Public
  11. Function Contains(X,Y : Integer) : Boolean;
  12. Property Left : SmallInt Read FRect.x Write Frect.x;
  13. Property Top : SmallInt Read FRect.y Write Frect.y;
  14. Property Width : Word Read Frect.Width Write Frect.Width;
  15. Property Height : Word Read Frect.Height Write Frect.Height;
  16. end;
  17. TBlock = Class(TGraphicalObject)
  18. Private
  19. FMaxHits : Integer;
  20. FBlockList : TBlockList;
  21. FGC : PGDKGC;
  22. FColor : PGDKColor;
  23. FNeedRedraw : Boolean;
  24. Procedure CreateGC;
  25. Function DrawingArea : PGtkWidget;
  26. Function PixMap : PgdkPixMap;
  27. Public
  28. Procedure Draw;
  29. Function Hit : Boolean;
  30. Constructor Create (ABlockList : TBlockList);
  31. Property Color : PGDKColor Read FColor Write FColor;
  32. end;
  33. TSprite = Class(TGraphicalObject)
  34. FPreviousTop,
  35. FPreviousLeft : Integer;
  36. FDrawingArea : PGtkWidget;
  37. FDrawPixMap : PgdkPixmap;
  38. FPixMap : PgdkPixMap;
  39. FBitMap : PGdkBitMap;
  40. FVisible : Boolean;
  41. Protected
  42. Procedure CreateSpriteFromData(SpriteData : PPGchar);
  43. Procedure CreatePixMap; Virtual; Abstract;
  44. Procedure SavePosition;
  45. Public
  46. Constructor Create(DrawingArea: PGtkWidget);
  47. Procedure Draw;
  48. Function GetChangeRect (Var Rect : TGDkRectAngle) : Boolean;
  49. Property PixMap : PgdkPixMap Read FPixMap;
  50. Property BitMap : PGdkBitMap Read FBitMap;
  51. Property Visible : Boolean Read FVisible Write FVisible;
  52. end;
  53. TPad = Class (TSprite)
  54. Private
  55. FSlope,
  56. FSpeed,FCurrentSpeed : Integer;
  57. Protected
  58. Procedure CreatePixMap; override;
  59. Procedure InitialPosition;
  60. Public
  61. Constructor Create(DrawingArea: PGtkWidget);
  62. Procedure Step;
  63. Procedure GoLeft;
  64. Procedure GoRight;
  65. Procedure Stop;
  66. Property CurrentSpeed : Integer Read FCurrentSpeed;
  67. Property Speed : Integer Read FSpeed Write FSpeed;
  68. Property Slope : Integer Read FSlope Write FSlope;
  69. end;
  70. TBall = Class (TSprite)
  71. Private
  72. FBreakOut : TBreakOut;
  73. FCurrentSpeedX,
  74. FCurrentSpeedY : Integer;
  75. FSpeedfactor : Integer;
  76. Protected
  77. Procedure CreatePixMap; override;
  78. Procedure SetSpeed(Value : Integer);
  79. Public
  80. Constructor Create(BreakOut : TBreakOut);
  81. Procedure Step;
  82. Procedure IncSpeed (Value: Integer);
  83. Procedure FlipSpeed (FlipX,FlipY : Boolean);
  84. Property CurrentSpeedX : Integer Read FCurrentSpeedX Write SetSpeed;
  85. Property CurrentSpeedY : Integer Read FCurrentSpeedY;
  86. Property SpeedFactor : INteger Read FSpeedFactor Write FSpeedFactor;
  87. end;
  88. TBlockList = Class (TList)
  89. FTotalRows,FTotalColums,FStartRow,FBlockRows,FSpacing : Byte;
  90. FBreakOut : TBreakOut;
  91. FColor : PGDKColor;
  92. Function DRawingArea : PGTKWidget;
  93. FPixMap : PGDKPixmap;
  94. Public
  95. Constructor Create(BreakOut : TBreakOut);
  96. Destructor Destroy; override;
  97. Procedure CheckCollision (Ball: TBall);
  98. Procedure DrawBlocks;
  99. Procedure DrawBlocks(Const Area : TGdkRectangle);
  100. Procedure CreateBlocks;
  101. Procedure FreeBlocks;
  102. Property TotalRows : Byte Read FTotalRows Write FTotalRows;
  103. Property TotalColumns : Byte Read FTotalColums Write FTotalColums;
  104. Property StartRow : Byte Read FStartRow Write FStartRow;
  105. Property BlockRows : Byte Read FBlockRows Write FBlockRows;
  106. Property BlockSpacing : Byte Read FSpacing Write FSpacing;
  107. Property PixMap : PGDKPixMap Read FPixMap Write FPixMap;
  108. end;
  109. TBreakOut = Class(TObject)
  110. Private
  111. FLevel : Integer;
  112. FBalls : Integer;
  113. FBGGC : PGDKGC;
  114. FBackGroundColor : PGDKColor;
  115. FPad : TPad;
  116. FBall : TBall;
  117. FBlockList : TBlockList;
  118. FDrawingArea : PGTKWidget;
  119. FPixMap : PGDKPixMap;
  120. Procedure DrawBackGround (Area : TGdkrectAngle);
  121. Procedure DrawBoard(Exposed : PGdkEventExpose);
  122. Procedure CreateGC;
  123. Procedure CreatePixMap;
  124. Procedure CopyPixMap(Area : TGdkRectangle);
  125. Procedure CheckCollision;
  126. Procedure FreeBall;
  127. Procedure NextLevel;
  128. Procedure NextBall;
  129. Procedure GameOver;
  130. Procedure LostBall;
  131. Procedure Redrawgame;
  132. Public
  133. Constructor Create (DrawingArea : PGtkWidget);
  134. Procedure Draw(Exposed : PGDKEventExpose);
  135. Procedure Step;
  136. Property BlockList : TBlockList Read FBlockList;
  137. Property Pad : TPad Read FPad;
  138. Property Level : Integer Read Flevel;
  139. Property Balls : Integer Read FBalls Write FBalls;
  140. end;
  141. Const
  142. HitAccelleration = 1;
  143. LevelAccelleration = 2;
  144. FMaxXspeed = 90;
  145. implementation
  146. { ---------------------------------------------------------------------
  147. TGraphicalObject implementation
  148. ---------------------------------------------------------------------}
  149. Function TGraphicalObject.Contains(X,Y : Integer) : Boolean;
  150. begin
  151. Result:=((X>=Left) and (X<Left+Width)) and
  152. ((Y>=top) and (Y<Top+Width));
  153. end;
  154. { ---------------------------------------------------------------------
  155. TBlock implementation
  156. ---------------------------------------------------------------------}
  157. Constructor TBlock.Create (ABlockList : TBlockList);
  158. begin
  159. Inherited Create;
  160. FBlockList:=ABlockList;
  161. FMaxHits:=1;
  162. end;
  163. Function TBlock.DrawingArea : PGtkWidget;
  164. begin
  165. Result:=FBlockList.FBreakout.FDrawingArea;
  166. end;
  167. Function TBlock.PixMap : PgdkPixMap;
  168. begin
  169. Result:=FBlockList.PixMap;
  170. end;
  171. Procedure TBlock.CreateGC;
  172. begin
  173. FGC:=gdk_gc_new(DrawingArea^.Window);
  174. gdk_gc_set_foreground(FGC,FColor);
  175. gdk_gc_set_fill(FGC,GDK_SOLID);
  176. FNeedRedraw:=True;
  177. end;
  178. Procedure TBlock.Draw;
  179. begin
  180. if FGC=Nil then
  181. CreateGC;
  182. if FNeedRedraw Then
  183. begin
  184. gdk_draw_rectangle(PGDKDrawable(Pixmap),FGC,-1,Left,Top,Width,Height);
  185. FNeedRedraw:=False;
  186. end;
  187. end;
  188. Function TBlock.Hit : Boolean;
  189. begin
  190. Dec(FMaxHits);
  191. Result:=FMaxHits=0;
  192. If Result then
  193. begin
  194. FBlockList.FBreakOut.DrawBackground(FRect);
  195. FBlockList.Remove(Self);
  196. Free;
  197. end;
  198. end;
  199. { ---------------------------------------------------------------------
  200. TBlockList implementation
  201. ---------------------------------------------------------------------}
  202. Constructor TBlockList.Create(BreakOut : TBreakOut);
  203. begin
  204. FBreakOut:=BreakOut;
  205. end;
  206. Function TBlockList.DrawingArea : PGtkWidget;
  207. begin
  208. Result:=FBreakOut.FDrawingArea;
  209. end;
  210. Destructor TBlockList.Destroy;
  211. begin
  212. If FColor<>Nil then
  213. FreeMem(FColor);
  214. FreeBlocks;
  215. end;
  216. Procedure TBlockList.DrawBlocks;
  217. Var
  218. I : Longint;
  219. begin
  220. If Count=0 then
  221. CreateBlocks;
  222. For I:=0 to Count-1 do
  223. TBlock(Items[i]).draw;
  224. end;
  225. Procedure TBlockList.DrawBlocks (Const Area : TGdkRectangle);
  226. Var
  227. i : longint;
  228. inters : TgdkRectangle;
  229. begin
  230. For I:=0 to Count-1 do
  231. With TBlock(Items[i]) do
  232. FNeedRedraw:=gdk_rectangle_intersect(@area,@Frect,@inters)<>0;
  233. DrawBlocks;
  234. end;
  235. Function AllocateColor(R,G,B : Integer; Widget : PGtkWidget) : PGdkColor;
  236. begin
  237. Result:=New(PgdkColor);
  238. With Result^ do
  239. begin
  240. Pixel:=0;
  241. Red:=R;
  242. Blue:=B;
  243. Green:=G;
  244. end;
  245. gdk_colormap_alloc_color(gtk_widget_get_colormap(Widget),Result,true,False);
  246. end;
  247. Procedure TBlockList.CreateBlocks;
  248. Var
  249. TotalHeight,TotalWidth,
  250. Cellheight,CellWidth,
  251. I,J : Integer;
  252. Block : TBlock;
  253. Min : Byte;
  254. begin
  255. FColor:=AllocateColor(0,0,$ffff,DrawingArea);
  256. Min:=FSpacing div 2;
  257. If Min<1 then
  258. Min:=1;
  259. TotalWidth:=Drawingarea^.Allocation.Width;
  260. TotalHeight:=DrawingArea^.Allocation.Height;
  261. Cellheight:=TotalHeight Div TotalRows;
  262. CellWidth:=TotalWidth div TotalColumns;
  263. For I:=StartRow to StartRow+BlockRows-1 do
  264. For J:=0 to TotalColumns-1 do
  265. begin
  266. Block:=TBlock.Create(Self);
  267. With Block do
  268. begin
  269. Top:=TotalHeight-(CellHeight*I)+Min;
  270. Left:=(CellWidth*J)+min;
  271. Width:=CellWidth-2*min;
  272. Height:=CellHeight-2*min;
  273. Color:=Self.FColor;
  274. FNeedRedraw:=True;
  275. end;
  276. add(Block);
  277. end;
  278. end;
  279. Procedure TBlockList.FreeBlocks;
  280. Var
  281. I : longint;
  282. begin
  283. For I:=Count-1 downto 0 do
  284. begin
  285. TBlock(Items[i]).Free;
  286. Delete(i);
  287. end;
  288. end;
  289. Procedure TBlockList.CheckCollision (Ball: TBall);
  290. var
  291. brect,ints : tgdkrectangle;
  292. B : TBlock;
  293. i : integer;
  294. flipx,flipy : Boolean;
  295. begin
  296. For I:=Count-1 downto 0 do
  297. begin
  298. B:=TBlock(Items[i]);
  299. BRect:=B.FRect;
  300. if gdk_rectangle_intersect(@Ball.Frect,@BRect,@ints)<>0 then
  301. begin
  302. FlipY:=((Ball.FpreviousTop>=(B.Top+B.Height)) and (Ball.CurrentSpeedY<0)) or
  303. ((Ball.FpreviousTop+Ball.Height<=B.Top) and (Ball.CurrentSpeedY>0));
  304. FlipX:=Not FlipY;
  305. If FlipX then
  306. FlipX:=((Ball.FPreviousLeft>=(B.Left+B.Width)) and (Ball.CurrentSpeedX<0)) or
  307. (((Ball.FPreviousLeft+Ball.Width)<=B.Left) and (Ball.CurrentSpeedX>0));
  308. Ball.FlipSpeed(FlipX,Flipy);
  309. if B.Hit and not (Count=0) then
  310. gtk_widget_draw(DrawingArea,@BRect);
  311. Break;
  312. end;
  313. end;
  314. end;
  315. { ---------------------------------------------------------------------
  316. TSprite implementation
  317. ---------------------------------------------------------------------}
  318. Constructor TSprite.Create(DrawingArea: PGtkWidget);
  319. begin
  320. Inherited Create;
  321. FDrawingArea:=DrawingArea;
  322. Visible:=False;
  323. end;
  324. Procedure TSprite.CreateSpriteFromData(SpriteData : PPGChar);
  325. begin
  326. FPixMap:=gdk_pixmap_create_from_xpm_d(FDrawingArea^.Window,
  327. @FBitmap,
  328. Nil,
  329. SpriteData);
  330. end;
  331. Procedure TSprite.Draw;
  332. Var
  333. gc : PGDKGc;
  334. begin
  335. if Visible then
  336. begin
  337. if FPixMap=Nil then
  338. CreatePixMap;
  339. gc:=gtk_widget_get_style(FDrawingArea)^.fg_gc[GTK_STATE_NORMAL];
  340. gdk_gc_set_clip_origin(gc,Left,Top);
  341. gdk_gc_set_clip_mask(gc,FBitmap);
  342. if FDrawPixMap<>Nil then
  343. gdk_draw_pixmap(FDrawPixMap,gc,FPixMap,0,0,Left,Top,Width,Height)
  344. else
  345. gdk_draw_pixmap(FDrawPixMap{FDrawingArea^.window},gc,FPixMap,0,0,Left,Top,Width,Height);
  346. gdk_gc_set_clip_mask(gc,Nil);
  347. end;
  348. end;
  349. Function TSprite.GetChangeRect (Var Rect : TGDkRectAngle) : Boolean;
  350. begin
  351. Result:=(FPreviousLeft<>Left) or (FPreviousTop<>Top);
  352. If Result then
  353. With Rect do
  354. begin
  355. x:=FPreviousLeft;
  356. y:=FPreviousTop;
  357. Width:=Abs(Left-FPreviousLeft)+self.Width;
  358. height:=Abs(Top-FPreviousTop)+self.Height;
  359. end;
  360. end;
  361. Procedure TSprite.SavePosition;
  362. begin
  363. FPreviousLeft:=Left;
  364. FPreviousTop:=Top;
  365. end;
  366. { ---------------------------------------------------------------------
  367. TPad implementation
  368. ---------------------------------------------------------------------}
  369. Const
  370. PadHeight = 10;
  371. PadWidth = 40;
  372. PadBitmap : Array[1..13] of pchar = (
  373. '40 10 2 1',
  374. ' c none',
  375. 'x c #ff0000',
  376. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  377. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  378. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  379. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  380. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  381. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  382. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  383. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  384. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  385. 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
  386. );
  387. Constructor TPad.Create(DrawingArea: PGtkWidget);
  388. begin
  389. Inherited Create(DrawingArea);
  390. FSpeed:=6;
  391. FSlope:=50;
  392. Visible:=True;
  393. end;
  394. Procedure TPad.CreatePixMap;
  395. begin
  396. CreateSpriteFromData(@PadBitmap[1]);
  397. Width:=PadWidth;
  398. Height:=PadHeight;
  399. InitialPosition;
  400. end;
  401. Procedure TPad.InitialPosition;
  402. begin
  403. Left:=(FDrawingArea^.Allocation.Width-Width) div 2;
  404. Top:=FDrawingArea^.Allocation.Height-(2*Height);
  405. FCurrentSpeed:=0;
  406. end;
  407. Procedure TPad.Step;
  408. begin
  409. SavePosition;
  410. Left:=Left+FCurrentSpeed;
  411. if Left<=0 then
  412. begin
  413. FCurrentSpeed:=-FCurrentSpeed;
  414. Left:=0;
  415. end
  416. else if Left+Width>=FDrawingArea^.allocation.width then
  417. begin
  418. FCurrentSpeed:=-FCurrentSpeed;
  419. Left:=FDrawingArea^.allocation.width-Width;
  420. end;
  421. end;
  422. Procedure TPad.GoLeft;
  423. begin
  424. FCurrentSpeed:=-FSpeed;
  425. end;
  426. Procedure TPad.GoRight;
  427. begin
  428. FCurrentSpeed:=FSpeed;
  429. end;
  430. Procedure TPad.Stop;
  431. begin
  432. FCurrentSpeed:=0;
  433. end;
  434. { ---------------------------------------------------------------------
  435. TBall implementation
  436. ---------------------------------------------------------------------}
  437. Const
  438. BallHeight = 10;
  439. BallWidth = 10;
  440. BallBitmap : Array[1..13] of pchar = (
  441. '10 10 2 1',
  442. ' c none',
  443. 'x c #ffffff',
  444. ' xx ',
  445. ' xxxxxx ',
  446. ' xxxxxxxx ',
  447. ' xxxxxxxx ',
  448. 'xxxxxxxxxx',
  449. 'xxxxxxxxxx',
  450. ' xxxxxxxx ',
  451. ' xxxxxxxx ',
  452. ' xxxxxx ',
  453. ' xx '
  454. );
  455. Constructor TBall.Create(BreakOut : TBreakOut);
  456. begin
  457. Inherited Create(BreakOut.FDrawingArea);
  458. FBreakOut:=breakout;
  459. FCurrentSpeedY:=-100;
  460. FCurrentSpeedX:=0;
  461. FSpeedFactor:=10;
  462. Visible:=True;
  463. end;
  464. Procedure TBall.CreatePixMap;
  465. begin
  466. CreateSpriteFromData(@BallBitmap[1]);
  467. Width:=BallWidth;
  468. Height:=BallHeight;
  469. end;
  470. Procedure TBall.Step;
  471. begin
  472. SavePosition;
  473. Left :=Left + Round((FCurrentSpeedX*FSpeedFactor/100));
  474. Top :=Top + Round((FCurrentSpeedY*FSpeedFactor/100));
  475. if Left<=1 then
  476. begin
  477. FlipSpeed(True,False);
  478. Left:=1;
  479. end
  480. else if Left+Width>=FDrawingArea^.allocation.width then
  481. begin
  482. FlipSpeed(True,False);
  483. Left:=FDrawingArea^.allocation.width-Width-1;
  484. end;
  485. if Top<=1 then
  486. begin
  487. FlipSpeed(False,True);
  488. Top:=1;
  489. end
  490. else if Top+Height>=FDrawingArea^.allocation.Height then
  491. FBreakOut.LostBall
  492. end;
  493. Procedure TBall.SetSpeed(Value : Integer);
  494. begin
  495. If Value<-FMaxXspeed then
  496. Value:=-FMaxXSpeed
  497. else if Value>FMaxXspeed then
  498. Value:=FMaxXspeed;
  499. FCurrentSpeedX:=Value;
  500. If FCurrentSpeedY>0 then
  501. FCurrentSpeedY:=100-Abs(FCurrentSpeedX)
  502. else
  503. FCurrentSpeedY:=-100+Abs(FCurrentSpeedX);
  504. end;
  505. Procedure TBall.IncSpeed (Value: Integer);
  506. begin
  507. FSpeedFactor:=FSpeedFactor+Value;
  508. If FSpeedFactor<10 then
  509. FSpeedFactor:=10;
  510. end;
  511. Procedure TBall.FlipSpeed (FlipX,FlipY : Boolean);
  512. begin
  513. If FlipX then
  514. FCurrentSpeedX:=-FCurrentSpeedX;
  515. If FlipY then
  516. FCurrentSpeedY:=-FCurrentSpeedY;
  517. end;
  518. { ---------------------------------------------------------------------
  519. TBreakout implementation
  520. ---------------------------------------------------------------------}
  521. Constructor TBreakOut.Create (DrawingArea : PGtkWidget);
  522. begin
  523. FDrawingArea:=DrawingArea;
  524. FBlockList:=TBlockList.Create (Self);
  525. FPad:=TPad.Create(FDrawingArea);
  526. FBalls:=5;
  527. end;
  528. Procedure TBreakOut.CheckCollision;
  529. Var
  530. Inters :TGdkrectangle;
  531. begin
  532. If Assigned(FBall) then
  533. begin
  534. if gdk_rectangle_intersect(@FBall.FRect,@FPad.Frect,@inters)<>0 then
  535. If (FBall.FPreviousTop<FPad.Top) and (FBall.FCurrentSpeedY>0) then
  536. begin
  537. FBall.FlipSpeed(False,True);
  538. If (FPad.CurrentSpeed<>0) then
  539. if (FBall.FCurrentSpeedX*FPad.CurrentSpeed)>0 then
  540. FBall.IncSpeed(HitAccelleration)
  541. else
  542. FBall.IncSpeed(-HitAccelleration);
  543. FBall.CurrentSpeedX:=FBall.CurrentSpeedX+(Round(((FBall.Left+(FBall.Width div 2)) - (FPad.left+Fpad.Width div 2)) * (FPad.Slope / 100)));
  544. end;
  545. FBlockList.CheckCollision(FBall);
  546. end;
  547. end;
  548. Procedure TBreakOut.Step;
  549. begin
  550. FPad.Step;
  551. If Assigned(FBall) then
  552. FBall.Step;
  553. CheckCollision;
  554. If FBlockList.Count=0 then
  555. NextLevel;
  556. if Not Assigned(FBall) and (FBalls=0) then
  557. GameOver;
  558. end;
  559. Procedure TBreakOut.CreateGC;
  560. begin
  561. FBGGC:=gdk_gc_new(FDrawingArea^.Window);
  562. FBackGroundColor:=AllocateColor(0,0,0,FDrawingArea);
  563. gdk_gc_set_foreground(FBGGC,FBackGroundColor);
  564. gdk_gc_set_fill(FBGGC,GDK_SOLID);
  565. end;
  566. Procedure TBreakOut.DrawBackGround (Area : TGdkrectAngle);
  567. begin
  568. With Area do
  569. begin
  570. gdk_draw_rectangle(PGDKDrawable(FPixMap),FBGGC,-1,x,y,Width+1,Height+1);
  571. end;
  572. end;
  573. Procedure TBreakOut.DrawBoard(Exposed : PGdkEventExpose);
  574. begin
  575. If FBGGC=Nil then
  576. begin
  577. CreateGC;
  578. end;
  579. DrawBackGround(Exposed^.Area);
  580. end;
  581. Procedure TBreakOut.CreatePixMap;
  582. begin
  583. If FPixMap<>Nil then
  584. GDK_pixmap_unref(FPixMap);
  585. With FDrawingArea^ do
  586. FPixMap:=gdk_pixmap_new(Window,Allocation.Width,Allocation.Height,-1);
  587. FBlockList.PixMap:=FPixMap;
  588. FPad.FDrawPixMap:=FPixMap;
  589. If Assigned(FBall) then
  590. FBall.FDrawPixMap:=FPixMap;
  591. end;
  592. Procedure TBreakOut.CopyPixMap(Area : TGdkRectangle);
  593. begin
  594. gdk_draw_pixmap(FDrawingArea^.Window,
  595. gtk_widget_get_style(FDrawingArea)^.fg_gc[GTK_WIDGET_STATE(FDrawingArea)],
  596. FPixMap,
  597. area.x,area.y,
  598. area.x,area.y,
  599. area.width,area.height);
  600. end;
  601. Procedure TBreakOut.Draw(Exposed : PGDKEventExpose);
  602. Var
  603. Rect : TGdkRectangle;
  604. begin
  605. if FPixMap=Nil then
  606. CreatePixMap;
  607. // draw whatever needed on pixmap.
  608. if Exposed<>Nil then
  609. begin
  610. DrawBoard(Exposed);
  611. FBlockList.DrawBlocks(exposed^.area)
  612. end
  613. else
  614. begin
  615. If Assigned(FBall) then
  616. if FBall.GetChangeRect(Rect) then
  617. begin
  618. DrawBackground(Rect);
  619. FBLockList.drawBlocks(Rect);
  620. end;
  621. if FPad.GetChangeRect(Rect) then
  622. DrawBackground(Rect)
  623. end;
  624. FPad.Draw;
  625. if Assigned(FBall) Then
  626. FBall.draw;
  627. If Exposed<>Nil then
  628. CopyPixMap(Exposed^.Area);
  629. If assigned(FBall) then
  630. if FBall.GetChangeRect(Rect) then
  631. CopyPixMap(Rect);
  632. if FPad.GetChangeRect(Rect) then
  633. CopyPixMap(Rect);
  634. IF Assigned(FBall) then
  635. CopyPixMap(FBall.FRect);
  636. CopyPixMap(FPad.FRect);
  637. end;
  638. Procedure TBreakout.Redrawgame;
  639. Var
  640. Rect : TgdkRectangle;
  641. begin
  642. Rect.X:=FDrawingArea^.allocation.x;
  643. Rect.Y:=FDrawingArea^.allocation.y;
  644. Rect.Width:=FDrawingArea^.allocation.Width;
  645. Rect.Height:=FDrawingArea^.allocation.Height;
  646. gtk_Widget_draw(FDrawingArea,@rect)
  647. end;
  648. Procedure TBreakOut.FreeBall;
  649. begin
  650. FBall.Free;
  651. FBall:=Nil;
  652. end;
  653. Procedure TbreakOut.NextBall;
  654. begin
  655. If FBall=Nil then
  656. begin
  657. FBall:=TBall.Create(Self);
  658. FBall.Top:=FPad.Top-1;
  659. FBall.Left:=FPad.Left + (FPad.Width div 2);
  660. FBall.CurrentSpeedX:=FPad.CurrentSpeed*5;
  661. FBall.FPreviousTop:=FBall.Top;
  662. FBall.FPreviousLeft:=FBall.Left;
  663. FBall.FDrawPixMap:=Self.FPixMap;
  664. FBall.Draw;
  665. end;
  666. end;
  667. Procedure TBreakOut.NextLevel;
  668. Var
  669. Area : TGdkRectangle;
  670. begin
  671. If Assigned(FBall) then
  672. FreeBall;
  673. FPad.FSpeed:=FPad.Speed+LevelAccelleration;
  674. FPad.InitialPosition;
  675. RedrawGame;
  676. end;
  677. Procedure TBreakout.LostBall;
  678. begin
  679. Dec(FBalls);
  680. If FBalls=0 then
  681. GameOver;
  682. FreeBall;
  683. Fpad.InitialPosition;
  684. RedrawGame;
  685. end;
  686. Procedure TBreakout.GameOver;
  687. begin
  688. end;
  689. end.