Polishing the Tile - SixtyFPS Memory Game Tutorial (C++)

# Polishing the Tile

Next, let's add a curtain like cover that opens up when clicking. We achieve this by declaring two rectangles below the Image, so that they are drawn afterwards and thus on top of the image. The TouchArea element declares a transparent rectangular region that allows reacting to user input such as a mouse click or tap. We use that to forward a callback to the MainWindow that the tile was clicked on. In the MainWindow we react by flipping a custom open_curtain property. That in turn is used in property bindings for the animated width and x properties. Let's look at the two states a bit more in detail:

open_curtain value: | false | true
--- | --- | ---
Left curtain rectangle | Fill the left half by setting the width width to half the parent's width | Width of zero makes the rectangle invisible
Right curtain rectangle | Fill the right half by setting x and width to half of the parent's width | width of zero makes the rectangle invisible. x is moved to the right, to slide the curtain open when animated

In order to make our tile extensible, the hard-coded icon name is replaced with an icon property that can be set from the outside when instantiating the element. For the final polish, we add a solved property that we use to animate the color to a shade of green when we've found a pair, later. We replace the code inside the `memory.60` file with the following:

    MemoryTile := Rectangle {
        callback clicked;
        property <bool> open_curtain;
        property <bool> solved;
        property <image> icon;

        height: 64px;
        width: 64px;
        background: solved ? #34CE57 : #3960D5;
        animate background { duration: 800ms; }

        Image {
            source: icon;
            width: parent.width;
            height: parent.height;
        }

        // Left curtain
        Rectangle {
            background: #193076;
            width: open_curtain ? 0px : (parent.width / 2);
            height: parent.height;
            animate width { duration: 250ms; easing: ease-in; }
        }

        // Right curtain
        Rectangle {
            background: #193076;
            x: open_curtain ? parent.width : (parent.width / 2);
            width: open_curtain ? 0px : (parent.width / 2);
            height: parent.height;
            animate width { duration: 250ms; easing: ease-in; }
            animate x { duration: 250ms; easing: ease-in; }
        }

        TouchArea {
            clicked => {
                // Delegate to the user of this element
                root.clicked();
            }
        }
    }
    MainWindow := Window {
        MemoryTile {
            icon: @image-url("icons/bus.png");
            clicked => {
                self.open_curtain = !self.open_curtain;
            }
        }
    }

Note the use of `root` and `self` in the code. `root` refers to the outermost element in the component, that's the MemoryTile in this case. `self` refers to the current element.

Running this gives us a window on the screen with a rectangle that opens up to show us the bus icon, when clicking on it. Subsequent clicks will close and open the curtain again.