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.

BallTrajectory

The Code

unit BallTrajectory;
{
    Copyright (c) 2014 Felix Thompson

    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
}
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 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.

{
    Copyright (c) 2014 Felix Thompson

    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/

    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;
  Stage.addChild(Graphics);
  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