Using Widgets to Provide Options to a Canvas Project

Introduction

This demonstration shows you how to use a TW3Slider and TW3ComboBox in a canvas project. This should be sufficient to enable you to use other widgets such as TW3ListBox and TW3EditBox that are normally dropped onto a form. Use the combo box to change the colour of the mob and the slider to change its width. We demonstrate the use of TW3Buttons in the Input section. The preceding page describes an alternative method for providing options, probably with better performance, using a form-based project linked to a canvas project. See below an example of placing the widgets on a do-it-yourself modal form.

Motion4.html

If you do not see the demonstration, your school security system might have blocked it. Click here to try it on a separate page.

Smart Pascal Code of Motion4

unit Unit1;

interface

uses
  System.Types, SmartCL.System, SmartCL.Components, SmartCL.Application,
  SmartCL.Game, SmartCL.GameApp, SmartCL.Graphics, SmartCL.Slider,
   SmartCL.Controls.ComboBox, System.Colors;

type
  TCanvasProject = class(TW3CustomGameApplication)
  private
    const SCENE_WIDTH = 100;
    const SCENE_HEIGHT = 200;
    MobWidth, MobHeight, MobX: integer;
    MobY: integer = 100;
    GoingRight, GoingUp: Boolean;
    sldrMobWidth: TW3Slider;
    cboColours: TW3ComboBox;
    MobColour: TColor := clWhite;

  protected
    procedure ApplicationStarting; override;
    procedure ApplicationClosing; override;
    procedure PaintView(Canvas: TW3Canvas); override;
  end;

implementation

procedure TCanvasProject.ApplicationStarting;
begin
  inherited;
  GoingRight := True;
  MobX := 5;
  MobWidth := 20;
  MobHeight := 10;

  cboColours := TW3Combobox.Create(Document);
  cboColours.Left := SCENE_WIDTH + 5;
  cboColours.Top := 5;
  cboColours.Width := 50;
  cboColours.Add('Red');
  cboColours.Add('Green');
  cboColours.Add('Blue');
  cboColours.Add('White');
  cboColours.OnChanged := procedure(Sender: TObject)
    begin
      case cboColours.SelectedIndex of
        0: MobColour := clRed;
        1: MobColour := clGreen;
        2: MobColour := clBlue;
        3: MobColour := clWhite;
      end;
    end;
  cboColours.SelectedIndex := 3;

  sldrMobWidth := TW3Slider.Create(Document);
  sldrMobWidth.Top := SCENE_HEIGHT + 5;
  sldrMobWidth.Left := 5;
  sldrMobWidth.Value := 0;
  sldrMobWidth.Minimum := 10;
  sldrMobWidth.Maximum := 25;
  sldrMobWidth.Width := SCENE_WIDTH - 10;
  sldrMobWidth.Height := 24;
  sldrMobWidth.Color := clBlue;
  sldrMobWidth.OnChange := lambda MobWidth := trunc(sldrMobWidth.Value); end;

  GameView.Delay := 20;
  GameView.StartSession(False);
end;

procedure TCanvasProject.ApplicationClosing;
begin
  GameView.EndSession;
  inherited;
end;

procedure TCanvasProject.PaintView(Canvas: TW3Canvas);
begin
  if sldrMobWidth.Value = 0 then
    sldrMobWidth.Value := 20;
  // Clear background to teal
  Canvas.FillStyle := 'teal';
  Canvas.FillRectF(0, 0, SCENE_WIDTH, SCENE_HEIGHT);
  Canvas.FillStyle := ColorToWebStr(MobColour);
  if MobX + MobWidth < SCENE_WIDTH then
    begin
      Canvas.BeginPath;
      Canvas.Ellipse(MobX, MobY, MobX + MobWidth, MobY + MobHeight); // leftX, topY, rightX, bottomY
      Canvas.Fill;
   end;
  // Change position of mobile before next paint.
  if GoingRight = True then
    MobX += 5
  else
    MobX -= 2;
  // Change direction when right of ellipse is at right of scene or beyond.
  if MobX + MobWidth >= SCENE_WIDTH  then //If the ball is on the right of the screen
    GoingRight := False   // Going right is no longer true i.e it will go left
  // Change direction when left of ellipse is at left of GameView or beyond.
  else if MobX <= 0 then
    GoingRight := True;
  if GoingUp = true then
    MobY -= 3
  else
    MobY += 6;
  if MobY <= 0 then
    GoingUp := False
  else if MobY + MobHeight >= SCENE_HEIGHT then
    GoingUp := True;
end;

end.
    

Showing Widgets in a DIY Modal Form

Another alternative is to show at the outset a form containing widgets including a button to remove the form and start the game. This example shows how to create such a form in code. An edit box is provided for the user to enter the delay in milliseconds. This simple, short example omits validation of the input. Also, instead of starting a game, we simply display the frame number once the form becomes invisible.

unit Unit1;

interface

uses 
  System.Types, SmartCL.System, SmartCL.Components, SmartCL.Application,
  SmartCL.Game, SmartCL.GameApp, SmartCL.Graphics, SmartCL.Controls,
  SmartCL.Forms, SmartCL.Controls.Panel, SmartCL.Controls.Button;
type
  TCanvasProject = class(TW3CustomGameApplication)
  private
    FrameCount: integer;
    MyForm : TW3CustomForm;
  protected
    procedure ApplicationStarting; override;
    procedure ApplicationClosing; override;
    procedure PaintView(Canvas: TW3Canvas); override;
  end;

implementation

procedure TCanvasProject.ApplicationStarting;
begin
  inherited;
  MyForm := TW3CustomForm.Create(Document);
  MyForm.SetBounds(0, 0, 300, 200);
  var  pnlBackground := TW3Panel.Create(MyForm);
  pnlBackground.SetBounds(0, 0, 200, 150);

  var lblDelay := TW3Label.Create(pnlBackground);
  lblDelay.SetBounds(10, 5, 250, 15);
  lblDelay.Caption := 'Please enter delay in ms';
  var edtDelay := TW3EditBox.Create(pnlBackground);
  edtDelay.SetBounds(10, 20, 70, 30);
  var btnStart := TW3Button.Create(pnlBackground);
  btnStart.SetBounds(10, 60, 80, 40);
  btnStart.Caption := 'Start';
  btnStart.OnClick := lambda
                        MyForm.Visible := False;
                        GameView.Delay := strToInt(edtDelay.Text);
                        GameView.StartSession(False);
                      end;
  MyForm.Visible := True;
end;

procedure TCanvasProject.ApplicationClosing;
begin
  GameView.EndSession;
  inherited;
end;

procedure TCanvasProject.PaintView(Canvas: TW3Canvas);
begin
  inc(FrameCount);
  if FrameCount = 2 then
    MyForm.Free;
  Canvas.FillStyle := 'rgb(0, 0, 99)';
  Canvas.FillRectF(0, 0, GameView.Width, GameView.Height);
  Canvas.Font := '16pt verdana';
  Canvas.FillStyle := 'rgb(255, 255, 255)';
  Canvas.FillText('Framecount: ' + IntToStr(FrameCount), 10, 20);
end;

end.    

Programming - a skill for life!

How to provide the user with game options in Smart Pascal