/* LICENSE BEGIN This file is part of the SixtyFPS Project -- https://sixtyfps.io Copyright (c) 2020 Olivier Goffart Copyright (c) 2020 Simon Hausmann SPDX-License-Identifier: GPL-3.0-only This file is also available under commercial licensing terms. Please contact info@sixtyfps.io for more information. LICENSE END */ struct TileData := { image: image, image_visible: bool, solved: bool, } MemoryTile := Rectangle { border-radius: 8px; callback clicked; property open_curtain; property solved; property icon; background: solved ? #34CE57 : #3960D5; animate background { duration: 800ms; } Image { source: icon; width: parent.width - 16px; height: parent.height - 16px; x: 8px; y: 8px; } // Left curtain Rectangle { background: #193076; border-radius: 4px; width: open_curtain ? 0px : parent.width / 2 + 4px; height: parent.height; animate width { duration: 250ms; easing: ease-in; } Clip { Image { width: root.width - 32px; height: root.height - 32px; x: 16px; y: 16px; source: @image-url("icons/tile_logo.png"); } } } // Right curtain right_curtain := Rectangle { background: #193076; border-radius: 4px; x: open_curtain ? parent.width : parent.width / 2 - 4px; width: open_curtain ? 0px : parent.width / 2 + 4px; height: parent.height; animate width { duration: 250ms; easing: ease-in; } animate x { duration: 250ms; easing: ease-in; } Clip { Image { width: root.width - 32px; height: root.height - 32px; x: right_curtain.width - width - 16px; y: 16px; source: @image-url("icons/tile_logo.png"); } } } TouchArea { width: 100%; height: 100%; clicked => { root.clicked(); } } } export MainWindow := Window { title: "Memory Game - SixtyFPS Demo"; callback check_if_pair_solved(); property disable_tiles; property tile_size: 80px; property tile_spacing: 10px; property row_count: 4; property column_count: 4; // "column_count + 1" and "row_count + 1" are the number of gaps between the tiles. width: (column_count * tile_size) + ((column_count + 1) * tile_spacing); height: (row_count * tile_size) + ((row_count + 1) * tile_spacing); property<[TileData]> memory_tiles : [ { image: @image-url("icons/at.png") }, { image: @image-url("icons/balance-scale.png") }, { image: @image-url("icons/bicycle.png") }, { image: @image-url("icons/bus.png") }, { image: @image-url("icons/cloud.png") }, { image: @image-url("icons/cogs.png") }, { image: @image-url("icons/motorcycle.png") }, { image: @image-url("icons/video.png") }, ]; for tile[i] in memory_tiles: MemoryTile { x: tile_spacing + mod(i, column_count) * (tile_size + tile_spacing); y: tile_spacing + floor(i / row_count) * (tile_size + tile_spacing); width: tile_size; height: tile_size; icon: tile.image; open_curtain: tile.image_visible || tile.solved; solved: tile.solved; clicked => { if (!root.disable_tiles) { tile.image_visible = !tile.image_visible; root.check_if_pair_solved(); } } } }