Win an Ipad
  Developer   Demos & Samples   Memory Cards (Pairs, ...

Memory Cards (Pairs, Pexeso)

Screenshot
See how easy is to develop a game like matching pairs in Moscrif.

User Interface

Matching Pairs is a simple game, where the goal is to find the same pairs in the  grid of cards. At the beginning, cards are flipped face down and randomly placed in the game grid. This demo supports 3x4 game grid which means that there are six card pairs.
One game move means to uncover two cards (one pair) from the game grid. If the cards are the same the card pair remains uncovered. There is a sound notification to indicate that you found the right card pair.
If appearance of the cards is not the same you might want to try again. Game ends when all card pairs are uncovered.
Navigation buttons and timer are located at the bottom of the screen. Button New, starts new game. Cards are randomly arranged on the playing grid and new game starts.

 

Paying cards

Pexeso can be played on various device resolutions, that is the reason why playing cards are vector graphics. They are kept as xml files. Following example shows how to define cards and how to manage them as vector graphics in Moscrif.

Definition of the vector grafics:

var imageList = new Array();
    imageList[0] = {};
    imageList[0].src = "app://img/face1.svg";
    imageList[0].color = 0xfff10eab;
    imageList[0].rectColor = 0xffd9034e;
    imageList[0].id = 0;
    imageList[1] = {};
    imageList[1].src = "app://img/face2.svg"
    imageList[1].color = 0xfff53c21;
    imageList[1].rectColor = 0xffe61208;
    imageList[1].id = 1;
    imageList[2] = {};
    imageList[2].src = "app://img/face3.svg"
    imageList[2].color = 0xffca32ed;
    imageList[2].rectColor = 0xff880ed2;
    imageList[2].id = 2;
    imageList[3] = {};
    imageList[3].src = "app://img/face4.svg"
    imageList[3].color = 0xfffec70f;
    imageList[3].rectColor = 0xfffd7e03;
    imageList[3].id = 3;
    imageList[4] = {};
    imageList[4].src = "app://img/face5.svg"
    imageList[4].color = 0xff1eb7f0;
    imageList[4].rectColor = 0xff0c93e6;
    imageList[4].id = 4;
    imageList[5] = {};
    imageList[5].src = "app://img/face6.svg"
    imageList[5].color = 0xffc0e322;
    imageList[5].rectColor = 0xff70ba08;
    imageList[5].id = 5;

Class for vector graphics managing. It loads file from XML file, transforms path, moves path and draws path.

 

class VectorImage
{
    //this is only basic class.
    function this(file = 0)
    {
        this.paints = new Array();
        this.paths = new Array();         //width of the vector file
        //size 50000 is probably large enough
        this.left = 50000;         //height of the vector file
        //size 5000 is probably large enough
        this.top = 5000;
        this.right = 0;
        this.bottom = 0;         this.width = 0;
        this.height = 0;
    }     function load(file)
    {
        this.paints = new Array();
        this.paths = new Array();         //width of the vector file
        //size 50000 is probably large enough
        this.left = 50000;         //height of the vector file
        //size 5000 is probably large enough
        this.top = 5000;
        this.right = 0;
        this.bottom = 0;         var xml;
        //var file = "app://vector.svg";
        if (!System.isFile(file))
            console << "Not found settings file";
        var f = Stream.openFile(file,  "r8");
        if (!f)
            console << "Can't load settings file";         var line = f.readln();
        while(line) {
            xml += line;
            line = f.readln();
        }
        f.close();         this._findPaths(xml);
    }     function draw(canvas, left, top, width, height)
    {
       for (var i = 0; i < this.paths.length; i++) {
            canvas.drawPath(this.paths[i], this.paints[i]);
        }
    }       function movePaths(x, y)
    {
        for (var i = 0; i < this.paths.length; i++) {
            this.paths[i].offset(-1*x,-1*y);
        }
    }     function transform(x, y, width, height, maintainRatio = true)
    {
        var (bl, bt, br, bb);         var scaleX = width / this.width;
        var scaleY = height / this.height;         if (maintainRatio == true) {
            if (this.width < this.height) {
                scaleY = height / this.height;
                scaleX = scaleY;
            } else {
                scaleX = width / this.width;
                scaleY = scaleX;
            }
        }         //it should be width of the vector file
        //size 50000 is probably lagre enought
        this.left = 50000;         //it should be height of the vector file
        //size 5000 is probably lagre enought
        this.top = 5000;
        this.right = 0;
        this.bottom = 0;         for (var i = 0; i < this.paths.length; i++) {
            var matrix = new Matrix();
            matrix.setScale(scaleX, scaleY);
            this.paths[i].transform(matrix);
   
            this.paths[i].offset(-1*x,-1*y);
            (bl, bt, br, bb) = this.paths[i].getBounds();
            this._setRect(bl, bt, br, bb);
        }     }     function _findPaths(file)
    {
        var lastPosition = 0;
        var tagStart = 0;
        var end = 0;
        var pathString = "";         while((tagStart = file.indexOf("         {
            //finded start of tag, now we need to find end.;
             end = file.indexOf("/>", tagStart);
             if (end == -1) {
                //unended tag
                return false;
             } else {
                pathString = file.substring(tagStart, end + 2);
                this._loadFromPath(pathString);
             }
             lastPosition = end + 2;
        }
        this.width = this.right - this.left;
        this.height = this.bottom - this.top;
        this.movePaths(this.left, this.top);
    }     function _loadFromPath(path)
    {
        var paint = new Paint();
        var graphics;         //get properties (stroke, fill, stroke width and d)
        var fill = this._loadParameter(path, "fill");
        if(fill) {
            if(this._isColor(fill)) {
                //<<"\n";
                paint.color = this._toColor(fill);
                paint.style = #fill;
            } else {
                paint.style = #stroke;
            }
        }         var stroke = this._loadParameter(path, "stroke");
        if(stroke) {
            if(this._isColor(stroke)) {
                //<<"\n";
                paint.color = this._toColor(stroke);
                paint.style = #stroke;
            } else {             }
        }         var width = this._loadParameter(path, "stroke-width");
        if(width) {
            //console<             paint.strokeWidth = width.toNumber();;
        }         var cap = this._loadParameter(path, "stroke-linecap");
        if(cap) {
            paint.strokeCap = this._toSymbol(cap);
        }         var join = this._loadParameter(path, "stroke-linejoin");
        if(join) {
            paint.strokeJoin = this._toSymbol(join);
        }         var d = this._loadParameter(path, "d");
        if(d) {
            //console<             graphics = Path.fromSVG(d);
         } else {
            //d is the most important.. we need it to
            return false;
        }
        //create objects         this.paths.push(graphics);
        this.paints.push(paint);         //calculate vector properties
        //we need to calculate with all elements
        var (bl, bt, br, bb) = graphics.getBounds();
        this._setRect(bl, bt, br, bb);
    }     function _setRect(left, top, right, bottom)
    {
        if (left < this.left)
            this.left = left;
        if (right > this.right)
            this.right = right;
        if (top < this.top)
            this.top = top;
        if (bottom > this.bottom)
            this.bottom = bottom;         this.width = this.right - this.left;
        this.height = this.bottom - this.top;
    }     function _toSymbol(string)
    {
        switch (string) {
            case "round":
                return #round;
                break;
        }
    }     function _loadParameter(path, param)
    {
        var valueStart = 0;
        var valueEnd = 0;
        var index = path.indexOf(" " + param + "=");
        var value = "";         if (index != -1) {
            //index is now start of param name
            //value we need to find the nearest double quote
            index = path.indexOf("\"", index);             //if there is no double quote, it is an error
            if (index == -1)
                return false;
   
            valueStart = index + 1;
            valueEnd = path.indexOf("\"", valueStart);             //if there is no double quote, it is unended value
            if (valueEnd == -1)
                return false;
        } else {
            index = path.indexOf(param + ":");
            if (index == -1)
                return false;
            valueStart = index + param.length + 1;
            valueEnd = path.indexOf(";", valueStart);
            if (valueEnd == -1)
                valueEnd = path.indexOf("\"", valueStart);
        }         value = path.substring(valueStart, valueEnd);
        return value;
    }     function _isColor(string)
    {
       if(string.indexOf("#") != -1)
            return true;
        else
            return false;
    }     function _toColor(string)
    {
        var color = 0xff000000;
        color += this._charToHex(string.charAt(1)) * 0x100000;
        color += this._charToHex(string.charAt(2)) * 0x010000;
        color += this._charToHex(string.charAt(3)) * 0x001000;
        color += this._charToHex(string.charAt(4)) * 0x000100;
        color += this._charToHex(string.charAt(5)) * 0x000010;
        color += this._charToHex(string.charAt(6)) * 0x000001;         return color;
    }     function _charToHex(char)
    {
        char.toLowerCase();
        switch (char) {
            case "0":
                return 0x0;
                break;
            case "1":
                return 0x1;
                break;
            case "2":
                return 0x2;
                break;
            case "3":
                return 0x3;
                break;
            case "4":
                return 0x4;
                break;
            case "5":
                return 0x5;
                break;
            case "6":
                return 0x6;
                break;
            case "7":
                return 0x7;
                break;
            case "8":
                return 0x8;
                break;
            case "9":
                return 0x9;
                break;
            case "a":
                return 0xa;
                break;
            case "b":
                return 0xb;
                break;
            case "c":
                return 0xc;
                break;
            case "d":
                return 0xd;
                break;
            case "e":
                return 0xe;
                break;
            case "f":
                return 0xf;
                break;
        }
    }
}


Try the full demo from the Moscrif repository.

License

This article, along with any associated source codes and files, is licensed under The BSD License

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