Pixi.js

[Text] [Images] [Mouse] [Touch] [Box2D]

Version 2.2 RC of Smart Mobile Studio has the Pixi.js library for fast rendering and there are several thoroughly commented demonstrations in the Projects\Featured Demos\Games\PixiJS Renderer folder. We converted Felix Thompson's BallTrajectory for rendering by Pixi.js and were pleased by both the ease of conversion and the performance of the output. We hope that some of you will be tempted to write programs that use the library.

You can compare the rendering of Pixi.js with the usual inbuilt drawing routines. We advise you to make a backup of the Projects\Featured Demos\Games\PixiJS Renderer folder before experimenting with the code. The following code, when used to replace the code in the demo Projects\Featured Demos\Games\PixiJS Renderer\Graphics\Graphics.spr, draws a green triangle with black edges on a blue background.

uses
  W3C.HTML5, PixiJS;

  var Renderer := JSystemRenderer(JPIXI.AutoDetectRenderer(800, 600, JRendererOptions(class antialias = true end)));
  document.body.appendChild(Renderer.view);
  var Stage := new JContainer;
  var Graphics := new JGraphics;
  // Blue background
  Graphics.beginFill($000063);
  Graphics.lineStyle(0);
  Graphics.drawRect(0, 0, 300, 300);
  // Green triangle with black edges
  Graphics.beginFill($00FF00);
  Graphics.lineStyle(2, $000000, 1);
  Graphics.moveTo(50,50);
  Graphics.lineTo(50, 100);
  Graphics.lineTo(100, 50);
  Graphics.lineTo(50, 50);
  Graphics.endFill;

  Stage.addChild(Graphics);
  Renderer.render(Stage);    

Find the names and parameters of these and other JGraphics routines in the PixiJS unit:
drawRect(x, y, width, height: Float)
moveTo(x, y: Float)
lineTo(x, y: Float)
drawCircle(x, y, radius: Float)
drawEllipse(x, y, width, height: Float)
arc(cx, cy, radius, startAngle, endAngle: Float; anticlockwise: Boolean)
quadraticCurveTo(cpX, cpY, toX, toY: Float)    

Drawing Text

The supplied demo Projects\Featured Demos\Games\PixiJS Renderer\Text is impressive and provides an example of the useful word wrap facility. The following code places the customary test greeting near the top left of the graphics window in the default black font.

var Greeting := JText.Create('Hello World!');
Greeting.x := 10;
Greeting.y := 10;
Stage.addChild(Greeting);    
For customised text, instead of
Canvas.FillStyle := 'rgb(220, 20, 50)';
Canvas.Font := '15pt verdana';
Canvas.FillText('Customised Text', 30, 160);    
in a canvas project, you would use code such as this for preparing to render the text by Pixi.js:
var MyStyle = class
  font := '15pt verdana';
  fill := '#DC1432';
end;

var CustomisedText := JText.Create('Customised text', JTextStyle(MyStyle));
CustomisedText.x := 30;
CustomisedText.y := 160;
Stage.addChild(CustomisedText);    

Drawing Images

The supplied demo Projects\Featured Demos\Games\PixiJS Renderer\Basic shows the loading and spinning of an image.

To add an image to Resources (in the res folder), you can:
  1. right click on the Resources folder in the tree view of the project at the top left of the Smart IDE;
  2. click on Add Resource File(s);
  3. browse to find your file (e.g. my_file.png) and open it.
In order to set up the image for rendering by Pixi.js you could use code such as this:
var Texture := JTexture.fromImage('res/my_file.png');
var MyImage := new JSprite(Texture);
MyImage.position.x := 100;
MyImage.position.y := 100;
Stage.addChild(MyImage);    
A simpler alternative is:
var MySprite := JSprite.fromImage('res/my_file.png');
MySprite.position.set(100, 100);
Stage.addChild(MySprite);   

Dragging a Sprite with the Mouse

Replace the code of the Click demo with the following to obtain the mouse position and use it to move the sprite.

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

  var Renderer := JSystemRenderer(JPIXI.AutoDetectRenderer(400, 300));
  document.body.appendChild(Renderer.view);
  var Stage := new JContainer;
  var Sprite := JSprite.fromImage('res/bunny.png');
  Sprite.position.set(200, 150);
  Sprite.interactive := true;
  asm
    (@Sprite).mousemove = function(event)
    {
      var newPosition = event.data.getLocalPosition(this.parent);
      this.position.x = newPosition.x;
      this.position.y = newPosition.y;
    }
  end;
  Stage.addChild(Sprite);

procedure Animate(Time: TDOMHighResTimeStamp);
begin
  requestAnimationFrame(Animate);
  renderer.render(Stage);
end;

  requestAnimationFrame(Animate);    

In order to position the mouse pointer at the centre of the sprite for the drag, insert these lines before the asm block:
  Sprite.anchor.x := 0.5;
  Sprite.anchor.y := 0.5;
    

Dragging a Sprite by Mouse and Touch

Simply change the code of the first line of the asm block above to
    (@Sprite).mousemove = (@Sprite).touchmove = function(event)

Using Pixi.js with Box2D

This example uses Pixi.js to render two rectangular objects as they fall to the ground under gravity. The physics engine Box2D calculates the positions and uses the value of restitution to determine the behaviour upon impact with the ground. In order to try it, replace the code of the supplied demo Graphics with the following.

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

  const BW = 0.5; //Border width
  const MOB_WIDTH = 3;
  const MOB_HEIGHT = 2;
  const FRAME_RATE = 1 / 30;
  const SCALE = 10;
  const RESTITUTION = 0.2;
  const FRICTION = 0.5;
  const GameViewWidth = 400;
  const GameViewHeight = 300;

  var Renderer := JSystemRenderer(JPIXI.AutoDetectRenderer(GameViewWidth, GameViewHeight, JRendererOptions(class antialias = true end)));
  document.body.appendChild(Renderer.view);
  var Stage := new JContainer;
  var Graphics := new JGraphics;
  var FWorld := Tb2World.Create(
    Tb2Vec2.Create(0.0, 10.0),   // gravity
    True                         // allow sleep
  );
  // Create fixture definition (used to describe fixture objects)
  var FixtureDef := Tb2FixtureDef.Create;
  FixtureDef.Density := 1.0;
  FixtureDef.Friction := FRICTION;
  FixtureDef.Restitution := RESTITUTION;
  // Create body definition class (used to describe body objects)
  var BodyDef := Tb2BodyDef.Create;
  BodyDef.BodyType := btStaticBody;
  // Create the surrounding ground.
  FixtureDef.Shape := Tb2PolygonShape.Create;
  Tb2PolygonShape(FixtureDef.Shape).SetAsBox(0.5 * GameViewWidth / SCALE, BW / 2);
  BodyDef.Position.SetXY(0.5 * GameViewWidth / SCALE, GameViewHeight / SCALE - BW / 2);
  FWorld.CreateBody(BodyDef).CreateFixture(FixtureDef);
  // Create two rectangular dynamic objects at the top of the screen.
  BodyDef.BodyType := btDynamicBody;
  Tb2PolygonShape(FixtureDef.Shape).SetAsBox(MOB_WIDTH / 2, MOB_HEIGHT / 2);
  BodyDef.Position.SetXY(10, MOB_HEIGHT / 2 + BW);
  BodyDef.Position.SetXY(10, MOB_HEIGHT / 2 + BW);
  FWorld.CreateBody(BodyDef).CreateFixture(FixtureDef);
  BodyDef.Position.SetXY(30, MOB_HEIGHT / 2 + BW);
  FWorld.CreateBody(BodyDef).CreateFixture(FixtureDef);

  Stage.addChild(Graphics);

procedure Animate(Time: TDOMHighResTimeStamp);
begin
  requestAnimationFrame(Animate);
  // Draw background and ground
  Graphics.beginFill($00C800, 1);
  Graphics.drawRect(0, 0, GameViewWidth, GameViewHeight);
  Graphics.beginFill($000000, 1);
  Graphics.drawRect(0, GameViewHeight - BW * SCALE, GameViewWidth, BW * SCALE);
  // Advance and draw world
  FWorld.Advance(FRAME_RATE, 6, 2);
  var Body := FWorld.GetBodyList;
  while Assigned(Body) do
    begin
      if Body.GetType = btDynamicBody then
        begin
          var Pos := Body.GetPosition;
          Graphics.beginFill($C80000, 1);
          Graphics.drawRect(Pos.X * SCALE -MOB_WIDTH * SCALE / 2, Pos.Y * SCALE -MOB_HEIGHT * SCALE / 2, MOB_WIDTH * SCALE, MOB_HEIGHT * SCALE);
        end;
    Body := Body.GetNext;
  end;
  FWorld.ClearForces;
  Renderer.render(Stage);
end;

  requestAnimationFrame(Animate);
    
Programming - a skill for life!

Useful for games, with drawing routines (including transforms and text fonts), images, sprites and WebGL 3D graphics. Now includes Box2D physics and rendering by Pixi.js.