1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: MIT |
3 | |
4 | #[allow (dead_code)] |
5 | fn main() { |
6 | use slint::Model; |
7 | |
8 | let main_window = MainWindow::new().unwrap(); |
9 | |
10 | // Fetch the tiles from the model |
11 | let mut tiles: Vec<TileData> = main_window.get_memory_tiles().iter().collect(); |
12 | // Duplicate them to ensure that we have pairs |
13 | tiles.extend(tiles.clone()); |
14 | |
15 | // Randomly mix the tiles |
16 | use rand::seq::SliceRandom; |
17 | let mut rng = rand::thread_rng(); |
18 | tiles.shuffle(&mut rng); |
19 | |
20 | // ANCHOR: game_logic |
21 | // Assign the shuffled Vec to the model property |
22 | let tiles_model = std::rc::Rc::new(slint::VecModel::from(tiles)); |
23 | main_window.set_memory_tiles(tiles_model.clone().into()); |
24 | |
25 | let main_window_weak = main_window.as_weak(); |
26 | main_window.on_check_if_pair_solved(move || { |
27 | let mut flipped_tiles = |
28 | tiles_model.iter().enumerate().filter(|(_, tile)| tile.image_visible && !tile.solved); |
29 | |
30 | if let (Some((t1_idx, mut t1)), Some((t2_idx, mut t2))) = |
31 | (flipped_tiles.next(), flipped_tiles.next()) |
32 | { |
33 | let is_pair_solved = t1 == t2; |
34 | if is_pair_solved { |
35 | t1.solved = true; |
36 | tiles_model.set_row_data(t1_idx, t1); |
37 | t2.solved = true; |
38 | tiles_model.set_row_data(t2_idx, t2); |
39 | } else { |
40 | let main_window = main_window_weak.unwrap(); |
41 | main_window.set_disable_tiles(true); |
42 | let tiles_model = tiles_model.clone(); |
43 | slint::Timer::single_shot(std::time::Duration::from_secs(1), move || { |
44 | main_window.set_disable_tiles(false); |
45 | t1.image_visible = false; |
46 | tiles_model.set_row_data(t1_idx, t1); |
47 | t2.image_visible = false; |
48 | tiles_model.set_row_data(t2_idx, t2); |
49 | }); |
50 | } |
51 | } |
52 | }); |
53 | // ANCHOR_END: game_logic |
54 | main_window.run().unwrap(); |
55 | } |
56 | |
57 | slint::slint! { |
58 | struct TileData { |
59 | image: image, |
60 | image_visible: bool, |
61 | solved: bool, |
62 | } |
63 | |
64 | component MemoryTile inherits Rectangle { |
65 | callback clicked; |
66 | in property <bool> open_curtain; |
67 | in property <bool> solved; |
68 | in property <image> icon; |
69 | |
70 | height: 64px; |
71 | width: 64px; |
72 | background: solved ? #34CE57 : #3960D5; |
73 | animate background { duration: 800ms; } |
74 | |
75 | Image { |
76 | source: icon; |
77 | width: parent.width; |
78 | height: parent.height; |
79 | } |
80 | |
81 | // Left curtain |
82 | Rectangle { |
83 | background: #193076; |
84 | width: open_curtain ? 0px : (parent.width / 2); |
85 | height: parent.height; |
86 | animate width { duration: 250ms; easing: ease-in; } |
87 | } |
88 | |
89 | // Right curtain |
90 | Rectangle { |
91 | background: #193076; |
92 | x: open_curtain ? parent.width : (parent.width / 2); |
93 | width: open_curtain ? 0px : (parent.width / 2); |
94 | height: parent.height; |
95 | animate width { duration: 250ms; easing: ease-in; } |
96 | animate x { duration: 250ms; easing: ease-in; } |
97 | } |
98 | |
99 | TouchArea { |
100 | clicked => { |
101 | // Delegate to the user of this element |
102 | root.clicked(); |
103 | } |
104 | } |
105 | } |
106 | // ANCHOR: mainwindow_interface |
107 | export component MainWindow inherits Window { |
108 | width: 326px; |
109 | height: 326px; |
110 | |
111 | callback check_if_pair_solved(); // Added |
112 | in property <bool> disable_tiles; // Added |
113 | |
114 | in-out property <[TileData]> memory_tiles: [ |
115 | { image: @image-url("icons/at.png" ) }, |
116 | // ANCHOR_END: mainwindow_interface |
117 | { image: @image-url("icons/balance-scale.png" ) }, |
118 | { image: @image-url("icons/bicycle.png" ) }, |
119 | { image: @image-url("icons/bus.png" ) }, |
120 | { image: @image-url("icons/cloud.png" ) }, |
121 | { image: @image-url("icons/cogs.png" ) }, |
122 | { image: @image-url("icons/motorcycle.png" ) }, |
123 | { image: @image-url("icons/video.png" ) }, |
124 | ]; |
125 | // ANCHOR: tile_click_logic |
126 | for tile[i] in memory_tiles : MemoryTile { |
127 | x: mod(i, 4) * 74px; |
128 | y: floor(i / 4) * 74px; |
129 | width: 64px; |
130 | height: 64px; |
131 | icon: tile.image; |
132 | open_curtain: tile.image_visible || tile.solved; |
133 | // propagate the solved status from the model to the tile |
134 | solved: tile.solved; |
135 | clicked => { |
136 | // old: tile.image_visible = !tile.image_visible; |
137 | // new: |
138 | if (!root.disable_tiles) { |
139 | tile.image_visible = !tile.image_visible; |
140 | root.check_if_pair_solved(); |
141 | } |
142 | } |
143 | } |
144 | // ANCHOR_END: tile_click_logic |
145 | } |
146 | } |
147 | |