# BallTrajectory

Educational motion graphic developed in Smart Mobile Studio by Felix Thompson: Y13 Age ~18

## Introduction

Felix shows how to use Physics to make the ball move in a realistic manner. (Sometimes the implementation of the effect of gravity uses a technique that is chosen for speed of execution rather than for strict adherence to the laws of nature). As usual, Felix comments the code thoroughly for your benefit.

The code follows the graphic in action. Refresh the screen for a different output; the ball will restart from the centre of the box with a different random velocity.

See also the use of much of the code in the Pixi.js version below and in the form-based Compendium.

If BallTrajectory does not run in your current browser, please try another (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.

## The Code

```unit BallTrajectory;
{

use this file except in compliance with the License, as described at
}
interface

uses
W3System, W3Components, W3Application, W3Game, W3GameApp, W3Graphics;

type
TApplication = class(TW3CustomGameApplication)
protected
procedure  ApplicationStarting; override;
procedure  ApplicationClosing; override;
procedure  PaintView(Canvas: TW3Canvas); override;
end;

implementation

{ TApplication}

var
t : Integer;
mX, mY, vX, vY : Real;

procedure TApplication.ApplicationStarting;
begin
inherited;
GameView.Delay := 20;
GameView.StartSession(True);
mX := 150;                               // The ball starts in the centre of the
mY := 150;                               // screen after each refresh.
vX := (100 - RandomInt(200));            // A random vertical and
vY := 20* (10 - RandomInt(20));          // horizontal velocity is chosen.
end;

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

procedure TApplication.PaintView(Canvas: TW3Canvas);
begin
Canvas.FillStyle := 'white';
Canvas.FillRectF(0, 0, GameView.Width, GameView.Height); //The screen in drawn with edges.
Canvas.FillStyle := 'Black';
Canvas.FillRectF(0, 299 , 300, 1);
Canvas.FillStyle := 'Black';
Canvas.FillRectF(299, 0, 1, 300);
Canvas.FillStyle := 'Black';
Canvas.FillRectF(0, 0 , 300, 1);
Canvas.FillStyle := 'Black';
Canvas.FillRectF(0, 0, 1, 300);

t += 1;
vY := vY - 0.2 * t;           //Vertical velocity always increases downwards - gravity.
mY -= 0.1 * vY;               //The speeds are added to the current location
mX -= 0.1 * vX;               //to give the new position.

if mY + 10 >= 300 then        //This stops the ball from going underground,
begin                       //it reverses its direction on collision and
vy := -vY * 0.9;          //loses a factor of its speed - restitution.
mY := 290;
end;
if mY - 10 <= 0 then
begin
vy := -vY * 0.9;
mY := 10;
end;
if (mX + 10 >= 300) AND (Abs(vX) > 0.01) then
begin
vX := -vX * 0.9;
mX := 290;
end;                        //The same happens here but for the walls.
if (mX - 10 <= 0) AND (Abs(vX) > 0.01) then
begin
vX := -vX * 0.9;
mX := 10;
end;                        //If the ball is on the ground it loses
if (mY = 290) then            //horizontal speed - friction.
begin
vX := vX * 0.95;
end;

Canvas.FillStyle := 'Black';  //The ball is drawn
Canvas.BeginPath;
Canvas.Ellipse(Round(mX) + 10, Round(mY) + 10, Round(mX) -10, Round(mY) - 10);
Canvas.Fill;
Canvas.ClosePath;
end;

end.

```

## BallTrajectory Project File for Version 3 of Smart Mobile Studio

You can compile this trimmed-down project file (without any warnings) using the command-line compiler of Version 3 of Smart Mobile Studio.

```<SMART>
<Project version="3" subversion="0">
<Name>BallTrajectory</Name>
<Author>Felix Thompson</Author>
<Company>PPS</Company>
<Options>
<Compiler />
<Codegen>
<Obfuscation>1</Obfuscation>
<Devirtualize>1</Devirtualize>
<MainBody>1</MainBody>
<CodePacking>1</CodePacking>
</Codegen>
<ConditionalDefines />
<EmbedJavaScript>1</EmbedJavaScript>
<Output>
<HtmlFileName>BallTrajectory.html</HtmlFileName>
<OutputFilePath>www\</OutputFilePath>
</Output>
<Import />
<Execute />
</Options>
<Files>
<File type="main">
<Name>BallTrajectoryApplication</Name>
<Source>
<![CDATA[uses
SmartCL.System, BallTrajectory;

var Application: TApplication;
try
Application := TApplication.Create;
Application.RunApp;
except
on e: Exception do
ShowMessage(e.message);
end;
]]>
</Source>
</File>
<File type="unit">
<Name>BallTrajectory</Name>
<Source>
<![CDATA[unit BallTrajectory;

interface

uses
SmartCL.System, SmartCL.Components, SmartCL.Application, SmartCL.Game,
SmartCL.GameApp, SmartCL.Graphics;

type
TApplication = class(TW3CustomGameApplication)
protected
procedure  ApplicationStarting; override;
procedure  ApplicationClosing; override;
procedure  PaintView(Canvas: TW3Canvas); override;
end;

implementation

var
t : Integer;
mX, mY, vX, vY : Float;

procedure TApplication.ApplicationStarting;
begin
inherited;
GameView.Delay := 20;
GameView.StartSession(True);
mX := 150;                               // The ball starts in the centre of the
mY := 150;                               // screen after each refresh.
vX := (100 - RandomInt(200));            // A random vertical and
vY := 20* (10 - RandomInt(20));          // horizontal velocity is chosen.
end;

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

procedure TApplication.PaintView(Canvas: TW3Canvas);
begin
Canvas.FillStyle := 'white';
Canvas.FillRectF(0, 0, GameView.Width, GameView.Height); //The screen in drawn with edges.
Canvas.FillStyle := 'Black';
Canvas.FillRectF(0, 299 , 300, 1);
Canvas.FillStyle := 'Black';
Canvas.FillRectF(299, 0, 1, 300);
Canvas.FillStyle := 'Black';
Canvas.FillRectF(0, 0 , 300, 1);
Canvas.FillStyle := 'Black';
Canvas.FillRectF(0, 0, 1, 300);

t += 1;
vY := vY - 0.2 * t;           // Vertical velocity always increases downwards - gravity.
mY -= 0.1 * vY;               // The speeds are added to the current location
mX -= 0.1 * vX;               // to give the new position.

if mY + 10 >= 300 then        // This stops the ball from going underground,
begin                       // it reverses its direction on collision and
vy := -vY * 0.9;          // loses a factor of its speed - restitution.
mY := 290;
end;
if mY - 10 <= 0 then
begin
vy := -vY * 0.9;
mY := 10;
end;
if (mX + 10 >= 300) AND (Abs(vX) > 0.01) then
begin
vX := -vX * 0.9;
mX := 290;
end;                        // The same happens here but for the walls.
if (mX - 10 <= 0) AND (Abs(vX) > 0.01) then
begin
vX := -vX * 0.9;
mX := 10;
end;                        // If the ball is on the ground it loses
if (mY = 290) then            // horizontal speed - friction.
begin
vX := vX * 0.95;
end;

Canvas.FillStyle := 'Black';  // The ball is drawn
Canvas.BeginPath;
Canvas.Ellipse(Round(mX) + 10, Round(mY) + 10, Round(mX) -10, Round(mY) - 10);
Canvas.Fill;
Canvas.ClosePath;
end;

end.
]]>
</Source>
</File>
</Files>
<Target>Browser</Target>
<Generator>Canvas Project</Generator>
</Project>
</SMART>```

## BallTrajectory with Rendering by Pixi.js

Change the code in the demo Projects\Featured Demos\Games\PixiJS Renderer\Graphics\Graphics.spr supplied with Version 2.2 RC of Smart Mobile Studio to the following for an example of fast rendering.

```{

use this file except in compliance with the License, as described at

Converted for Pixi.js rendering by PPS (2016)
}

uses
W3C.HTML5, W3C.AnimationTiming, W3C.HighResolutionTime, PixiJS;

var t : Integer;
var  mX, mY, vX, vY : Float;

var Renderer := JSystemRenderer(JPIXI.AutoDetectRenderer(300, 300, JRendererOptions(class antialias = true end)));
document.body.appendChild(Renderer.view);
var Stage := new JContainer;
var Graphics := new JGraphics;
mX := 150;                               // The ball starts in the centre of the
mY := 150;                               // screen after each refresh.
vX := (100 - RandomInt(200));            // A random vertical and
vY := 20 * (10 - RandomInt(20));         // horizontal velocity is chosen.

procedure Animate(Time: TDOMHighResTimeStamp);
begin
requestAnimationFrame(Animate);
t += 1;
vY := vY - 0.2 * t;        // Vertical velocity always increases downwards - gravity.
mY -= 0.1 * vY;            // The speeds are added to the current location
mX -= 0.1 * vX;            // to give the new position.

if mY + 10 >= 300 then     // This stops the ball from going underground,
begin                    // it reverses its direction on collision and
vy := -vY * 0.9;       // loses a factor of its speed - restitution.
mY := 290;
end;
if mY - 10 <= 0 then
begin
vy := -vY * 0.9;
mY := 10;
end;
if (mX + 10 >= 300) AND (Abs(vX) > 0.01) then
begin
vX := -vX * 0.9;
mX := 290;
end;                        // The same happens here but for the walls.
if (mX - 10 <= 0) AND (Abs(vX) > 0.01) then
begin
vX := -vX * 0.9;
mX := 10;
end;                        // If the ball is on the ground it loses
if (mY = 290) then            // horizontal speed - friction.
begin
vX := vX * 0.95;
end;

// Draw white background with black edges
Graphics.lineStyle(2, \$000000, 1);
Graphics.beginFill(\$FFFFFF, 1);
Graphics.drawRect(0, 0, 300, 300);
Graphics.endFill;

// Draw circle with lineStyle set to zero so circle has no outline
Graphics.lineStyle(0);
Graphics.beginFill(\$000000, 1);
Graphics.drawCircle(mX, mY, 10);
Graphics.endFill;

Renderer.render(Stage);
end;

requestAnimationFrame(Animate);

```
Programming - a skill for life!

BallTrajectory, BigFibonacci, CollatzASM and MaxCircles by Felix Thompson