Win an Ipad
  Blog   Using keyboard in ga ...

22.5.2012

Using keyboard in games

Our next release (non-beta) of Moscrif SDK is going to be adopted for a game development. Let's see how to implement support of a keyboard for, let's say "enter player name" scenario.

The first way is to develop own custom keyboard. This is used to reach graphically perfect keyboard that match game design. Graphically perfect but funcional limited. To enter some non-ASCII character is not possible or it takes additional effort to implement a support national characters. Also switching keyboard’s layout can be very limited rather missing generally (no layout for numerics, special characters, etc). To implement custom keyboard you need to create set of buttons, that emulate a keyboard events:

include "lib://game2d/base/gameControl.ms" class KeyButton: TextButton
{     var smallPaint = null;     // overwritten
    function beforeInit()
    {
        super.beforeInit();         if (KeyButton.smallPaint == null) {
            var p = new Paint();
            p.textSize = System.height / 40;
            p.color = 0xffffff00;
            p.typeface = Typeface.fromName("Mail Ray Stuff", #normal);
            KeyButton.smallPaint = p;
        }
    }     // overwritten
    function draw(canvas)
    {
        canvas.save(#matrix);
        canvas.scale(this._scale, this._scale);
        canvas.translate(-this._anchorX, -this._anchorY)
        if (typeof this._text == #string) {
            canvas.drawText(this._text, this._x, this._y + this._height, TextButton.paint);
        } else {
            canvas.drawText(this._text.toString(), this._x, this._y + this._height, KeyButton.smallPaint);
        }
        canvas.restore();
    }     // overwritten
    property text(v)
    {
        get { return this._text; }
        set {
            var (dw, dh) = typeof v == #string ? TextButton.paint.measureText(v) : KeyButton.smallPaint.measureText(v.toString());
            this._width = dw;
            this._height = dh;
            this._anchorX = this._width / 2;
            this._anchorY = this._height / 2;
        }
    } } class CustomKbControl : GameControl
{
    var gap = System.width / 13;     // overwritten
    function init()
    {
        super.init();         this._bgPaint = new Paint();
        this._bgPaint.color = 0x55000000;         this._map = this.options.map ||
            [["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"],
            ["a", "s", "d", "f", "g", "h", "j", "k", "l", #backspace],
            ["z", "x", "c", "v", "b", "n", "m", #enter],
            [#space]];         this._width = this.options.width || System.width / 10 * 9;
        this._height = this.options.height || System.height / 10 * 3;         this._anchorX = this._width / 2;
        this._anchorY = this._height / 2;         this._buttons = [];
        this._build();
    }     // overwritten
    function draw(canvas)
    {
        canvas.save(#matrix);
        canvas.translate(this._x, this._y);
        canvas.scale(this._scale, this._scale);
        canvas.translate(-this._anchorX, -this._anchorY)         canvas.drawRect(0, 0, this.width, this.height, this._bgPaint);         for(var b in this._buttons)
            b.draw(canvas);         canvas.restore();
    }     // overwritten
    function pointerPressed(x, y)
    {
        super.pointerPressed(x, y);
        x += -this._x + this._anchorX;
        y += -this._y + this._anchorY;
        for (var b in this._buttons)
            if (b.intersectsPoint(x, y))
                b.pointerPressed(x, y);
    }     // overwritten
    function pointerReleased(x, y)
    {
        super.pointerReleased(x, y);
        x += -this._x + this._anchorX;
        y += -this._y + this._anchorY;
        for (var b in this._buttons)
            if (b.intersectsPoint(x, y))
                b.pointerReleased(x, y);
    }     property width(v)
    {
        get {
            return this._width;
        }
    }     property height(v)
    {
        get {
            return this._height;
        }
    }     property onKey(v)
    {
        get return this._onKeyHandler;
        set
        {
            if(typeof(v) != #function || v == null)
                throw new InvalidArgument("[CustomKbControl.onKey] Instance of function expected");
            this._onKeyHandler = v;
        }
    }     function _build()
    {
        for (var r = 0; r < this._map.length; r++) {
            var cols = this._map[r].length;
            for (var c = 0; c < cols; c++) {
                var chr = this._map[r][c];
                var x = CustomKbControl.gap/2 + c * CustomKbControl.gap;
                var y = CustomKbControl.gap + r * (4*CustomKbControl.gap/3);
                switch (r) {
                    case 0: x += System.width / 18; break;
                    case 1: x += System.width / 30; break;
                    case 2: x += System.width / 10; break;
                    case 3: x += System.width / 3; break;
                }
                if (typeof chr == #symbol) x += CustomKbControl.gap/2;
                var button = new KeyButton({text:chr, x:x, y:y});
                button.key = chr;
                button.onClick = function(sender) {
                    var self = this super;
                    if (typeof self.onKey == #function)
                        self.onKey(self, sender.key);
                }
                this._buttons.push(button);
            }
        }
    } }

Usage of built-in keyboard appears to be a better way. Moscrif allows you to use it very simple way. System.requestKeyboard is designed to invoke system (build-in, native) keyboard:

include "lib://game2d/scene.ms" class SystemKbScene : Scene
{
    // overwritten
    function init()
    {
        super.init();         this._paint = new Paint();
        this._paint.color = 0xff00fffff;
        this._paint.textSize = System.height/20;
        this._paint.typeface = Typeface.fromName("Mail Ray Stuff", #normal);
        this._playerName = "player";         this._quit = new TextButton({name:"btnQuit", text:"back", y:System.height/10*9, x:System.width/2});
        this._quit.onClick = function(sender) { game.pop(); }
        this.add(this._quit);         game.onKeyReleased = function(sender, key)
        {
            this super._keyboardHandler(key);
        }         game.onChar = function(sender, key)
        {
            this super._keyboardHandler(key);
        }     }     // overwritten
    function draw(canvas)
    {
        super.draw(canvas);         canvas.drawText("Name :", 50, 100, this._paint);
        canvas.drawText(this._playerName, System.width/2, 100, this._paint);
    }     // overwritten
    function pointerReleased(x, y)
    {
        super.pointerReleased(x, y);
        if (!this._quit.intersectsPoint(x, y))
            this._keyboard ? this._hideKeyboard() : this._showKeyboard();
    }     function _keyboardHandler(key)
    {
        if (key == #backspace)
            this._playerName = this._playerName.substr(0, this._playerName.length - 1);
        else if (key == #enter)
            this._hideKeyboard();
        else if (typeof key == #string)
            this._playerName += key;
    }     function _showKeyboard()
    {
        this._keyboard = true;
        System.requestKeyboard(function(sender, key) {
            this super._keyboardHandler(key);
        });
    }
   
    function _hideKeyboard()
    {
        this._keyboard = false;
        System.hideKeyboard();
    } }

 

On the left picture there is screenshot from iPhone. On the right picture there is taken photo of Amazon Kindle Fire.

In short, you can use both custom and native (system) keyboards in your own games. 

Source code: GameKeyboard.zip

Write a Comment (0)
Subject
Please complete this mandatory field.
HTML Tags Not Allowed!
Comment
Please complete this mandatory field.
Author

Author latest blogs