Browse Source

+ Added all examples for GTK - 5

michael 24 years ago
parent
commit
3a1f29ce31
3 changed files with 1054 additions and 0 deletions
  1. 832 0
      docs/gtk5ex/blocks.pp
  2. 104 0
      docs/gtk5ex/breakout.pp
  3. 118 0
      docs/gtk5ex/graphics.pp

+ 832 - 0
docs/gtk5ex/blocks.pp

@@ -0,0 +1,832 @@
+unit blocks;
+
+{$mode objfpc}
+
+interface
+
+uses gdk,gtk,classes;
+
+type
+  TBlockList = Class;
+  TBreakOut = Class;
+  
+  TGraphicalObject  = Class(TObject)
+    FRect : TGdkRectangle;
+  Public 
+    Function Contains(X,Y : Integer) : Boolean;
+    Property Left : SmallInt Read FRect.x Write Frect.x;
+    Property Top : SmallInt  Read FRect.y Write Frect.y;
+    Property Width : Word  Read Frect.Width Write Frect.Width;
+    Property Height : Word  Read Frect.Height Write Frect.Height;
+  end;
+
+  TBlock = Class(TGraphicalObject)
+  Private
+    FMaxHits : Integer;
+    FBlockList : TBlockList;
+    FGC : PGDKGC;
+    FColor : PGDKColor;
+    FNeedRedraw : Boolean;
+    Procedure CreateGC;
+    Function DrawingArea : PGtkWidget;
+    Function PixMap : PgdkPixMap; 
+  Public
+    Procedure Draw;
+    Function Hit : Boolean;
+    Constructor Create (ABlockList : TBlockList);
+    Property Color : PGDKColor Read FColor Write FColor;
+  end;
+
+  TSprite = Class(TGraphicalObject)
+    FPreviousTop,
+    FPreviousLeft : Integer;
+    FDrawingArea : PGtkWidget;
+    FDrawPixMap : PgdkPixmap;
+    FPixMap : PgdkPixMap;
+    FBitMap : PGdkBitMap;
+    FVisible : Boolean;
+  Protected
+    Procedure CreateSpriteFromData(SpriteData : PPGchar);
+    Procedure CreatePixMap; Virtual; Abstract; 
+    Procedure SavePosition;
+  Public
+    Constructor Create(DrawingArea: PGtkWidget);
+    Procedure Draw;    
+    Function GetChangeRect (Var Rect : TGDkRectAngle) : Boolean;
+    Property PixMap : PgdkPixMap Read FPixMap;
+    Property BitMap : PGdkBitMap Read FBitMap; 
+    Property Visible : Boolean Read FVisible Write FVisible;
+  end;
+
+  TPad = Class (TSprite)
+  Private
+    FSlope,
+    FSpeed,FCurrentSpeed : Integer;
+  Protected
+    Procedure CreatePixMap; override;
+    Procedure InitialPosition; 
+  Public  
+    Constructor Create(DrawingArea: PGtkWidget);
+    Procedure Step;
+    Procedure GoLeft;
+    Procedure GoRight;
+    Procedure Stop;
+    Property CurrentSpeed : Integer Read FCurrentSpeed;
+    Property Speed : Integer Read FSpeed Write FSpeed;
+    Property Slope : Integer Read FSlope Write FSlope;
+  end;
+
+  TBall = Class (TSprite)
+  Private
+    FBreakOut : TBreakOut;
+    FCurrentSpeedX,
+    FCurrentSpeedY : Integer;
+    FSpeedfactor : Integer;
+  Protected
+    Procedure CreatePixMap; override;
+    Procedure SetSpeed(Value : Integer);
+  Public  
+    Constructor Create(BreakOut : TBreakOut);
+    Procedure Step;
+    Procedure IncSpeed (Value: Integer);
+    Procedure FlipSpeed (FlipX,FlipY : Boolean);
+    Property CurrentSpeedX : Integer Read FCurrentSpeedX Write SetSpeed;
+    Property CurrentSpeedY : Integer Read FCurrentSpeedY;
+    Property SpeedFactor : INteger Read FSpeedFactor Write FSpeedFactor;
+  end;
+
+  TBlockList = Class (TList)
+    FTotalRows,FTotalColums,FStartRow,FBlockRows,FSpacing : Byte;
+    FBreakOut : TBreakOut;
+    FColor : PGDKColor;
+    Function DRawingArea : PGTKWidget;
+    FPixMap : PGDKPixmap;
+  Public 
+    Constructor Create(BreakOut : TBreakOut);
+    Destructor Destroy; override;
+    Procedure CheckCollision (Ball: TBall);
+    Procedure DrawBlocks;
+    Procedure DrawBlocks(Const Area : TGdkRectangle);
+    Procedure CreateBlocks;
+    Procedure FreeBlocks;
+    Property TotalRows : Byte Read FTotalRows Write FTotalRows;
+    Property TotalColumns : Byte Read FTotalColums Write FTotalColums;
+    Property StartRow : Byte Read FStartRow Write FStartRow;
+    Property BlockRows : Byte Read FBlockRows Write FBlockRows;
+    Property BlockSpacing : Byte Read FSpacing Write FSpacing; 
+    Property PixMap : PGDKPixMap Read FPixMap Write FPixMap;
+  end;
+
+
+  TBreakOut = Class(TObject)
+  Private
+    FLevel : Integer;
+    FBalls : Integer;
+    FBGGC : PGDKGC;
+    FBackGroundColor : PGDKColor;
+    FPad : TPad;
+    FBall : TBall;
+    FBlockList : TBlockList;
+    FDrawingArea : PGTKWidget;
+    FPixMap : PGDKPixMap;
+    Procedure DrawBackGround (Area : TGdkrectAngle);
+    Procedure DrawBoard(Exposed : PGdkEventExpose);
+    Procedure CreateGC;
+    Procedure CreatePixMap;
+    Procedure CopyPixMap(Area : TGdkRectangle);
+    Procedure CheckCollision;
+    Procedure FreeBall;
+    Procedure NextLevel;
+    Procedure NextBall;
+    Procedure GameOver;
+    Procedure LostBall;
+    Procedure Redrawgame;
+  Public   
+    Constructor Create (DrawingArea : PGtkWidget);
+    Procedure Draw(Exposed : PGDKEventExpose);
+    Procedure Step;
+    Property BlockList : TBlockList Read FBlockList;
+    Property Pad : TPad Read FPad;
+    Property Level : Integer Read Flevel;
+    Property Balls : Integer Read FBalls Write FBalls;
+  end;
+
+Const 
+  HitAccelleration   = 1;
+  LevelAccelleration = 2;
+  FMaxXspeed = 90;
+
+
+implementation
+
+{ ---------------------------------------------------------------------
+    TGraphicalObject implementation
+  ---------------------------------------------------------------------}
+
+Function TGraphicalObject.Contains(X,Y : Integer) : Boolean;
+
+begin
+  Result:=((X>=Left) and (X<Left+Width)) and
+          ((Y>=top) and (Y<Top+Width));
+end;
+
+{ ---------------------------------------------------------------------
+    TBlock implementation
+  ---------------------------------------------------------------------}
+  
+
+Constructor TBlock.Create (ABlockList : TBlockList);
+
+begin
+  Inherited Create;
+  FBlockList:=ABlockList;
+  FMaxHits:=1;
+end;
+
+Function TBlock.DrawingArea : PGtkWidget;
+
+begin
+  Result:=FBlockList.FBreakout.FDrawingArea;
+end;
+
+Function TBlock.PixMap : PgdkPixMap; 
+
+begin
+  Result:=FBlockList.PixMap;
+end;
+
+Procedure TBlock.CreateGC;
+
+begin
+  FGC:=gdk_gc_new(DrawingArea^.Window);
+  gdk_gc_set_foreground(FGC,FColor);
+  gdk_gc_set_fill(FGC,GDK_SOLID);
+  FNeedRedraw:=True;
+end;
+
+Procedure TBlock.Draw;
+
+begin
+  if FGC=Nil then
+    CreateGC;
+  if FNeedRedraw Then
+    begin
+    gdk_draw_rectangle(PGDKDrawable(Pixmap),FGC,-1,Left,Top,Width,Height);
+    FNeedRedraw:=False;
+   end;
+end;
+
+Function TBlock.Hit : Boolean;
+
+begin
+  Dec(FMaxHits);
+  Result:=FMaxHits=0;
+  If Result then
+    begin
+    FBlockList.FBreakOut.DrawBackground(FRect);
+    FBlockList.Remove(Self);
+    Free;
+    end;
+end;
+
+{ ---------------------------------------------------------------------
+    TBlockList implementation
+  ---------------------------------------------------------------------}
+  
+Constructor TBlockList.Create(BreakOut : TBreakOut);
+
+begin
+  FBreakOut:=BreakOut;
+end;
+
+Function TBlockList.DrawingArea : PGtkWidget;
+
+begin
+  Result:=FBreakOut.FDrawingArea;
+end;
+
+Destructor TBlockList.Destroy; 
+
+begin
+  If FColor<>Nil then
+    FreeMem(FColor);
+  FreeBlocks;
+end;
+
+Procedure TBlockList.DrawBlocks;
+
+Var
+  I : Longint; 
+
+begin
+  If Count=0 then
+    CreateBlocks;
+  For I:=0 to Count-1 do
+    TBlock(Items[i]).draw;
+end;
+
+Procedure TBlockList.DrawBlocks (Const Area : TGdkRectangle);
+
+Var
+  i : longint;
+  inters : TgdkRectangle;
+
+begin
+  For I:=0 to Count-1 do
+    With TBlock(Items[i]) do
+      FNeedRedraw:=gdk_rectangle_intersect(@area,@Frect,@inters)<>0;
+  DrawBlocks;    
+end;
+
+Function AllocateColor(R,G,B : Integer; Widget : PGtkWidget) : PGdkColor;
+
+begin
+  Result:=New(PgdkColor);
+  With Result^ do
+    begin
+    Pixel:=0;
+    Red:=R;
+    Blue:=B;
+    Green:=G;  
+    end;
+  gdk_colormap_alloc_color(gtk_widget_get_colormap(Widget),Result,true,False);
+end;
+
+Procedure TBlockList.CreateBlocks;
+
+Var
+  TotalHeight,TotalWidth,
+  Cellheight,CellWidth,
+  I,J : Integer;
+  Block : TBlock;
+  Min : Byte;
+  
+begin
+  FColor:=AllocateColor(0,0,$ffff,DrawingArea);
+  Min:=FSpacing div 2;
+  If Min<1 then 
+    Min:=1;
+  TotalWidth:=Drawingarea^.Allocation.Width;
+  TotalHeight:=DrawingArea^.Allocation.Height;
+  Cellheight:=TotalHeight Div TotalRows;
+  CellWidth:=TotalWidth div TotalColumns;
+  For I:=StartRow to StartRow+BlockRows-1 do
+    For J:=0 to TotalColumns-1 do
+    begin
+    Block:=TBlock.Create(Self);
+    With Block do
+      begin
+      Top:=TotalHeight-(CellHeight*I)+Min;
+      Left:=(CellWidth*J)+min;
+      Width:=CellWidth-2*min;
+      Height:=CellHeight-2*min;
+      Color:=Self.FColor;
+      FNeedRedraw:=True;
+      end;
+    add(Block);
+    end;
+end;
+
+Procedure TBlockList.FreeBlocks;
+
+Var
+  I : longint;
+
+begin
+  For I:=Count-1 downto 0 do
+    begin
+    TBlock(Items[i]).Free;
+    Delete(i);
+    end;
+end;
+
+Procedure TBlockList.CheckCollision (Ball: TBall);
+
+var
+  brect,ints : tgdkrectangle;
+  B : TBlock;
+  i : integer;
+  flipx,flipy : Boolean;
+    
+begin
+  For I:=Count-1 downto 0 do
+    begin
+    B:=TBlock(Items[i]);
+    BRect:=B.FRect;    
+    if gdk_rectangle_intersect(@Ball.Frect,@BRect,@ints)<>0 then
+      begin
+      FlipY:=((Ball.FpreviousTop>=(B.Top+B.Height)) and (Ball.CurrentSpeedY<0)) or
+             ((Ball.FpreviousTop+Ball.Height<=B.Top) and (Ball.CurrentSpeedY>0));
+      FlipX:=Not FlipY;
+      If FlipX then
+        FlipX:=((Ball.FPreviousLeft>=(B.Left+B.Width)) and (Ball.CurrentSpeedX<0)) or
+               (((Ball.FPreviousLeft+Ball.Width)<=B.Left) and (Ball.CurrentSpeedX>0));
+      Ball.FlipSpeed(FlipX,Flipy);
+      if B.Hit and not (Count=0) then 
+        gtk_widget_draw(DrawingArea,@BRect);
+      Break;
+      end;
+    end;
+end;
+
+{ ---------------------------------------------------------------------
+    TSprite implementation
+  ---------------------------------------------------------------------}
+
+Constructor TSprite.Create(DrawingArea: PGtkWidget);
+
+begin
+  Inherited Create;
+  FDrawingArea:=DrawingArea;
+  Visible:=False;
+end;
+
+Procedure TSprite.CreateSpriteFromData(SpriteData : PPGChar);
+
+begin
+  FPixMap:=gdk_pixmap_create_from_xpm_d(FDrawingArea^.Window, 
+                                        @FBitmap,
+                                        Nil,
+                                        SpriteData);
+end;
+
+Procedure TSprite.Draw;    
+
+Var
+  gc : PGDKGc;
+  
+begin
+  if Visible then
+    begin
+    if FPixMap=Nil then
+      CreatePixMap;    
+    gc:=gtk_widget_get_style(FDrawingArea)^.fg_gc[GTK_STATE_NORMAL];
+    gdk_gc_set_clip_origin(gc,Left,Top);
+    gdk_gc_set_clip_mask(gc,FBitmap);
+    if FDrawPixMap<>Nil then
+      gdk_draw_pixmap(FDrawPixMap,gc,FPixMap,0,0,Left,Top,Width,Height)
+    else
+      gdk_draw_pixmap(FDrawPixMap{FDrawingArea^.window},gc,FPixMap,0,0,Left,Top,Width,Height);
+    gdk_gc_set_clip_mask(gc,Nil);  
+    end;
+end;
+
+Function TSprite.GetChangeRect (Var Rect : TGDkRectAngle) : Boolean;
+
+begin
+  Result:=(FPreviousLeft<>Left) or (FPreviousTop<>Top);
+  If Result then
+    With Rect do
+      begin
+      x:=FPreviousLeft;
+      y:=FPreviousTop;
+      Width:=Abs(Left-FPreviousLeft)+self.Width;
+      height:=Abs(Top-FPreviousTop)+self.Height;
+      end;
+end;
+
+Procedure TSprite.SavePosition;
+
+begin
+  FPreviousLeft:=Left;
+  FPreviousTop:=Top;
+end;
+
+
+{ ---------------------------------------------------------------------
+    TPad implementation
+  ---------------------------------------------------------------------}
+
+Const
+  PadHeight = 10;
+  PadWidth = 40; 
+  PadBitmap : Array[1..13] of pchar = (
+    '40 10 2 1',
+    '  c none',
+    'x c #ff0000',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
+  );
+
+Constructor TPad.Create(DrawingArea: PGtkWidget);
+
+begin
+  Inherited Create(DrawingArea);
+  FSpeed:=6;
+  FSlope:=50;
+  Visible:=True;
+end;
+
+Procedure TPad.CreatePixMap; 
+
+begin
+  CreateSpriteFromData(@PadBitmap[1]);
+  Width:=PadWidth;
+  Height:=PadHeight;
+  InitialPosition;
+end;
+
+Procedure TPad.InitialPosition;
+
+begin
+  Left:=(FDrawingArea^.Allocation.Width-Width) div 2;
+  Top:=FDrawingArea^.Allocation.Height-(2*Height);
+  FCurrentSpeed:=0;
+end;
+
+Procedure TPad.Step;
+
+begin
+  SavePosition;
+  Left:=Left+FCurrentSpeed;
+  if Left<=0 then
+    begin
+    FCurrentSpeed:=-FCurrentSpeed;
+    Left:=0;
+    end
+  else if Left+Width>=FDrawingArea^.allocation.width then
+    begin
+    FCurrentSpeed:=-FCurrentSpeed;
+    Left:=FDrawingArea^.allocation.width-Width;
+    end;
+end;
+
+Procedure TPad.GoLeft;
+
+begin
+  FCurrentSpeed:=-FSpeed;
+end;
+
+Procedure TPad.GoRight;
+
+begin
+  FCurrentSpeed:=FSpeed;
+end;
+
+Procedure TPad.Stop;
+
+begin
+  FCurrentSpeed:=0;
+end;
+
+{ ---------------------------------------------------------------------
+    TBall implementation
+  ---------------------------------------------------------------------}
+
+Const
+  BallHeight = 10;
+  BallWidth = 10; 
+  BallBitmap : Array[1..13] of pchar = (
+    '10 10 2 1',
+    '  c none',
+    'x c #ffffff',
+    '    xx    ',
+    '  xxxxxx  ',
+    ' xxxxxxxx ',
+    ' xxxxxxxx ',
+    'xxxxxxxxxx',	
+    'xxxxxxxxxx',
+    ' xxxxxxxx ',	
+    ' xxxxxxxx ',
+    '  xxxxxx  ',
+    '    xx    '
+  );
+
+
+Constructor TBall.Create(BreakOut : TBreakOut);
+
+begin
+  Inherited Create(BreakOut.FDrawingArea);
+  FBreakOut:=breakout;
+  FCurrentSpeedY:=-100;
+  FCurrentSpeedX:=0;
+  FSpeedFactor:=10;
+  Visible:=True;
+end;
+
+Procedure TBall.CreatePixMap; 
+
+begin
+  CreateSpriteFromData(@BallBitmap[1]);
+  Width:=BallWidth;
+  Height:=BallHeight;
+end;
+
+
+Procedure TBall.Step;
+
+begin
+  SavePosition;
+  Left :=Left + Round((FCurrentSpeedX*FSpeedFactor/100));
+  Top  :=Top  + Round((FCurrentSpeedY*FSpeedFactor/100));
+  if Left<=1 then
+    begin
+    FlipSpeed(True,False);
+    Left:=1;
+    end
+  else if Left+Width>=FDrawingArea^.allocation.width then
+    begin
+    FlipSpeed(True,False);
+    Left:=FDrawingArea^.allocation.width-Width-1;
+    end;
+  if Top<=1 then
+    begin
+    FlipSpeed(False,True);
+    Top:=1;
+    end
+  else if Top+Height>=FDrawingArea^.allocation.Height then
+    FBreakOut.LostBall
+end;
+
+Procedure TBall.SetSpeed(Value : Integer);
+
+begin
+  If Value<-FMaxXspeed then 
+    Value:=-FMaxXSpeed
+  else if Value>FMaxXspeed then
+    Value:=FMaxXspeed;
+  FCurrentSpeedX:=Value;
+  If FCurrentSpeedY>0 then
+    FCurrentSpeedY:=100-Abs(FCurrentSpeedX)
+  else
+    FCurrentSpeedY:=-100+Abs(FCurrentSpeedX);
+end;
+
+Procedure TBall.IncSpeed (Value: Integer);
+
+begin
+  FSpeedFactor:=FSpeedFactor+Value;
+  If FSpeedFactor<10 then
+    FSpeedFactor:=10;
+end;
+
+Procedure TBall.FlipSpeed (FlipX,FlipY : Boolean);
+
+begin
+  If FlipX then 
+    FCurrentSpeedX:=-FCurrentSpeedX;
+  If FlipY then 
+    FCurrentSpeedY:=-FCurrentSpeedY;
+end;
+
+{ ---------------------------------------------------------------------
+    TBreakout implementation
+  ---------------------------------------------------------------------}
+  
+Constructor TBreakOut.Create (DrawingArea : PGtkWidget);
+
+begin
+  FDrawingArea:=DrawingArea;
+  FBlockList:=TBlockList.Create (Self);
+  FPad:=TPad.Create(FDrawingArea);
+  FBalls:=5;
+end;
+
+
+Procedure TBreakOut.CheckCollision;
+
+Var
+  Inters :TGdkrectangle;
+
+begin
+  If Assigned(FBall) then
+   begin
+   if gdk_rectangle_intersect(@FBall.FRect,@FPad.Frect,@inters)<>0 then
+     If (FBall.FPreviousTop<FPad.Top) and (FBall.FCurrentSpeedY>0) then
+       begin
+       FBall.FlipSpeed(False,True);
+       If (FPad.CurrentSpeed<>0) then
+         if (FBall.FCurrentSpeedX*FPad.CurrentSpeed)>0 then
+           FBall.IncSpeed(HitAccelleration)
+         else
+           FBall.IncSpeed(-HitAccelleration);
+       FBall.CurrentSpeedX:=FBall.CurrentSpeedX+(Round(((FBall.Left+(FBall.Width div 2)) - (FPad.left+Fpad.Width div 2)) * (FPad.Slope / 100)));
+       end; 
+   FBlockList.CheckCollision(FBall);  
+   end;
+end;
+
+Procedure TBreakOut.Step;
+
+begin
+  FPad.Step;
+  If Assigned(FBall) then
+    FBall.Step;
+  CheckCollision;
+  If FBlockList.Count=0 then
+    NextLevel;
+  if Not Assigned(FBall) and (FBalls=0) then
+    GameOver;
+end;
+
+Procedure TBreakOut.CreateGC;
+
+begin
+  FBGGC:=gdk_gc_new(FDrawingArea^.Window);
+  FBackGroundColor:=AllocateColor(0,0,0,FDrawingArea);
+  gdk_gc_set_foreground(FBGGC,FBackGroundColor);
+  gdk_gc_set_fill(FBGGC,GDK_SOLID);
+end;
+
+Procedure TBreakOut.DrawBackGround (Area : TGdkrectAngle);
+
+begin
+  With Area do
+    begin
+    gdk_draw_rectangle(PGDKDrawable(FPixMap),FBGGC,-1,x,y,Width+1,Height+1);
+    end;
+end;
+
+Procedure TBreakOut.DrawBoard(Exposed : PGdkEventExpose);
+
+begin
+  If FBGGC=Nil then
+    begin
+    CreateGC;  
+    end;
+  DrawBackGround(Exposed^.Area);
+end;
+
+Procedure TBreakOut.CreatePixMap;
+
+begin
+  If FPixMap<>Nil then
+    GDK_pixmap_unref(FPixMap);
+  With FDrawingArea^ do
+    FPixMap:=gdk_pixmap_new(Window,Allocation.Width,Allocation.Height,-1);
+  FBlockList.PixMap:=FPixMap;
+  FPad.FDrawPixMap:=FPixMap;
+  If Assigned(FBall) then
+    FBall.FDrawPixMap:=FPixMap;
+end;
+
+Procedure TBreakOut.CopyPixMap(Area : TGdkRectangle);
+
+begin
+  gdk_draw_pixmap(FDrawingArea^.Window,
+                  gtk_widget_get_style(FDrawingArea)^.fg_gc[GTK_WIDGET_STATE(FDrawingArea)],
+                  FPixMap,
+                  area.x,area.y,
+                  area.x,area.y,
+                  area.width,area.height); 
+end;
+
+Procedure TBreakOut.Draw(Exposed : PGDKEventExpose);
+
+Var
+  Rect : TGdkRectangle;
+
+begin
+  if FPixMap=Nil then 
+    CreatePixMap;
+  // draw whatever needed on pixmap.
+  if Exposed<>Nil then
+    begin
+    DrawBoard(Exposed);
+    FBlockList.DrawBlocks(exposed^.area)
+    end
+  else
+    begin
+    If Assigned(FBall) then 
+      if FBall.GetChangeRect(Rect) then
+        begin
+        DrawBackground(Rect);
+        FBLockList.drawBlocks(Rect);
+        end;  
+    if FPad.GetChangeRect(Rect) then
+      DrawBackground(Rect)
+    end;
+
+  FPad.Draw;
+  if Assigned(FBall) Then
+    FBall.draw;
+  
+  If Exposed<>Nil then
+    CopyPixMap(Exposed^.Area);
+  If assigned(FBall) then
+    if FBall.GetChangeRect(Rect) then
+      CopyPixMap(Rect);
+  if FPad.GetChangeRect(Rect) then
+    CopyPixMap(Rect);
+  IF Assigned(FBall) then
+    CopyPixMap(FBall.FRect);
+  CopyPixMap(FPad.FRect);
+end;
+
+
+Procedure TBreakout.Redrawgame;
+
+Var
+  Rect : TgdkRectangle;
+
+begin
+  Rect.X:=FDrawingArea^.allocation.x;
+  Rect.Y:=FDrawingArea^.allocation.y;
+  Rect.Width:=FDrawingArea^.allocation.Width;
+  Rect.Height:=FDrawingArea^.allocation.Height;
+  gtk_Widget_draw(FDrawingArea,@rect)
+end;
+
+
+Procedure TBreakOut.FreeBall;
+
+begin
+  FBall.Free;
+  FBall:=Nil;
+end;
+
+Procedure TbreakOut.NextBall;
+
+begin
+  If FBall=Nil then
+    begin
+    FBall:=TBall.Create(Self);
+    FBall.Top:=FPad.Top-1;
+    FBall.Left:=FPad.Left + (FPad.Width div 2);
+    FBall.CurrentSpeedX:=FPad.CurrentSpeed*5;
+    FBall.FPreviousTop:=FBall.Top;
+    FBall.FPreviousLeft:=FBall.Left;
+    FBall.FDrawPixMap:=Self.FPixMap;
+    FBall.Draw;
+    end;
+end;
+
+Procedure TBreakOut.NextLevel;
+
+Var
+  Area : TGdkRectangle;
+
+begin
+  If Assigned(FBall) then
+    FreeBall;
+  FPad.FSpeed:=FPad.Speed+LevelAccelleration;
+  FPad.InitialPosition;
+  RedrawGame;
+end;
+
+Procedure TBreakout.LostBall;
+
+begin
+  Dec(FBalls);
+  If FBalls=0 then 
+    GameOver;
+  FreeBall;
+  Fpad.InitialPosition;
+  RedrawGame;
+end;
+
+Procedure TBreakout.GameOver;
+
+begin
+end;
+
+end.
+  

+ 104 - 0
docs/gtk5ex/breakout.pp

@@ -0,0 +1,104 @@
+program breakout;
+
+{$mode objfpc}
+
+uses glib,gdk,gtk,blocks;
+
+Type 
+  TBreakOutWindow = Class(TObject)
+  Public
+    window, 
+    area : PGtkWidget;
+    BreakOut : TBreakOut;
+  end;
+
+Var
+  GameWindow : TBreakOutWindow;
+  
+Function close_application( widget : PGtkWidget ;
+                        event : PGdkEvent;
+                        data : gpointer) : boolean; cdecl;
+Begin
+  gtk_main_quit();
+  close_application := false;
+End;
+
+function Exposed(Widget: PGtkWidget;event : PGdkEventExpose; Data : gpointer) : Integer; cdecl;
+
+begin
+{  gdk_window_clear_area (widget^.window,
+                         event^.area.x, 
+                         event^.area.y,
+                         event^.area.width, 
+                         event^.area.height);
+}  TBreakOutWindow(Data).BreakOut.Draw(Event);
+  result:=0;
+end;
+
+function KeyPress (Widget: PGtkWidget;event : PGdkEventKey; Data : gpointer) : Integer; cdecl;
+
+begin
+  with TBreakOutWindow(Data).BreakOut do
+    Case event^.keyval of
+      gdk_left  : Pad.Goleft;
+      gdk_right : Pad.GoRight;
+      gdk_down  : Pad.Stop;
+      Ord(' ')  : NextBall;
+    end;    
+  Result:=0; 
+end;
+
+function Step (data : Gpointer): integer;cdecl;
+
+Var
+ Rect : TGdkRectangle;
+
+begin
+  With TBreakOutWindow(Data) do
+    begin
+    With Breakout do
+      begin
+      Step;
+      Draw(Nil);
+      end; 
+    end;
+  Result:=integer(True);
+end;
+
+Begin
+  // Initialize GTK and create the main window
+  gtk_init( @argc, @argv );
+  GameWindow:=TBreakOutWindow.Create;
+  With GameWindow do
+    begin
+    window := gtk_window_new( GTK_WINDOW_TOPLEVEL );
+    gtk_window_set_policy(PgtkWindow(Window),0,0,1);
+    gtk_signal_connect (GTK_OBJECT (window), 'delete_event',
+            GTK_SIGNAL_FUNC( @close_application ), NIL);
+    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+    area := gtk_drawing_area_new();
+    gtk_container_add( GTK_CONTAINER(window), Area);
+    BreakOut:=TBreakOut.Create(area);
+    With BreakOut.BlockList do
+      begin
+      TotalRows:=20;
+      TotalColumns:=10;
+      StartRow:=15;
+      BlockRows:=5;
+      BlockSpacing:=2;
+      end;
+    gtk_signal_connect (GTK_OBJECT (area),'expose_event',
+                        GTK_SIGNAL_FUNC(@Exposed),GameWindow);
+    gtk_drawing_area_size (PGTKDRAWINGAREA(area),600,400);
+    // key handling.
+    gtk_widget_set_events(window,GDK_KEY_RELEASE_MASK);
+    gtk_signal_connect(PGTKObject(Window),'key_press_event',
+                       GTK_SIGNAL_FUNC(@KeyPress),GameWindow);
+    // Timer handling.
+    gtk_timeout_add(50,@Step,GameWindow);
+    gtk_widget_show_all( window ); 
+    gtk_main();
+    end;
+End.
+  
+end.

+ 118 - 0
docs/gtk5ex/graphics.pp

@@ -0,0 +1,118 @@
+program graphics;
+
+{$mode objfpc}
+{$h+}
+
+uses glib,gdk,gtk,sysutils;
+
+var 
+  window, 
+  area : PGtkWidget;
+
+Function close_application( widget : PGtkWidget ;
+                        event : PGdkEvent;
+                        data : gpointer) : boolean; cdecl;
+Begin
+  gtk_main_quit();
+  close_application := false;
+End;
+
+Function AllocateColor(R,G,B : Integer; Widget : PGtkWidget) : PGdkColor;
+
+begin
+  Result:=New(PgdkColor);
+  With Result^ do
+    begin
+    Pixel:=0;
+    Red:=R;
+    Blue:=B;
+    Green:=G;  
+    end;
+  gdk_colormap_alloc_color(gtk_widget_get_colormap(Widget),Result,true,False);
+end;
+
+
+function Exposed(Widget: PGtkWidget;event : PGdkEventExpose; Data : gpointer) : Integer; cdecl;
+
+Const 
+  Triangle : Array[1..4] of TgdkPoint = 
+            ((X:10;Y:195),(X:110;Y:195),(X:55;Y:145),(X:10;Y:195));
+  LineStyles : Array[1..5] of TgdkLineStyle = 
+          (GDK_LINE_SOLID, GDK_LINE_ON_OFF_DASH, GDK_LINE_DOUBLE_DASH,
+          GDK_LINE_ON_OFF_DASH, GDK_LINE_SOLID);
+  capstyles : Array[1..5] of TgdkCapStyle = 
+          (GDK_CAP_ROUND,GDK_CAP_NOT_LAST, GDK_CAP_BUTT,  GDK_CAP_PROJECTING,
+          GDK_CAP_NOT_LAST);
+          
+Var
+  SegTriangle : Array[1..3] of TgdkSegment;
+  Win : pgdkWindow;
+  gc : PgdkGC;
+  i,seg : Integer; 
+  font : PgdkFont;
+  Angle1,Angle2 : Longint;
+    
+begin
+  gc:=gdk_gc_new(widget^.Window);
+  Win:=widget^.window;
+  With Event^.area do
+    gdk_window_clear_area (win,x,y,width,height);
+  gdk_gc_set_foreground(gc,allocatecolor(0,0,0,Widget));
+  gdk_draw_rectangle(win,gc,0,5,5,590,390);
+//  gdk_draw_rectangle(win,gc,-1,15,15,570,370);
+  gdk_gc_set_foreground(gc,allocatecolor(0,0,$ffff,Widget));
+  for I:=10 to 50 do
+    gdk_draw_point(win,gc,I*10,100);
+  gdk_gc_set_foreground(gc,allocatecolor($ffff,0,0,Widget));
+  for I:=10 to 50 do
+    begin
+    gdk_gc_set_line_attributes(gc,6,LineStyles[i div 10],CapStyles[i div 10],GDK_JOIN_MITER);
+    gdk_draw_line(win,gc,I*10,20,I*10,90)
+    end;
+  gdk_gc_set_line_attributes(gc,1,GDK_LINE_SOLID,GDK_CAP_BUTT,GDK_JOIN_MITER);
+  gdk_gc_set_foreground(gc,allocatecolor($ffff,0,$ffff,Widget));
+  seg:=(360 div 20) * 64;
+  For I:=1 to 20 do
+    gdk_draw_arc(win,gc,0,220-I*4,200-i*4,8*i,8*i,i*seg,seg*19);
+  For I:=1 to 20 do
+    gdk_draw_arc(win,gc,-1,380-I*4,200-i*4,8*i,8*i,(i-1)*seg,seg);
+  gdk_gc_set_foreground(gc,allocatecolor(0,$ffff,$ffff,Widget));
+  gdk_draw_polygon(win,gc,0,@triangle[1],4);  
+  For I:=1 to 4 do
+    Triangle[i].Y:=400-Triangle[i].y;
+  gdk_draw_polygon(win,gc,-1,@triangle[1],4);  
+  gdk_gc_set_foreground(gc,allocatecolor(0,$ffff,0,Widget));
+  For I:=1 to 4 do
+    Triangle[i].X:=600-Triangle[i].x;
+  gdk_draw_lines(win,gc,@triangle[1],4);
+  For I:=1 to 3 do
+    begin
+    SegTriangle[i].X1:=Triangle[i].X;
+    SegTriangle[i].Y1:=400-Triangle[i].Y;
+    SegTriangle[i].X2:=Triangle[i+1].X;
+    SegTriangle[i].Y2:=400-Triangle[i+1].Y;
+    end;
+  gdk_draw_segments(win,gc,@segtriangle[1],3);
+  font:=gdk_font_load('-*-helvetica-bold-r-normal--*-120-*-*-*-*-iso8859-1');
+  gdk_gc_set_foreground(gc,allocatecolor($ffff,$ffff,0,Widget));
+  For I:=1 to 4 do
+    gdk_draw_string(win,font,gc,I*100,300,Pchar(format('String %d',[i])));
+  result:=0;
+end;
+
+Begin
+  // Initialize GTK and create the main window
+  gtk_init( @argc, @argv );
+  window := gtk_window_new( GTK_WINDOW_TOPLEVEL );
+  gtk_window_set_policy(PgtkWindow(Window),0,0,1);
+  gtk_signal_connect (GTK_OBJECT (window), 'delete_event',
+          GTK_SIGNAL_FUNC( @close_application ), NIL);
+  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+  area := gtk_drawing_area_new();
+  gtk_container_add( GTK_CONTAINER(window), Area);
+  gtk_signal_connect (GTK_OBJECT (area),'expose_event',
+                      GTK_SIGNAL_FUNC(@Exposed),Nil);
+  gtk_drawing_area_size (PGTKDRAWINGAREA(area),600,400);
+  gtk_widget_show_all( window ); 
+  gtk_main();
+end.