Bare Game Example: Draw

The following is a walk through of the Bare Game draw example located in the
examples/draw
folder of your Bare Game install location. The example demonstrates how to define a game window, load textures, draw a background, draw a sprite, read input, and how to handle game logic and render logic.

The scene

The example creates a simple scene with a background image of a cartoon house and fields. The mouse cursor is a neon pointer and swings back and forth from its pointing location. Holding down the left mouse button adds vector line segments to the canvas path. Instructions are drawn using a font writer at different locations around the screen.
The following table lists the keyboard commands
  • ESC
    Exit the program
  • F1
    Toggle window full screen and windowed modes
  • F2
    Change to a perspective view
  • F3
    Change to an orthographic view
A few notes about the example. The perspective and orthographic views serve to demonstrate that in Bare Game, even when it seems as if you are in a 2D world, it's actually 3D all the time. You can move, rotate, and scale sprites, text, backgrounds, and canvas paths in three dimensions at anytime.

Video

Here is a video capture of the draw example begin run. Currently you can write Bare Game programs on Windows and Linux. A Macintosh capable version is soon to be released with Bare Game version 2.

Program listing

Below is a listing of the draw example program. You can research the help reference documentation to the Bare Game library on its official website. Comments are provided in the source code to help new users understand the structure. Although no sound playback or joystick input is used in this example, Bare Game is perfectly capable of using those features.
program draw;

{$mode delphi}

uses
  Bare.System,
  Bare.Game,
  Bare.Geometry,
  Bare.Graphics,
  Bare.Animation,
  Bare.Example,
  Bare.Interop.OpenGL;

{ TDrawExample }

type
  TDrawExample = class(TWorldWindow)
  private
    FBackground: TBackgroudSprite;
    FSprite: TSprite;
    FDrawing: Boolean;
    FEasing: TEasing;
    FPerspectiveView: Boolean;
    FPerspectiveTime: Float;
    FPerspectiveFactor: Float;
    FX, FY: Float;
  protected
    procedure RenderInitialize; override;
    procedure RenderFinalize; override;
    procedure Logic(Stopwatch: TStopwatch); override;
    procedure Render(Stopwatch: TStopwatch); override;
  end;


const
  TexCracked = 0;
  TexBackground = TexCracked + 1;
  TexCursor = TexBackground + 1;
  TexCount = TexCursor + 1;

procedure TDrawExample.RenderInitialize;
begin
  inherited RenderInitialize;
  { Change the window caption }
  Caption := 'Drawing Demo';
  { We're drawing our own cursor }
  Mouse.Visible := False;
  { We're going to use an easing in this sample }
  Easings.RegisterDefaults;
  FEasing := Easings['Bounce'];
  FPerspectiveTime := -1;
  { Setup our pen }
  Pen.Color := clHotPink;
  Pen.Width := 10;
  { Make room for 3 images }
  Textures.Generate(TexCount);
  Textures.Load('cracked.jpg', TexCracked);
  Textures.Load('background.jpg', TexBackground);
  Textures.Load('cursor.png', TexCursor);
  { If you create it }
  FBackground := TBackgroudSprite.Create(World);
  FBackground.Origin := Vec(0, 0);
  { This line creates a sprite object }
  FSprite := TSprite.Create(World);
  { This line defines the image we want to use for the sprite }
  FSprite.Texture := Textures[TexCursor];
  { This line sets how big we want out sprite to be in width and height }
  FSprite.Size := Vec(100, 148);
  { This line sets the point where a sprite is scaled and rotated in the range from 0 to 1 }
  FSprite.Origin := Vec(0.2, 0.1);
end;

procedure TDrawExample.RenderFinalize;
begin
  { You must destroy it }
  FSprite.Free;
  FBackground.Free;
  inherited RenderFinalize;
end;

procedure TDrawExample.Logic(Stopwatch: TStopwatch);
begin
  { Place your game logic code here }
  if (Keyboard.Key[VK_F2]) and (not FPerspectiveView) then
  begin
    { If the F2 key is pressed switch to a perspective view }
    FPerspectiveView := True;
    FPerspectiveTime := Stopwatch.Time;
  end;
  if (Keyboard.Key[VK_F3]) and FPerspectiveView then
  begin
    { If the F3 key is pressed switch to am othographic view }
    FPerspectiveView := False;
    FPerspectiveTime := Stopwatch.Time;
  end;
  { Animate the view changes using an easing }
  FPerspectiveFactor := Interpolate(FEasing, Stopwatch.Time - FPerspectiveTime);
  if not FPerspectiveView then
    FPerspectiveFactor := 1 - FPerspectiveFactor;
  if mbLeft in Mouse.Buttons then
  begin
    { Draw when the left mouse button is down }
    if not FDrawing then
    begin
      Canvas.Path.Clear;
      Canvas.Path.MoveTo(Mouse.X, Mouse.Y)
    end
    else if (Mouse.X <> FX) or (Mouse.Y <> FY) then
      Canvas.Path.LineTo(Mouse.X, Mouse.Y);
    FDrawing := True;
  end
  else
    FDrawing := False;
  { Capture the last mouse X and Y coords }
  FX := Mouse.X;
  FY := Mouse.Y;
end;

procedure TDrawExample.Render(Stopwatch: TStopwatch);
const
  Instructions = 'Press the left mouse button to draw';
  Status = 'Time: %.2f'#13#10'FPS: %d';
  Help = 'Press ESC to terminate - F1 Fullscreen toggle'#13#10 +
    'F2 Perspective view - F3 Orthographic view';
begin
  { Place your game render code here }
  World.Update;
  { Make our cracked fill the screen }
  FBackground.Size.X := World.Width;
  FBackground.Size.Y := World.Height;
  FBackground.Texture := Textures[TexCracked];
  FBackground.Draw;
  { You can mix in opengl code if you want, here we add perspective manually,
    you could also use the camera class }
  glRotatef(20 * FPerspectiveFactor, 0, 1, 0);
  glRotatef(20 * FPerspectiveFactor, 1, 0, 0);
  glTranslatef(10 * FPerspectiveFactor, -8 * FPerspectiveFactor, -4 * FPerspectiveFactor);
  { Make our background fill the world }
  FBackground.Texture := Textures[TexBackground];
  FBackground.Draw;
  { Write some instructions, scale factor 1, horizontally and vertically centered }
  Font.Write(Instructions, 1, World.Width / 2, World.Height / 2, justifyCenter);
  { Stroke the current path }
  Canvas.Stroke(Pen, False);
  { Move the cursor sprite around }
  FSprite.Position := Vec(FX, FY, 0);
  FSprite.Rotation.Z := Sin(Stopwatch.Time * 4) * 20;
  FSprite.Draw;
  { Write some more text }
  Font.Write(Format(Status, [Stopwatch.Time, Stopwatch.Framerate]), 0.75, 1, 0);
  Font.Write(Help, 0.75, World.Width / 2, World.Height - 50, justifyCenter);
end;

begin
  Application.Run(TDrawExample);
end.