Navigation

Part 2 - The Input Panel

Let's start constructing our Input Panel class.

First, we'll create the letters you can select from by drawing a Bitmap Text with a 20 pixel spacing between each character. After 10 characters we'll wrap them onto a new line:

class InputPanel extends Phaser.Scene {

    constructor ()
    {
        super({ key: 'InputPanel', active: false });

        this.chars = [
            [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' ],
            [ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T' ],
            [ 'U', 'V', 'W', 'X', 'Y', 'Z', '.', '-', '<', '>' ]
        ];

        this.cursor = new Phaser.Math.Vector2();

        this.text;
        this.block;

        this.name = '';
        this.charLimit = 3;
    }

    create ()
    {
        let text = this.add.bitmapText(130, 50, 'arcade', 'ABCDEFGHIJ\n\nKLMNOPQRST\n\nUVWXYZ.-');

        text.setLetterSpacing(20);
        text.setInteractive();

        this.add.image(text.x + 430, text.y + 148, 'rub');
        this.add.image(text.x + 482, text.y + 148, 'end');

        this.block = this.add.image(text.x - 10, text.y - 2, 'block').setOrigin(0);

        this.text = text;
    }
}

In the above code we just add a Bitmap Text and a couple of Images to the Scene. We can't actually select anything yet. To do that, let's listen for the pointermove event on the text object, and run this new function when we receive it:

moveBlock (pointer, x, y)
{
    let cx = Phaser.Math.Snap.Floor(x, 52, 0, true);
    let cy = Phaser.Math.Snap.Floor(y, 64, 0, true);
    let char = this.chars[cy][cx];

    this.cursor.set(cx, cy);

    this.block.x = this.text.x - 10 + (cx * 52);
    this.block.y = this.text.y - 2 + (cy * 64);
}

Our text characters are spaced out 52 x 64 pixels apart, so by taking the input coordinates we can snap them to our grid size and then figure out which letter you clicked on.

Then we need a function to handle what happens when you click:

pressKey ()
{
    let x = this.cursor.x;
    let y = this.cursor.y;
    let nameLength = this.name.length;

    this.block.x = this.text.x - 10 + (x * 52);
    this.block.y = this.text.y - 2 + (y * 64);

    if (x === 9 && y === 2 && nameLength > 0)
    {
        //  Submit
        this.events.emit('submitName', this.name);
    }
    else if (x === 8 && y === 2 && nameLength > 0)
    {
        //  Rub
        this.name = this.name.substr(0, nameLength - 1);

        this.events.emit('updateName', this.name);
    }
    else if (this.name.length < this.charLimit)
    {
        //  Add
        this.name = this.name.concat(this.chars[y][x]);

        this.events.emit('updateName', this.name);
    }
}

The above function is invoked on the pointerup event. It checks which letter we've clicked, by taking the cursor values, and then either emiting the submitName event, or the updateName one, depending on which character was clicked. Our Highscore class is the one waiting for those events. If you hook them together, you get the following:

Note how in the demo above you can click around, select characters, and have them appear.

Here is the full class so far:

class InputPanel extends Phaser.Scene {

    constructor ()
    {
        super({ key: 'InputPanel', active: false });

        this.chars = [
            [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' ],
            [ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T' ],
            [ 'U', 'V', 'W', 'X', 'Y', 'Z', '.', '-', '<', '>' ]
        ];

        this.cursor = new Phaser.Math.Vector2();

        this.text;
        this.block;

        this.name = '';
        this.charLimit = 3;
    }

    create ()
    {
        let text = this.add.bitmapText(130, 50, 'arcade', 'ABCDEFGHIJ\n\nKLMNOPQRST\n\nUVWXYZ.-');

        text.setLetterSpacing(20);
        text.setInteractive();

        this.add.image(text.x + 430, text.y + 148, 'rub');
        this.add.image(text.x + 482, text.y + 148, 'end');

        this.block = this.add.image(text.x - 10, text.y - 2, 'block').setOrigin(0);

        this.text = text;

        text.on('pointermove', this.moveBlock, this);
        text.on('pointerup', this.pressKey, this);
    }

    moveBlock (pointer, x, y)
    {
        let cx = Phaser.Math.Snap.Floor(x, 52, 0, true);
        let cy = Phaser.Math.Snap.Floor(y, 64, 0, true);
        let char = this.chars[cy][cx];

        this.cursor.set(cx, cy);

        this.block.x = this.text.x - 10 + (cx * 52);
        this.block.y = this.text.y - 2 + (cy * 64);
    }

    pressKey ()
    {
        let x = this.cursor.x;
        let y = this.cursor.y;
        let nameLength = this.name.length;

        this.block.x = this.text.x - 10 + (x * 52);
        this.block.y = this.text.y - 2 + (y * 64);

        if (x === 9 && y === 2 && nameLength > 0)
        {
            //  Submit
            this.events.emit('submitName', this.name);
        }
        else if (x === 8 && y === 2 && nameLength > 0)
        {
            //  Rub
            this.name = this.name.substr(0, nameLength - 1);

            this.events.emit('updateName', this.name);
        }
        else if (this.name.length < this.charLimit)
        {
            //  Add
            this.name = this.name.concat(this.chars[y][x]);

            this.events.emit('updateName', this.name);
        }
    }
}

Next, we'll add keyboard controls.