How do I make a simple calculator app?

In fact my question is about any ideas, suggestions, samples or tutorials that helps me to make it in a proper way.

Thanks in advance

It is a good idea to write a simple calculator for a little practice. I like this challenge. At first we need to create a simple button. I found this tutorial: https://phaser.io/news/2018/12/buttons-in-phaser-3 The tutorial is based on this example: https://github.com/snowbillr/phaser3-webpack-es6-dev-starter

I like to use TypeScript instead of ES6. I rewrote the base example to TypeScript:

I will try to create my first button tomorrow using the tutorial above.

1 Like

Oh! great! I found a few tutorials but with Unity3D (https://gist.github.com/naruse/7100104), Javascript (https://freshman.tech/calculator/) or Godot (https://godotengine.org/qa/3858/virtual-keyboard). I’ll try to make it as you but in ES6.

On the other hand, maybe it’d be a nice idea to hosting a “challenge jam” or something alike (or maybe not!). It could help to people who starting with Phaser and want to see how skilled or advanced users developes a proposal like that, a simple calculator.

1 Like

ES6 and TypeScript are very similar. Please, compare this code from the “Buttons in Phaser 3” tutorial:

ES6:

export class SimpleScene extends Phaser.Scene {
  create() {
    let clickCount = 0;
    this.clickCountText = this.add.text(100, 200, '');

    const clickButton = this.add.text(100, 100, 'Click me!', { fill: '#0f0' })
      .setInteractive()
      .on('pointerdown', () => this.updateClickCountText(++clickCount) );

    this.updateClickCountText(clickCount);
  }

  updateClickCountText(clickCount) {
    this.clickCountText.setText(`Button has been clicked ${clickCount} times.`);
  }
}

TypeScript

export default class SimpleScene extends Phaser.Scene
{
    private _clickCountText: Phaser.GameObjects.Text;

    private create(): void
    {
        let clickCount = 0;
        this._clickCountText = this.add.text(50, 200, "");

        const clickButton = this.add.text(50, 100, "Click me!", { fill: "#0f0" })
            .setInteractive()
            .on("pointerdown", () => { this.UpdateClickCountText(++clickCount) });

        this.UpdateClickCountText(clickCount);
    }

    private UpdateClickCountText(clickCount: number): void
    {
        this._clickCountText.setText(`Button has been clicked ${clickCount} times.`);
    }
}

We can understand each other.

The first part of the Buttons in Phaser 3 tutorial is enough to write a very simple calculator in Phaser. I made this steps from the tutorial and I created branches on GitHub for every three steps. You can run them on Playground:

step-003-pointerdown

After googling a bit I made this wip version. No nice buttons or calculator layout but also I stuck with two issues related to my lack of knowledge:

  • The digits value is displaying left to right.
  • Can’t pass the context of this if I want to encapsulate on a function whenever it updates the display value.
// WIP Phaser3 Calculator
// Based on this great tutorial: https://freshman.tech/calculator/
// also triying to understand how it works emits? https://labs.phaser.io/edit.html?src=src/events/listen%20to%20game%20object%20event.js&v=3.22.0

// Open console log to see the calculator states

console.clear();

const calculator = {
  displayValue: '0',
  firstOperand: null,
  waitingForSecondOperand: false,
  operator: null,
};

var config = {
  type: Phaser.AUTO,
  parent: 'calculator-canvas',
  width: 800,
  height: 600,
  disableContextMenu: true,
  scene: {
    preload: preload,
    create: create
  }
};
var game = new Phaser.Game(config);

function preload()
{
  
}

function create()
{
  const buttons = [
    ['7', '8', '9', '/'],
    ['4', '5', '6', 'x'],
    ['1', '2', '3', '-'],
    ['0', '.', '=', '+'],
    ['C']
  ];
  // display the buttons in a grid form
  for (const [index, row] of buttons.entries())
  {
    var nrow = index;
    for (const [index, value] of row.entries())
    {
      var button = this.add.text((32 * (index % 4)), (32 * nrow), value, { fill : '#0d0'});
      button.setInteractive();
      button.on('clicked', clickHandler, this);
    }
  };

    //  If a Game Object is clicked on, this event is fired.
    //  We can use it to emit the 'clicked' event on the game object itself.
    this.input.on('gameobjectup', function (pointer, gameObject)
    {
        gameObject.emit('clicked', gameObject);
    }, this);

  
  this.value = this.add.text(500, 90, calculator.displayValue, {
    fill: '#00f',
    font: '128px cursive'
  });

}

function clickHandler(button)
{
  console.table(calculator);
  
  if (button.text === 'C')
  {
    resetCalculator();
    // Update display
    // @TODO: This must be a function but it lost the this context!
    this.value.text = calculator.displayValue;  
    return;
  }
  // Handle with digits
  inputDigit(button.text);
  // Update display
  this.value.text = calculator.displayValue;  
}

function inputDigit(digit) {
  const { displayValue, waitingForSecondOperand } = calculator;

  if (waitingForSecondOperand === true) {
    calculator.displayValue = digit;
    calculator.waitingForSecondOperand = false;
  } else {
    calculator.displayValue = displayValue === '0' ? digit : displayValue + digit;
  }
}

function resetCalculator()
{
  calculator.displayValue = '0';
  calculator.firstOperand = null;
  calculator.waitingForSecondOperand = false;
  calculator.operator = null;
}


Fixed:

  this.value = this.add.text(500, 90, calculator.displayValue, {
    fill: '#00f',
    font: '128px cursive',
    rtl: true // https://phaser.io/examples/v3/view/game-objects/text/static/right-to-left-text#
  });