Using Records in Smart Pascal
A record is a composite type that allows related variables to be grouped together. In Smart Pascal, a record may also contain procedures and functions to process the data in its variables. The first example demonstrates a record with no routines. The code of the first three demonstrations compiles with Versions 2.2 and 3.0 of Smart Mobile Studio.
unit Unit1; interface uses System.Types, SmartCL.System, SmartCL.Components, SmartCL.Application, SmartCL.Game, SmartCL.GameApp, SmartCL.Graphics; type TCanvasProject = class(TW3CustomGameApplication) protected procedure ApplicationStarting; override; procedure ApplicationClosing; override; procedure PaintView(Canvas: TW3Canvas); override; end; implementation type T_Triangle = record Vertices: array[1..3, 1..2] of integer; Colour: string; Filled: Boolean; end; var MyTriangle: T_Triangle; procedure TCanvasProject.ApplicationStarting; begin inherited; MyTriangle.Vertices := [[100, 0], [150, 100], [100, 200]]; MyTriangle.Colour := 'red'; MyTriangle.Filled := true; GameView.Delay := 20; GameView.StartSession(True); end; procedure TCanvasProject.ApplicationClosing; begin GameView.EndSession; inherited; end; procedure TCanvasProject.PaintView(Canvas: TW3Canvas); begin // Clear background Canvas.FillStyle := 'rgb(0, 0, 99)'; Canvas.FillRectF(0, 0, GameView.Width, GameView.Height); Canvas.FillStyle := MyTriangle.Colour; Canvas.StrokeStyle := MyTriangle.Colour; // Draw triangle Canvas.BeginPath; Canvas.MoveToF(MyTriangle.Vertices[1, 1], MyTriangle.Vertices[1, 2]); Canvas.LineToF(MyTriangle.Vertices[2, 1], MyTriangle.Vertices[2, 2]); Canvas.LineToF(MyTriangle.Vertices[3, 1], MyTriangle.Vertices[3, 2]); Canvas.ClosePath; if MyTriangle.Filled = true then Canvas.Fill else Canvas.Stroke; end; end.
You receive auto-completion options from code insight when you have (1) defined your record, (2) declared a variable of that type, then (3) keyed-in the variable name followed by a period:

Code Insight
Select your variable with a mouse click or the vertical arrow keys and copy it to the editor with a double click or by pressing Return/Enter.
Arrays of Records
When processing multiple records of the same type you will find it convenient to put them into an array. The array of records in this example enables us to render the triangles concisely with a for-in loop.
unit Unit1; interface uses System.Types, SmartCL.System, SmartCL.Components, SmartCL.Application, SmartCL.Game, SmartCL.GameApp, SmartCL.Graphics; type TCanvasProject = class(TW3CustomGameApplication) protected procedure ApplicationStarting; override; procedure ApplicationClosing; override; procedure PaintView(Canvas: TW3Canvas); override; end; implementation type T_Triangle = record Vertices: array[1..3, 1..2] of integer; Colour: string; Filled: Boolean; end; var Triangles: array[1..3] of T_Triangle; procedure TCanvasProject.ApplicationStarting; begin inherited; Triangles[1].Vertices := [[100, 0], [150, 100], [100, 200]]; Triangles[1].Colour := 'red'; Triangles[1].Filled := true; Triangles[2].Vertices := [[150, 0], [200, 100], [150, 200]]; Triangles[2].Colour := 'green'; Triangles[2].Filled := false; Triangles[3].Vertices := [[200, 0], [250, 100], [200, 200]]; Triangles[3].Colour := 'yellow'; Triangles[3].Filled := true; GameView.Delay := 20; GameView.StartSession(True); end; procedure TCanvasProject.ApplicationClosing; begin GameView.EndSession; inherited; end; procedure TCanvasProject.PaintView(Canvas: TW3Canvas); begin // Clear background Canvas.FillStyle := 'rgb(0, 0, 99)'; Canvas.FillRectF(0, 0, GameView.Width, GameView.Height); // Draw triangles for var Triangle in Triangles do begin Canvas.FillStyle := Triangle.Colour; Canvas.StrokeStyle := Triangle.Colour; Canvas.BeginPath; Canvas.MoveToF(Triangle.Vertices[1, 1], Triangle.Vertices[1, 2]); Canvas.LineToF(Triangle.Vertices[2, 1], Triangle.Vertices[2, 2]); Canvas.LineToF(Triangle.Vertices[3, 1], Triangle.Vertices[3, 2]); Canvas.ClosePath; if Triangle.Filled = true then Canvas.Fill else Canvas.Stroke; end; end; end.
The Inbuilt TRect Record
The next example uses the Create, CreateSized, MoveBy and Intersect routines of the inbuilt TRect record (in the System.Types unit). The mobile moves diagonally until any further movement would make it intersect with the obstacle. Use of the inbuilt record with its well-named routines makes the code tight and easy to follow.
unit Unit1; interface uses System.Types, SmartCL.System, SmartCL.Components, SmartCL.Application, SmartCL.Game, SmartCL.GameApp, SmartCL.Graphics; type TCanvasProject = class(TW3CustomGameApplication) protected procedure ApplicationStarting; override; procedure ApplicationClosing; override; procedure PaintView(Canvas: TW3Canvas); override; end; implementation var Mob, Obstacle, Intersection: TRect; procedure TCanvasProject.ApplicationStarting; begin inherited; Mob := TRect.Create(0, 0, 20, 10); Obstacle := TRect.CreateSized(200, 200, 20, 20); GameView.Delay := 20; GameView.StartSession(True); end; procedure TCanvasProject.ApplicationClosing; begin GameView.EndSession; inherited; end; procedure TCanvasProject.PaintView(Canvas: TW3Canvas); begin // Clear background Canvas.FillStyle := 'rgb(0, 0, 99)'; Canvas.FillRectF(0, 0, GameView.Width, GameView.Height); // Draw obstacle and mobile Canvas.FillStyle := 'black'; Canvas.FillRect(Obstacle); Canvas.FillStyle := 'red'; Canvas.FillRect(Mob); Mob.MoveBy(1, 1); if Mob.Intersect(Obstacle, Intersection) then Mob.MoveBy(-1, -1); end; end.
Other Inbuilt Records
If you need rectangles with greater precision you can use the TRectF record. Other types in the System.Types unit that you may find useful in your games include TPoint, TPointArray, TPointF and TPointArrayF. The Distance and AngleTo functions of TPoint made this demonstration easy to write. The code follows the application in action. You should see a yellow line from the centre of a blue frame to the pointer as you move the mouse and read the angle and distance of the pointer from the centre. If the application does not work, please use another browser such as Chrome. If you see no display at school, the security system might have blocked it. You can try instead this direct link to the program running on its own page.
We developed this example with Version 2.2 of Smart Mobile Studio. Add System.Types.Graphics to the uses clause and change the line Canvas.Font := '10pt verdana'; to Canvas.FontStyle := '10pt verdana'; when using Version 3.0.
unit Unit1; interface uses System.Types, SmartCL.System, SmartCL.Components, SmartCL.Application, SmartCL.Game, SmartCL.GameApp, SmartCL.Graphics; type TCanvasProject = class(TW3CustomGameApplication) protected procedure ApplicationStarting; override; procedure ApplicationClosing; override; procedure PaintView(Canvas: TW3Canvas); override; end; implementation var Centre, MousePos: TPoint; Angle, Distance: real; procedure TCanvasProject.ApplicationStarting; begin inherited; GameView.OnMouseMove := procedure(o : TObject; ss : TShiftState; x, y : integer) begin MousePos.X := x; MousePos.Y := y; end; Centre.X := GameView.Width div 2; Centre.Y := GameView.Height div 2; GameView.Delay := 1; GameView.StartSession(false); end; procedure TCanvasProject.ApplicationClosing; begin GameView.EndSession; inherited; end; procedure TCanvasProject.PaintView(Canvas: TW3Canvas); begin // Clear background Canvas.FillStyle := 'rgb(0, 0, 99)'; Canvas.FillRectF(0, 0, GameView.Width, GameView.Height); // Find distance and angle Distance := Centre.Distance(MousePos); Angle := Centre.AngleTo(MousePos) * 180 / Pi; // Draw line from centre to pointer Canvas.StrokeStyle := 'yellow'; Canvas.BeginPath; Canvas.LineF(Centre.X, Centre.Y, MousePos.X, MousePos.Y); Canvas.Stroke; // Draw angle and distance on top left of screen Canvas.Font := '10pt verdana'; Canvas.FillStyle := 'rgb(255, 255, 255)'; Canvas.FillTextF('Angle: ' + IntToStr(Round(Angle)) + ' Distance: ' + IntToStr(Round(Distance)), 10, 20, MAX_INT); end; end.