From c7667f5fb179ad23beeff6f044d499f6308395ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Wed, 15 May 2024 15:52:09 +0200
Subject: [PATCH] Normalize game architecture

---
 android/app/build.gradle                      |   2 +-
 android/gradle.properties                     |   4 +-
 assets/images/blank.png                       | Bin 197 -> 0 bytes
 assets/images/left-foot.png                   | Bin 6196 -> 0 bytes
 assets/images/left-hand.png                   | Bin 4383 -> 0 bytes
 assets/images/right-foot.png                  | Bin 6196 -> 0 bytes
 assets/images/right-hand.png                  | Bin 4325 -> 0 bytes
 assets/translations/en.json                   |  13 +-
 assets/translations/fr.json                   |  13 +-
 assets/ui/button_back.png                     | Bin 0 -> 3771 bytes
 assets/ui/button_delete_saved_game.png        | Bin 0 -> 5813 bytes
 assets/ui/button_resume_game.png              | Bin 0 -> 3659 bytes
 assets/ui/button_start.png                    | Bin 0 -> 3999 bytes
 assets/ui/game_end.png                        | Bin 0 -> 7937 bytes
 assets/ui/move-blank.png                      | Bin 0 -> 170 bytes
 assets/ui/move-left-foot.png                  | Bin 0 -> 2830 bytes
 assets/ui/move-left-hand.png                  | Bin 0 -> 1937 bytes
 assets/ui/move-right-foot.png                 | Bin 0 -> 2846 bytes
 assets/ui/move-right-hand.png                 | Bin 0 -> 1924 bytes
 assets/ui/placeholder.png                     | Bin 0 -> 170 bytes
 .../metadata/android/en-US/changelogs/24.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/24.txt  |   1 +
 images/build_game_images.sh                   |  80 ---------
 lib/config/color_theme.dart                   |  10 ++
 lib/config/colors.dart                        |  10 --
 lib/config/default_game_settings.dart         |  33 ++++
 lib/config/default_global_settings.dart       |  33 ++++
 lib/config/default_settings.dart              |   9 -
 lib/config/menu.dart                          |  52 ++++++
 lib/config/theme.dart                         |  10 +-
 lib/cubit/bottom_nav_cubit.dart               |  31 ----
 lib/cubit/game_cubit.dart                     | 109 +++++++++---
 lib/cubit/game_state.dart                     |  14 +-
 lib/cubit/nav_cubit.dart                      |  37 ++++
 lib/cubit/settings_cubit.dart                 |  39 -----
 lib/cubit/settings_game_cubit.dart            |  61 +++++++
 lib/cubit/settings_game_state.dart            |  15 ++
 lib/cubit/settings_global_cubit.dart          |  60 +++++++
 lib/cubit/settings_global_state.dart          |  15 ++
 lib/cubit/settings_state.dart                 |  19 ---
 lib/main.dart                                 |  98 +++++++----
 lib/models/game/game.dart                     | 116 +++++++++++++
 lib/models/{ => game}/move.dart               |   9 +-
 lib/models/{ => game}/twister_color.dart      |   0
 lib/models/{ => game}/twister_member.dart     |   0
 lib/models/settings/settings_game.dart        |  41 +++++
 lib/models/settings/settings_global.dart      |  41 +++++
 lib/ui/game/game_end.dart                     |  51 ++++++
 lib/ui/{widgets => helpers}/app_titles.dart   |  27 +--
 lib/ui/helpers/outlined_text_widget.dart      |  51 ++++++
 lib/ui/layouts/game_layout.dart               |  34 ++++
 lib/ui/layouts/parameters_layout.dart         | 154 +++++++++++++++++
 lib/ui/parameters/parameter_image.dart        |  38 +++++
 lib/ui/parameters/parameter_painter.dart      |  90 ++++++++++
 lib/ui/screens/home.dart                      |  26 ---
 lib/ui/screens/page_about.dart                |  41 +++++
 lib/ui/screens/page_game.dart                 |  24 +++
 lib/ui/screens/page_settings.dart             |  26 +++
 lib/ui/screens/settings.dart                  |  29 ----
 lib/ui/settings/settings_form.dart            |  63 +++++++
 lib/ui/settings/theme_card.dart               |  47 ++++++
 lib/ui/skeleton.dart                          |  46 +++--
 .../actions/button_delete_saved_game.dart     |  21 +++
 lib/ui/widgets/actions/button_game_quit.dart  |  21 +++
 .../actions/button_game_start_new.dart        |  34 ++++
 .../actions/button_resume_saved_game.dart     |  21 +++
 lib/ui/widgets/app_bar.dart                   |  18 --
 lib/ui/widgets/bottom_nav_bar.dart            |  48 ------
 lib/ui/widgets/game.dart                      | 159 ------------------
 lib/ui/widgets/game/game_board.dart           |  20 +++
 lib/ui/widgets/game/game_current_move.dart    |  80 +++++++++
 lib/ui/widgets/game/game_moves_history.dart   |  88 ++++++++++
 .../{show_move.dart => game/move.dart}        |  68 ++++----
 lib/ui/widgets/global_app_bar.dart            |  83 +++++++++
 lib/ui/widgets/settings_form.dart             | 113 -------------
 lib/ui/widgets/theme_card.dart                |  45 -----
 pubspec.lock                                  | 132 ++++++++-------
 pubspec.yaml                                  |  23 ++-
 .../app/build_application_resources.sh        |   2 +-
 {icons => resources/app}/featureGraphic.svg   |   0
 {icons => resources/app}/icon.svg             |   0
 resources/build_resources.sh                  |   7 +
 {tts => resources/tts}/generate_sounds.sh     |   2 +-
 resources/ui/build_ui_resources.sh            | 111 ++++++++++++
 resources/ui/images/button_back.svg           |   2 +
 .../ui/images/button_delete_saved_game.svg    |   2 +
 resources/ui/images/button_resume_game.svg    |   2 +
 resources/ui/images/button_start.svg          |   2 +
 resources/ui/images/game_end.svg              |   2 +
 .../ui/images/move-blank.svg                  |   0
 .../ui/images/move-left-foot.svg              |   0
 .../ui/images/move-left-hand.svg              |   0
 .../ui/images/move-right-foot.svg             |   0
 .../ui/images/move-right-hand.svg             |   0
 resources/ui/images/placeholder.svg           |   2 +
 95 files changed, 1953 insertions(+), 878 deletions(-)
 delete mode 100644 assets/images/blank.png
 delete mode 100644 assets/images/left-foot.png
 delete mode 100644 assets/images/left-hand.png
 delete mode 100644 assets/images/right-foot.png
 delete mode 100644 assets/images/right-hand.png
 create mode 100644 assets/ui/button_back.png
 create mode 100644 assets/ui/button_delete_saved_game.png
 create mode 100644 assets/ui/button_resume_game.png
 create mode 100644 assets/ui/button_start.png
 create mode 100644 assets/ui/game_end.png
 create mode 100644 assets/ui/move-blank.png
 create mode 100644 assets/ui/move-left-foot.png
 create mode 100644 assets/ui/move-left-hand.png
 create mode 100644 assets/ui/move-right-foot.png
 create mode 100644 assets/ui/move-right-hand.png
 create mode 100644 assets/ui/placeholder.png
 create mode 100644 fastlane/metadata/android/en-US/changelogs/24.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/24.txt
 delete mode 100755 images/build_game_images.sh
 create mode 100644 lib/config/color_theme.dart
 delete mode 100644 lib/config/colors.dart
 create mode 100644 lib/config/default_game_settings.dart
 create mode 100644 lib/config/default_global_settings.dart
 delete mode 100644 lib/config/default_settings.dart
 create mode 100644 lib/config/menu.dart
 delete mode 100644 lib/cubit/bottom_nav_cubit.dart
 create mode 100644 lib/cubit/nav_cubit.dart
 delete mode 100644 lib/cubit/settings_cubit.dart
 create mode 100644 lib/cubit/settings_game_cubit.dart
 create mode 100644 lib/cubit/settings_game_state.dart
 create mode 100644 lib/cubit/settings_global_cubit.dart
 create mode 100644 lib/cubit/settings_global_state.dart
 delete mode 100644 lib/cubit/settings_state.dart
 create mode 100644 lib/models/game/game.dart
 rename lib/models/{ => game}/move.dart (84%)
 rename lib/models/{ => game}/twister_color.dart (100%)
 rename lib/models/{ => game}/twister_member.dart (100%)
 create mode 100644 lib/models/settings/settings_game.dart
 create mode 100644 lib/models/settings/settings_global.dart
 create mode 100644 lib/ui/game/game_end.dart
 rename lib/ui/{widgets => helpers}/app_titles.dart (52%)
 create mode 100644 lib/ui/helpers/outlined_text_widget.dart
 create mode 100644 lib/ui/layouts/game_layout.dart
 create mode 100644 lib/ui/layouts/parameters_layout.dart
 create mode 100644 lib/ui/parameters/parameter_image.dart
 create mode 100644 lib/ui/parameters/parameter_painter.dart
 delete mode 100644 lib/ui/screens/home.dart
 create mode 100644 lib/ui/screens/page_about.dart
 create mode 100644 lib/ui/screens/page_game.dart
 create mode 100644 lib/ui/screens/page_settings.dart
 delete mode 100644 lib/ui/screens/settings.dart
 create mode 100644 lib/ui/settings/settings_form.dart
 create mode 100644 lib/ui/settings/theme_card.dart
 create mode 100644 lib/ui/widgets/actions/button_delete_saved_game.dart
 create mode 100644 lib/ui/widgets/actions/button_game_quit.dart
 create mode 100644 lib/ui/widgets/actions/button_game_start_new.dart
 create mode 100644 lib/ui/widgets/actions/button_resume_saved_game.dart
 delete mode 100644 lib/ui/widgets/app_bar.dart
 delete mode 100644 lib/ui/widgets/bottom_nav_bar.dart
 delete mode 100644 lib/ui/widgets/game.dart
 create mode 100644 lib/ui/widgets/game/game_board.dart
 create mode 100644 lib/ui/widgets/game/game_current_move.dart
 create mode 100644 lib/ui/widgets/game/game_moves_history.dart
 rename lib/ui/widgets/{show_move.dart => game/move.dart} (54%)
 create mode 100644 lib/ui/widgets/global_app_bar.dart
 delete mode 100644 lib/ui/widgets/settings_form.dart
 delete mode 100644 lib/ui/widgets/theme_card.dart
 rename icons/build_repository_icons.sh => resources/app/build_application_resources.sh (98%)
 rename {icons => resources/app}/featureGraphic.svg (100%)
 rename {icons => resources/app}/icon.svg (100%)
 create mode 100755 resources/build_resources.sh
 rename {tts => resources/tts}/generate_sounds.sh (98%)
 create mode 100755 resources/ui/build_ui_resources.sh
 create mode 100644 resources/ui/images/button_back.svg
 create mode 100644 resources/ui/images/button_delete_saved_game.svg
 create mode 100644 resources/ui/images/button_resume_game.svg
 create mode 100644 resources/ui/images/button_start.svg
 create mode 100644 resources/ui/images/game_end.svg
 rename images/blank.svg => resources/ui/images/move-blank.svg (100%)
 rename images/left-foot.svg => resources/ui/images/move-left-foot.svg (100%)
 rename images/left-hand.svg => resources/ui/images/move-left-hand.svg (100%)
 rename images/right-foot.svg => resources/ui/images/move-right-foot.svg (100%)
 rename images/right-hand.svg => resources/ui/images/move-right-hand.svg (100%)
 create mode 100644 resources/ui/images/placeholder.svg

diff --git a/android/app/build.gradle b/android/app/build.gradle
index 27a93e6..2328355 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -37,7 +37,7 @@ if (keystorePropertiesFile.exists()) {
 }
 
 android {
-    compileSdkVersion 33
+    compileSdkVersion 34
     namespace "org.benoitharrault.twister"
 
     defaultConfig {
diff --git a/android/gradle.properties b/android/gradle.properties
index 3487476..1913fd1 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.23
-app.versionCode=23
+app.versionName=0.1.0
+app.versionCode=24
diff --git a/assets/images/blank.png b/assets/images/blank.png
deleted file mode 100644
index 71f46e2afe84d6655d32e85d164c463cdfc5dabc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 197
zcmeAS@N?(olHy`uVBq!ia0y~yU}6AaMrH;EhI8B8b}}$9a29w(7BevL9R^{><M}I6
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJasB`Q|MDZ!
zCm0wQ7)yfuf*Bm1-AH3#U@-G^aSV}=e0z|Qk%57sX~DnsWgZ6@2!L~}O$-c-TiLVL
PffRbW`njxgN@xNA7Y;A$

diff --git a/assets/images/left-foot.png b/assets/images/left-foot.png
deleted file mode 100644
index fd46c1a8ac871945c801a6a353ebb0b70639df7f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 6196
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

diff --git a/assets/images/left-hand.png b/assets/images/left-hand.png
deleted file mode 100644
index 34d676bb3985fe6479e20d003c1be4370d20857d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4383
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
I=akR{0NP>|oB#j-

diff --git a/assets/images/right-foot.png b/assets/images/right-foot.png
deleted file mode 100644
index d0eff85495b7b8910389f948a712b02cde1909ef..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 6196
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

diff --git a/assets/images/right-hand.png b/assets/images/right-hand.png
deleted file mode 100644
index e730e5f4c58c8bdf3444ae7ff7ad45fe3e32e3e3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4325
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

diff --git a/assets/translations/en.json b/assets/translations/en.json
index 867a994..7ff9b8c 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -6,13 +6,14 @@
   "left_foot": "left foot",
   "right_foot": "right foot",
 
-  "bottom_nav_game": "Game",
-  "bottom_nav_settings": "Settings",
-
   "settings_title": "Settings",
   "settings_label_theme": "Theme mode",
-  "settings_title_game": "Game settings",
-  "settings_label_game_timer_value": "Timer value: ",
 
-  "lang_prefix": "en"
+  "lang_prefix": "en",
+
+  "about_title": "Informations",
+  "about_content": "Twister",
+  "about_version": "Version: {version}",
+
+  "": ""
 }
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index c481788..e2aafac 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -6,13 +6,14 @@
   "left_foot": "pied gauche",
   "right_foot": "pied droit",
 
-  "bottom_nav_game": "Jeu",
-  "bottom_nav_settings": "Réglages",
-
   "settings_title": "Réglages",
   "settings_label_theme": "Thème de couleurs",
-  "settings_title_game": "Paramètres du jeu",
-  "settings_label_game_timer_value": "Durée du chrono : ",
 
-  "lang_prefix": "fr"
+  "lang_prefix": "fr",
+
+  "about_title": "Informations",
+  "about_content": "Twister.",
+  "about_version": "Version : {version}",
+
+  "": ""
 }
diff --git a/assets/ui/button_back.png b/assets/ui/button_back.png
new file mode 100644
index 0000000000000000000000000000000000000000..cc48ffb1dbb653d9a996f139dfbe02969724bfa5
GIT binary patch
literal 3771
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

literal 0
HcmV?d00001

diff --git a/assets/ui/button_delete_saved_game.png b/assets/ui/button_delete_saved_game.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e4f217689b11e444b7163557d7e5d68f3bbfe7d
GIT binary patch
literal 5813
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

literal 0
HcmV?d00001

diff --git a/assets/ui/button_resume_game.png b/assets/ui/button_resume_game.png
new file mode 100644
index 0000000000000000000000000000000000000000..b2ea0a02d05e42377eb551a4b51428b511a32f5d
GIT binary patch
literal 3659
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

literal 0
HcmV?d00001

diff --git a/assets/ui/button_start.png b/assets/ui/button_start.png
new file mode 100644
index 0000000000000000000000000000000000000000..6845e2f5c21598ab61f1684d2075aeec0334bf23
GIT binary patch
literal 3999
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

literal 0
HcmV?d00001

diff --git a/assets/ui/game_end.png b/assets/ui/game_end.png
new file mode 100644
index 0000000000000000000000000000000000000000..876334279c1711b349a62131a33607eecf924eb6
GIT binary patch
literal 7937
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
P3=9mOu6{1-oD!M<Ur^e&

literal 0
HcmV?d00001

diff --git a/assets/ui/move-blank.png b/assets/ui/move-blank.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a504ec4e9ab530b04d5324bcfb4cf187a3c1b86
GIT binary patch
literal 170
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VLJ3*K+H)HNE
z1_lPn64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq!<_&m;-!5T>t<7zx;^w
z2?hoR#*!evU<QY0H_{jw7^FR2977}|-ySq%WME)8r0{!r94~(Y0|Ns?fsW7t2F7;w
Qi|;@@Pgg&ebxsLQ0Nd>^`~Uy|

literal 0
HcmV?d00001

diff --git a/assets/ui/move-left-foot.png b/assets/ui/move-left-foot.png
new file mode 100644
index 0000000000000000000000000000000000000000..1d4a90c1b42d4da8a617c0b10cad5c5dc9329b32
GIT binary patch
literal 2830
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

literal 0
HcmV?d00001

diff --git a/assets/ui/move-left-hand.png b/assets/ui/move-left-hand.png
new file mode 100644
index 0000000000000000000000000000000000000000..d8e288cc61afef47b8f6342fdf109098d321dde8
GIT binary patch
literal 1937
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0VLJ3*K+H)HNE
z1_lPn64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq!<{O90GhoT>t<7&oBx`
zLx9{6nCIWq!N9<<za+>nn1PXrnT3^&or9B$hnJ6EKu}0nL{v;lT1Hk*UO`b=MO95*
zLsLszPv5}M$k@cx%-q7#+Q!z-!O_Xt#og1(+s8K`Feo@AG%P$KGCC$UE-@)3H9aFM
zCpRy@ps=W<w6dzUuD+qMxwXBcv%9Caf5N26Q>IOyIcxTu`3sk=SiNrjhK-vxZ{4<Y
z_r61ij~qLG^3>@wXV0C#aOv`uYu9hyx_#%~{YQ_VJbm{3#miT(-@JYI{=>&lpTB(l
z_Wj4tU%&tS{rA-5S`q^T3%jR_V@SoVw|CNmgB?ZK9teA71hR-~iv{Sg1d41-a8xbZ
zsKg}p#^tCO_tB<~uDy#JWJRT21G^M|W=pwyh+Uhp>E7MPbH3lcYdpDfzGqSK_cS2}
zu2!do0U9DO%C+EE>N}I?K2Fi``=4*VJ8}0(i{H}gZr2~5)w*&2x=Z(jU(2*KOf8#!
zh4mrxog&s7moI+pf0xAI`hvl2+5W#eUE6bm!oD49+|M5rc|eurZ@5jV$y*EKFV`>n
z<TNxqdbiHkIFO0Y^7OVIXAX}t+m|6b8C6o&%}osuC}>-0{m`EwxcBjbuPIxy{xZ*=
zxy$-T!-30p+j%>?7?W=7Qvca-_}pWD<*Q6RsjsIMGOje6-paL=p>Q69o`Lq_i;PbD
z47Dp?Fzk&>bAOUwvHYy8{2Nw<iLsg!W9<Lsv_DP>GC7dk5U6=z)jRPouT!Qp@MQZ>
zJXXlTIPrbVteC40nRAj?`5b58aV*5Lga5*j5Y6N48;nBNJz_2qY+ztfU|{5MU|<r!
z&U|3cz;a~vG(9Ob)&hBjPTg?E4F~Q?&wR!wu=W4d^;gwrAKuD-qo_ChMv-jf<#!vj
zW2KkJ6f;LW`txj$o@a4Gej#g4QSE_kCM6A#Zys;$ab)YLxS3tTD!E|8c^y{Kgplg_
zH#tKZKJDAgK7*mya`XBQ2FI%>7%lhQl(uPD(ZA=Wr40jj`8Gygg@@MpU+j2z7j#*l
za{ug^^T;o&c_V{Ue1ZDs3o*U#p73d1e8b+h<<m9m#}^n*?RY)wPfiGj!qH>4t!_z-
zQ|>*}%V*JPaC`Uau!9Lh-6aNdht>Ce|7$x$>l7WZJHWf5-+?cJc?Y9;=?=ziD;uN(
zxOOncCrx1HVlaPDsZr#h_JA#fF|VOisptUb0p1MB7MXwrh4n84YDA^hnJx&_N!WYs
z@4~o@|I@3^GH!KZygBQ8`)Q@$<}I208y48H{ykIH`1dxuH^UO;yT`vQ*?+))(@G<T
z0Npk9y;J@b_(&wQ%N)o_+^(eZH!|V^`y6S>bU#j}HPcvU=q#%*-l4;AM}WyfZ>|0B
z`3Lqb3x4$fFRPsxg9ck?q{;(M2~}Z+>wnp1EdAF0!>qnMNwA1<!)<?uwkQ7<?0+6!
z&+T!Zqh3!#uJt7Qftvf@S?51;XifS3XX-be0Oji1J<_>Mp+QeBtKTRJP~U0xKHo)$
zZR)0Tx1;ywr#D1-R=o@Tzx%M`R+soMkKR@*u!#7yE&slH{?evdotsLk0{%a~CJ<n@
zQT5vX+y-uC$CpRM%yv|N%rR{EbaD2nSv%g|mzlecS%!1o=H-+2daSjdZ*Iv@psJP{
n`A={2&6o*$?_^+P(3(1il76*Yi*)5KfJ#PBS3j3^P6<r_RYX*1

literal 0
HcmV?d00001

diff --git a/assets/ui/move-right-foot.png b/assets/ui/move-right-foot.png
new file mode 100644
index 0000000000000000000000000000000000000000..f9fa2905b064ca539d6785851d89ae3e55428d4d
GIT binary patch
literal 2846
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

literal 0
HcmV?d00001

diff --git a/assets/ui/move-right-hand.png b/assets/ui/move-right-hand.png
new file mode 100644
index 0000000000000000000000000000000000000000..297d74dff520bba8e4ab33b893a1fe4f49fcf197
GIT binary patch
literal 1924
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0VLJ3*K+H)HNE
z1_lPn64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq!<{OOagpDT>t<7&oBx`
zLx7YJ@JjELWME*}T@vIM%)rRR%)-jX&cVsW&BM#bFCZu+A}S^>B`qT>C$FHWq^zQ<
zrmmr-t*38bXk=_+YG!U>X=QC=YiIB1<m}?=;pOcU5Ev938WtWA6&Ih7n3A56nU#}U
zP*_x4Rb5kCSKrXm+R@q7-P_kcdFqUrv*s>XykzOJ<ttXMS-WoihK-vxZ`rzS=idDX
z4jwvu^!SNWXU|=@c<IX3Yu9hwx_$TlgNKhEKY9A>`HPpYUcY(!?)}G4pTB(l_Wj4t
zU%&tS{g=0J&lCm*7A{X0$B>F!Z}0rHo)Rc>;A69!(9|s%mzA^@2J~h)Z(HQLX-bgd
zP4C}vUY<)ct}dFSntd|je*HT4i8~*w85i&UKJU5Z{rmTRpSGO;-0-kY97ES44FnRp
z_v^}?#~a^eT<5P_$9sKd>VcjA_c7)!anF<Ze*a^6z3=Ykg8IYOXV+BJG|YYWJG=iQ
zBbUU112QEIt9cwgyR+{&&a|yZrrK?(3Y(<@i$uM=-mW{=HG$&&A_CV8t0EtD2yR%G
z{l+T%=-j)9zaL*Wli|aKH&q4!JHOg`*Yo6m(|Q)qQ2*?~qO9NSX8r5J-ke}hF=Bt)
zWy>{fd*9o#Hhzs%f3X#;JF>Uk3eXTQ=(LSodgY(pnLKkf<`02f6Ar$)_O^#F;Dp|G
zA=w8qyJH$e8Jh2Z6DYsR&^Vc`;t9Wf?aXy++_-MsF!;6MX0y<P>vrEJsS7C{Sa|Bq
zu1qsK2Z`bdjr<eN%Y-~)zLUmx>jUGe8O?QX8W@=b8W>m<7#KMm7;rE@M9av^@4h9d
zeZX|<yYCy$FSk)+YKhca{x)fU(3j`GMND@wn_cOx)swYlTwtV8Il*=%pWmxw|99-m
zva6Vte4c&g`y-tY9L)dWWfFUyD_g;e4KpI%w{dT%ymKNarr}Yca`m*uOjr8mSIUY$
zP)~nh=F=c|?m{@5OM~0JD~CH6wpRq-w*AO3X=ifx2ZosF9m&@p{R~!Ww%*Rff8fJ3
zYYR4B2Bn?NuVXJV=)|Y>PU&QSaQpb|J9}Ap4?K#uakuVgH+U|c|7C(8F9Tm;y1lkD
zbHS>oeEIIo4F$QYF1_wun|*`vp6v<73B9rpt~JOoc-~;-^PkA9kiucfaB2hdo_)&f
z2MpgZOy@trD9|p;z`ud{8m|Jo183QRKYmXb9{Mlc#hg|r%5CtHx1l+SaqTW<9{E<L
zSEcL@s{#&q|7Fy3l4pJTi}{G1pr{wa8DmbCCEg4NDjOT#8Zpdf`6oBIxP6BCA%^oy
z-sBfP*RR%^z#O6VhPTVWlHu9A@^4q(sBliu;0Vykte<gFkxk+Kwbr9f-_}psX20fz
zIAh0Tc7acVueoQI$9;LZSzh5gTXbdFd;PD^{211K+h=6_^CatmJZr|83f8~xJy|ua
zzPx6-l=Zj#&ul+`-uf5Yd~ogpC%4)5|NPiZy(G5e{?`duy4UQlXQ9*;%~QYTFIqTx
zLC`TZ?eFjJvS&U0dSumK`_`tcolhb^9=v>Z=Yj;q_3At8f|XX>{GyyY`R7ahPYkJ_
zPyD^VJpFI_^u|kPy{hdG{_4Hy?f6rsx3%}r`}DYuQZ^Y&)+KlU9MZWTRHu|A_287P
shT_u<KR>^)s+t#03y?DEA`QpCOnL8Tb_A8Zu>%!`p00i_>zopr0B&VuIsgCw

literal 0
HcmV?d00001

diff --git a/assets/ui/placeholder.png b/assets/ui/placeholder.png
new file mode 100644
index 0000000000000000000000000000000000000000..814df31be6ddc4275ebe4490c79365578dbef1f0
GIT binary patch
literal 170
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0WCPk}I_+{y{!
z3=9mCC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NHH)lFbDXAxc>kDfB6yV
z6ATOtj3q&S!3+-1Zlp0VFi3m4IEF|_zCCEj$iTpGNa6SLI9~n)1_lO(0v(|P42<pU
Q7vF(+p00i_>zopr0K3yKtN;K2

literal 0
HcmV?d00001

diff --git a/fastlane/metadata/android/en-US/changelogs/24.txt b/fastlane/metadata/android/en-US/changelogs/24.txt
new file mode 100644
index 0000000..d4afd51
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/24.txt
@@ -0,0 +1 @@
+Improve/normalize game architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/24.txt b/fastlane/metadata/android/fr-FR/changelogs/24.txt
new file mode 100644
index 0000000..6a9871a
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/24.txt
@@ -0,0 +1 @@
+Amélioration/normalisation de l'architecture du jeu.
diff --git a/images/build_game_images.sh b/images/build_game_images.sh
deleted file mode 100755
index 4d7f1be..0000000
--- a/images/build_game_images.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#! /bin/bash
-
-# Check dependencies
-command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
-command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; }
-command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
-
-CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
-BASE_DIR="$(dirname "${CURRENT_DIR}")"
-ASSETS_DIR="${BASE_DIR}/assets"
-
-OPTIPNG_OPTIONS="-preserve -quiet -o7"
-ICON_SIZE=512
-
-#######################################################
-
-# Game images
-AVAILABLE_GAME_IMAGES="
-  blank
-  left-hand
-  right-hand
-  left-foot
-  right-foot
-"
-#######################################################
-
-# optimize svg
-function optimize_svg() {
-  SOURCE="$1"
-
-  cp ${SOURCE} ${SOURCE}.tmp
-  scour \
-      --remove-descriptive-elements \
-      --enable-id-stripping \
-      --enable-viewboxing \
-      --enable-comment-stripping \
-      --nindent=4 \
-      --quiet \
-      -i ${SOURCE}.tmp \
-      -o ${SOURCE}
-  rm ${SOURCE}.tmp
-}
-
-# build icons
-function build_icon() {
-  SOURCE="$1"
-  TARGET="$2"
-
-  echo "Building ${TARGET}"
-
-  if [ ! -f "${SOURCE}" ]; then
-    echo "Missing file: ${SOURCE}"
-    exit 1
-  fi
-
-  optimize_svg "${SOURCE}"
-
-  inkscape \
-      --export-width=${ICON_SIZE} \
-      --export-height=${ICON_SIZE} \
-      --export-filename=${TARGET} \
-      ${SOURCE}
-
-  optipng ${OPTIPNG_OPTIONS} ${TARGET}
-}
-
-#######################################################
-
-# Create output folder
-mkdir -p ${ASSETS_DIR}/images
-
-# Delete existing generated images
-find ${ASSETS_DIR}/images -type f -name "*.png" -delete
-
-# build game images
-for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}
-do
-  build_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${ASSETS_DIR}/images/${GAME_IMAGE}.png
-done
-
diff --git a/lib/config/color_theme.dart b/lib/config/color_theme.dart
new file mode 100644
index 0000000..6b0ae12
--- /dev/null
+++ b/lib/config/color_theme.dart
@@ -0,0 +1,10 @@
+import 'package:flutter/material.dart';
+
+class TwisterColors {
+  static const Color grey = Color.fromARGB(255, 0xF0, 0xE2, 0xE7); // F0E2E7
+
+  static const Color blue = Color.fromARGB(255, 0x3F, 0x84, 0xE5); // 3F84E5
+  static const Color green = Color.fromARGB(255, 0x1D, 0xA2, 0x3C); // 1DA23C
+  static const Color red = Color.fromARGB(255, 0xE0, 0x0D, 0x3B); // E00D3B
+  static const Color yellow = Color.fromARGB(255, 0xE8, 0xD9, 0x17); // E8D917
+}
diff --git a/lib/config/colors.dart b/lib/config/colors.dart
deleted file mode 100644
index 988ca61..0000000
--- a/lib/config/colors.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-import 'package:flutter/material.dart';
-
-class TwisterColors {
-  static const Color grey = Color.fromARGB(255, 0xF0, 0xE2, 0xE7); // F0E2E7
-
-  static const Color blue = Color.fromARGB(255, 0x3F, 0x84, 0xE5); // 3F84E5
-  static const Color green = Color.fromARGB(255, 0x3F, 0x78, 0x4C); // 3F784C
-  static const Color red = Color.fromARGB(255, 0xB2, 0x0D, 0x30); // B20D30
-  static const Color yellow = Color.fromARGB(255, 0xC1, 0x78, 0x17); // C17817
-}
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart
new file mode 100644
index 0000000..d2d7d49
--- /dev/null
+++ b/lib/config/default_game_settings.dart
@@ -0,0 +1,33 @@
+import 'package:twister/utils/tools.dart';
+
+class DefaultGameSettings {
+  // available global parameters codes
+  static const String parameterCodeTimerValue = 'timer';
+  static const List<String> availableParameters = [
+    parameterCodeTimerValue,
+  ];
+
+  // timer value: available values
+  static const String timerValueMedium = 'medium';
+  static const List<String> allowedTimerValues = [
+    timerValueMedium,
+  ];
+  // timer value: default value
+  static const String defaultTimerValue = timerValueMedium;
+
+  // available values from parameter code
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeTimerValue:
+        return DefaultGameSettings.allowedTimerValues;
+    }
+
+    printlog('Did not find any available value for game parameter "$parameterCode".');
+    return [];
+  }
+
+  // parameters displayed with assets (instead of painter)
+  static List<String> displayedWithAssets = [
+    //
+  ];
+}
diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart
new file mode 100644
index 0000000..f090d53
--- /dev/null
+++ b/lib/config/default_global_settings.dart
@@ -0,0 +1,33 @@
+import 'package:twister/utils/tools.dart';
+
+class DefaultGlobalSettings {
+  // available global parameters codes
+  static const String parameterCodeSkin = 'skin';
+  static const List<String> availableParameters = [
+    parameterCodeSkin,
+  ];
+
+  // skin: available values
+  static const String skinValueColors = 'colors';
+  static const List<String> allowedSkinValues = [
+    skinValueColors,
+  ];
+  // skin: default value
+  static const String defaultSkinValue = skinValueColors;
+
+  // available values from parameter code
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeSkin:
+        return DefaultGlobalSettings.allowedSkinValues;
+    }
+
+    printlog('Did not find any available value for global parameter "$parameterCode".');
+    return [];
+  }
+
+  // parameters displayed with assets (instead of painter)
+  static List<String> displayedWithAssets = [
+    //
+  ];
+}
diff --git a/lib/config/default_settings.dart b/lib/config/default_settings.dart
deleted file mode 100644
index c327148..0000000
--- a/lib/config/default_settings.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-class DefaultSettings {
-  static const int defaultTimerValue = 20;
-
-  static const List<int> allowedTimerValues = [
-    10,
-    defaultTimerValue,
-    30,
-  ];
-}
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
new file mode 100644
index 0000000..1af3bf3
--- /dev/null
+++ b/lib/config/menu.dart
@@ -0,0 +1,52 @@
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:twister/ui/screens/page_about.dart';
+import 'package:twister/ui/screens/page_game.dart';
+import 'package:twister/ui/screens/page_settings.dart';
+
+class MenuItem {
+  final Icon icon;
+  final Widget page;
+
+  const MenuItem({
+    required this.icon,
+    required this.page,
+  });
+}
+
+class Menu {
+  static const indexGame = 0;
+  static const menuItemGame = MenuItem(
+    icon: Icon(UniconsLine.home),
+    page: PageGame(),
+  );
+
+  static const indexSettings = 1;
+  static const menuItemSettings = MenuItem(
+    icon: Icon(UniconsLine.setting),
+    page: PageSettings(),
+  );
+
+  static const indexAbout = 2;
+  static const menuItemAbout = MenuItem(
+    icon: Icon(UniconsLine.info_circle),
+    page: PageAbout(),
+  );
+
+  static Map<int, MenuItem> items = {
+    indexGame: menuItemGame,
+    indexSettings: menuItemSettings,
+    indexAbout: menuItemAbout,
+  };
+
+  static bool isIndexAllowed(int pageIndex) {
+    return items.keys.contains(pageIndex);
+  }
+
+  static Widget getPageWidget(int pageIndex) {
+    return items[pageIndex]?.page ?? menuItemGame.page;
+  }
+
+  static int itemsCount = Menu.items.length;
+}
diff --git a/lib/config/theme.dart b/lib/config/theme.dart
index be39034..74f532f 100644
--- a/lib/config/theme.dart
+++ b/lib/config/theme.dart
@@ -39,11 +39,9 @@ final ColorScheme lightColorScheme = ColorScheme.light(
   secondary: primarySwatch.shade500,
   onSecondary: Colors.white,
   error: errorColor,
-  background: textSwatch.shade200,
-  onBackground: textSwatch.shade500,
   onSurface: textSwatch.shade500,
   surface: textSwatch.shade50,
-  surfaceVariant: Colors.white,
+  surfaceContainerHighest: Colors.white,
   shadow: textSwatch.shade900.withOpacity(.1),
 );
 
@@ -52,11 +50,9 @@ final ColorScheme darkColorScheme = ColorScheme.dark(
   secondary: primarySwatch.shade500,
   onSecondary: Colors.white,
   error: errorColor,
-  background: const Color(0xFF171724),
-  onBackground: textSwatch.shade400,
   onSurface: textSwatch.shade300,
   surface: const Color(0xFF262630),
-  surfaceVariant: const Color(0xFF282832),
+  surfaceContainerHighest: const Color(0xFF282832),
   shadow: textSwatch.shade900.withOpacity(.2),
 );
 
@@ -192,5 +188,3 @@ final ThemeData darkTheme = lightTheme.copyWith(
     ),
   ),
 );
-
-final ThemeData appTheme = darkTheme;
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/bottom_nav_cubit.dart
deleted file mode 100644
index c633c65..0000000
--- a/lib/cubit/bottom_nav_cubit.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-import 'package:hydrated_bloc/hydrated_bloc.dart';
-
-class BottomNavCubit extends HydratedCubit<int> {
-  BottomNavCubit() : super(0);
-
-  int pagesCount = 2;
-
-  void updateIndex(int index) {
-    if (isIndexAllowed(index)) {
-      emit(index);
-    } else {
-      goToHomePage();
-    }
-  }
-
-  bool isIndexAllowed(int index) {
-    return (index >= 0) && (index < pagesCount);
-  }
-
-  void goToHomePage() => emit(0);
-
-  @override
-  int? fromJson(Map<String, dynamic> json) {
-    return 0;
-  }
-
-  @override
-  Map<String, dynamic>? toJson(int state) {
-    return <String, int>{'pageIndex': state};
-  }
-}
diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart
index 325c872..f0eed2c 100644
--- a/lib/cubit/game_cubit.dart
+++ b/lib/cubit/game_cubit.dart
@@ -1,53 +1,118 @@
+import 'package:audioplayers/audioplayers.dart';
 import 'package:equatable/equatable.dart';
 import 'package:flutter/material.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 
-import 'package:twister/models/move.dart';
+import 'package:twister/models/game/game.dart';
+import 'package:twister/models/game/move.dart';
+import 'package:twister/models/settings/settings_game.dart';
+import 'package:twister/models/settings/settings_global.dart';
 
 part 'game_state.dart';
 
 class GameCubit extends HydratedCubit<GameState> {
-  GameCubit() : super(const GameState());
+  GameCubit()
+      : super(GameState(
+          currentGame: Game.createEmpty(),
+        ));
 
-  Move getMove() {
-    return state.move ?? Move.createNull();
+  void updateState(Game game) {
+    emit(GameState(
+      currentGame: game,
+    ));
   }
 
-  void setValues({
-    Move? move,
+  void refresh() {
+    final Game game = Game(
+      // Settings
+      gameSettings: state.currentGame.gameSettings,
+      globalSettings: state.currentGame.globalSettings,
+      // State
+      isRunning: state.currentGame.isRunning,
+      isStarted: state.currentGame.isStarted,
+      isFinished: state.currentGame.isFinished,
+      animationInProgress: state.currentGame.animationInProgress,
+      // Base data
+      move: state.currentGame.move,
+      // Game data
+      history: state.currentGame.history,
+    );
+    // game.dump();
+
+    updateState(game);
+  }
+
+  void startNewGame({
+    required GameSettings gameSettings,
+    required GlobalSettings globalSettings,
   }) {
-    List<Move> history = state.history ?? [];
-    if (move != null) {
-      history.add(move);
-    }
+    final Game newGame = Game.createNew(
+      // Settings
+      gameSettings: gameSettings,
+      globalSettings: globalSettings,
+    );
 
-    emit(GameState(
-      move: move ?? state.move,
-      history: history,
-    ));
+    newGame.dump();
+
+    updateState(newGame);
+    refresh();
+  }
+
+  void quitGame() {
+    state.currentGame.isRunning = false;
+    refresh();
+  }
+
+  void resumeSavedGame() {
+    state.currentGame.isRunning = true;
+    refresh();
+  }
+
+  void deleteSavedGame() {
+    state.currentGame.isRunning = false;
+    state.currentGame.isFinished = true;
+    refresh();
+  }
+
+  void setMove(Move move) {
+    state.currentGame.isStarted = true;
+    state.currentGame.move = move;
+    state.currentGame.history.add(move);
+    refresh();
   }
 
   void deleteHistory() {
-    List<Move> history = [];
-    emit(GameState(
-      move: state.move,
-      history: history,
-    ));
+    state.currentGame.history = [];
+    state.currentGame.isStarted = false;
+    refresh();
+  }
+
+  void setAnimationIsRunning(bool isRunning) {
+    state.currentGame.animationInProgress = isRunning;
+    refresh();
+  }
+
+  void pickNewMove() {
+    Move newMove = Move.pickRandom();
+    setMove(newMove);
+
+    final player = AudioPlayer();
+    player.play(AssetSource(newMove.toSoundAsset()));
   }
 
   @override
   GameState? fromJson(Map<String, dynamic> json) {
-    Move move = json['move'] as Move;
+    final Game currentGame = json['currentGame'] as Game;
 
     return GameState(
-      move: move,
+      currentGame: currentGame,
     );
   }
 
   @override
   Map<String, dynamic>? toJson(GameState state) {
     return <String, dynamic>{
-      'move': state.move?.toJson(),
+      'currentGame': state.currentGame.toJson(),
     };
   }
 }
diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart
index 204801e..00e2116 100644
--- a/lib/cubit/game_state.dart
+++ b/lib/cubit/game_state.dart
@@ -3,21 +3,13 @@ part of 'game_cubit.dart';
 @immutable
 class GameState extends Equatable {
   const GameState({
-    this.move,
-    this.history,
+    required this.currentGame,
   });
 
-  final Move? move;
-  final List<Move>? history;
+  final Game currentGame;
 
   @override
   List<dynamic> get props => <dynamic>[
-        move,
-        history,
+        currentGame,
       ];
-
-  Map<String, dynamic> get values => <String, dynamic>{
-        'move': move,
-        'history': history,
-      };
 }
diff --git a/lib/cubit/nav_cubit.dart b/lib/cubit/nav_cubit.dart
new file mode 100644
index 0000000..c998a44
--- /dev/null
+++ b/lib/cubit/nav_cubit.dart
@@ -0,0 +1,37 @@
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:twister/config/menu.dart';
+
+class NavCubit extends HydratedCubit<int> {
+  NavCubit() : super(0);
+
+  void updateIndex(int index) {
+    if (Menu.isIndexAllowed(index)) {
+      emit(index);
+    } else {
+      goToGamePage();
+    }
+  }
+
+  void goToGamePage() {
+    emit(Menu.indexGame);
+  }
+
+  void goToSettingsPage() {
+    emit(Menu.indexSettings);
+  }
+
+  void goToAboutPage() {
+    emit(Menu.indexAbout);
+  }
+
+  @override
+  int fromJson(Map<String, dynamic> json) {
+    return Menu.indexGame;
+  }
+
+  @override
+  Map<String, dynamic>? toJson(int state) {
+    return <String, int>{'pageIndex': state};
+  }
+}
diff --git a/lib/cubit/settings_cubit.dart b/lib/cubit/settings_cubit.dart
deleted file mode 100644
index 200abf9..0000000
--- a/lib/cubit/settings_cubit.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-import 'package:equatable/equatable.dart';
-import 'package:flutter/material.dart';
-import 'package:hydrated_bloc/hydrated_bloc.dart';
-
-import 'package:twister/config/default_settings.dart';
-
-part 'settings_state.dart';
-
-class SettingsCubit extends HydratedCubit<SettingsState> {
-  SettingsCubit() : super(const SettingsState());
-
-  int getTimerValue() {
-    return state.timerValue ?? DefaultSettings.defaultTimerValue;
-  }
-
-  void setValues({
-    int? timerValue,
-  }) {
-    emit(SettingsState(
-      timerValue: timerValue ?? state.timerValue,
-    ));
-  }
-
-  @override
-  SettingsState? fromJson(Map<String, dynamic> json) {
-    int timerValue = json['timerValue'] as int;
-
-    return SettingsState(
-      timerValue: timerValue,
-    );
-  }
-
-  @override
-  Map<String, dynamic>? toJson(SettingsState state) {
-    return <String, dynamic>{
-      'timerValue': state.timerValue ?? DefaultSettings.defaultTimerValue,
-    };
-  }
-}
diff --git a/lib/cubit/settings_game_cubit.dart b/lib/cubit/settings_game_cubit.dart
new file mode 100644
index 0000000..e9a16c0
--- /dev/null
+++ b/lib/cubit/settings_game_cubit.dart
@@ -0,0 +1,61 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:twister/config/default_game_settings.dart';
+import 'package:twister/models/settings/settings_game.dart';
+
+part 'settings_game_state.dart';
+
+class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
+  GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault()));
+
+  void setValues({
+    String? timerValue,
+  }) {
+    emit(
+      GameSettingsState(
+        settings: GameSettings(
+          timerValue: timerValue ?? state.settings.timerValue,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGameSettings.parameterCodeTimerValue:
+        return GameSettings.getTimerValueFromUnsafe(state.settings.timerValue);
+    }
+
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String timerValue = code == DefaultGameSettings.parameterCodeTimerValue
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeTimerValue);
+
+    setValues(
+      timerValue: timerValue,
+    );
+  }
+
+  @override
+  GameSettingsState? fromJson(Map<String, dynamic> json) {
+    final String timerValue = json[DefaultGameSettings.parameterCodeTimerValue] as String;
+
+    return GameSettingsState(
+      settings: GameSettings(
+        timerValue: timerValue,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameSettingsState state) {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeTimerValue: state.settings.timerValue,
+    };
+  }
+}
diff --git a/lib/cubit/settings_game_state.dart b/lib/cubit/settings_game_state.dart
new file mode 100644
index 0000000..5acd85b
--- /dev/null
+++ b/lib/cubit/settings_game_state.dart
@@ -0,0 +1,15 @@
+part of 'settings_game_cubit.dart';
+
+@immutable
+class GameSettingsState extends Equatable {
+  const GameSettingsState({
+    required this.settings,
+  });
+
+  final GameSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+}
diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings_global_cubit.dart
new file mode 100644
index 0000000..1742cfb
--- /dev/null
+++ b/lib/cubit/settings_global_cubit.dart
@@ -0,0 +1,60 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:twister/config/default_global_settings.dart';
+import 'package:twister/models/settings/settings_global.dart';
+
+part 'settings_global_state.dart';
+
+class GlobalSettingsCubit extends HydratedCubit<GlobalSettingsState> {
+  GlobalSettingsCubit() : super(GlobalSettingsState(settings: GlobalSettings.createDefault()));
+
+  void setValues({
+    String? skin,
+  }) {
+    emit(
+      GlobalSettingsState(
+        settings: GlobalSettings(
+          skin: skin ?? state.settings.skin,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGlobalSettings.parameterCodeSkin:
+        return GlobalSettings.getSkinValueFromUnsafe(state.settings.skin);
+    }
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String skin = (code == DefaultGlobalSettings.parameterCodeSkin)
+        ? value
+        : getParameterValue(DefaultGlobalSettings.parameterCodeSkin);
+
+    setValues(
+      skin: skin,
+    );
+  }
+
+  @override
+  GlobalSettingsState? fromJson(Map<String, dynamic> json) {
+    final String skin = json[DefaultGlobalSettings.parameterCodeSkin] as String;
+
+    return GlobalSettingsState(
+      settings: GlobalSettings(
+        skin: skin,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GlobalSettingsState state) {
+    return <String, dynamic>{
+      DefaultGlobalSettings.parameterCodeSkin: state.settings.skin,
+    };
+  }
+}
diff --git a/lib/cubit/settings_global_state.dart b/lib/cubit/settings_global_state.dart
new file mode 100644
index 0000000..ebcddd7
--- /dev/null
+++ b/lib/cubit/settings_global_state.dart
@@ -0,0 +1,15 @@
+part of 'settings_global_cubit.dart';
+
+@immutable
+class GlobalSettingsState extends Equatable {
+  const GlobalSettingsState({
+    required this.settings,
+  });
+
+  final GlobalSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+}
diff --git a/lib/cubit/settings_state.dart b/lib/cubit/settings_state.dart
deleted file mode 100644
index 6048256..0000000
--- a/lib/cubit/settings_state.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-part of 'settings_cubit.dart';
-
-@immutable
-class SettingsState extends Equatable {
-  const SettingsState({
-    this.timerValue,
-  });
-
-  final int? timerValue;
-
-  @override
-  List<dynamic> get props => <dynamic>[
-        timerValue,
-      ];
-
-  Map<String, dynamic> get values => <String, dynamic>{
-        'timerValue': timerValue,
-      };
-}
diff --git a/lib/main.dart b/lib/main.dart
index 78da985..d77b529 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -2,20 +2,22 @@ import 'dart:io';
 
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:hive/hive.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 import 'package:path_provider/path_provider.dart';
 
 import 'package:twister/config/theme.dart';
-import 'package:twister/cubit/bottom_nav_cubit.dart';
 import 'package:twister/cubit/game_cubit.dart';
-import 'package:twister/cubit/settings_cubit.dart';
+import 'package:twister/cubit/nav_cubit.dart';
+import 'package:twister/cubit/settings_game_cubit.dart';
+import 'package:twister/cubit/settings_global_cubit.dart';
 import 'package:twister/cubit/theme_cubit.dart';
 import 'package:twister/ui/skeleton.dart';
 
 void main() async {
-  /// Initialize packages
+  // Initialize packages
   WidgetsFlutterBinding.ensureInitialized();
   await EasyLocalization.ensureInitialized();
   final Directory tmpDir = await getTemporaryDirectory();
@@ -24,18 +26,17 @@ void main() async {
     storageDirectory: tmpDir,
   );
 
-  runApp(
-    EasyLocalization(
-      path: 'assets/translations',
-      supportedLocales: const <Locale>[
-        Locale('en'),
-        Locale('fr'),
-      ],
-      fallbackLocale: const Locale('en'),
-      useFallbackTranslations: true,
-      child: const MyApp(),
-    ),
-  );
+  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
+      .then((value) => runApp(EasyLocalization(
+            path: 'assets/translations',
+            supportedLocales: const <Locale>[
+              Locale('en'),
+              Locale('fr'),
+            ],
+            fallbackLocale: const Locale('en'),
+            useFallbackTranslations: true,
+            child: const MyApp(),
+          )));
 }
 
 class MyApp extends StatelessWidget {
@@ -43,31 +44,62 @@ class MyApp extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    final List<String> assets = getImagesAssets();
+    for (String asset in assets) {
+      precacheImage(AssetImage(asset), context);
+    }
+
     return MultiBlocProvider(
       providers: [
-        BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
-        BlocProvider<GameCubit>(create: (context) => GameCubit()),
-        BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
+        BlocProvider<NavCubit>(create: (context) => NavCubit()),
         BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
+        BlocProvider<GameCubit>(create: (context) => GameCubit()),
+        BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()),
+        BlocProvider<GameSettingsCubit>(create: (context) => GameSettingsCubit()),
       ],
       child: BlocBuilder<ThemeCubit, ThemeModeState>(
-          builder: (BuildContext context, ThemeModeState state) {
-        return MaterialApp(
-          title: 'Twister',
-          home: const SkeletonScreen(),
+        builder: (BuildContext context, ThemeModeState state) {
+          return MaterialApp(
+            title: 'Twister',
+            home: const SkeletonScreen(),
 
-          // Theme stuff
-          theme: lightTheme,
-          darkTheme: darkTheme,
-          themeMode: state.themeMode,
+            // Theme stuff
+            theme: lightTheme,
+            darkTheme: darkTheme,
+            themeMode: state.themeMode,
 
-          // Localization stuff
-          localizationsDelegates: context.localizationDelegates,
-          supportedLocales: context.supportedLocales,
-          locale: context.locale,
-          debugShowCheckedModeBanner: false,
-        );
-      }),
+            // Localization stuff
+            localizationsDelegates: context.localizationDelegates,
+            supportedLocales: context.supportedLocales,
+            locale: context.locale,
+            debugShowCheckedModeBanner: false,
+          );
+        },
+      ),
     );
   }
+
+  List<String> getImagesAssets() {
+    final List<String> assets = [];
+
+    const List<String> gameImages = [
+      'button_back',
+      'button_delete_saved_game',
+      'button_resume_game',
+      'button_start',
+      'game_end',
+      'move-blank',
+      'move-left-foot',
+      'move-left-hand',
+      'move-right-foot',
+      'move-right-hand',
+      'placeholder',
+    ];
+
+    for (String image in gameImages) {
+      assets.add('assets/ui/$image.png');
+    }
+
+    return assets;
+  }
 }
diff --git a/lib/models/game/game.dart b/lib/models/game/game.dart
new file mode 100644
index 0000000..3ba1cd2
--- /dev/null
+++ b/lib/models/game/game.dart
@@ -0,0 +1,116 @@
+import 'package:twister/models/game/move.dart';
+import 'package:twister/models/settings/settings_game.dart';
+import 'package:twister/models/settings/settings_global.dart';
+import 'package:twister/utils/tools.dart';
+
+class Game {
+  Game({
+    // Settings
+    required this.gameSettings,
+    required this.globalSettings,
+
+    // State
+    this.isRunning = false,
+    this.isStarted = false,
+    this.isFinished = false,
+    this.animationInProgress = false,
+
+    // Base data
+    required this.move,
+
+    // Game data
+    required this.history,
+  });
+
+  // Settings
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  // State
+  bool isRunning;
+  bool isStarted;
+  bool isFinished;
+  bool animationInProgress;
+
+  // Base data
+  Move? move;
+
+  // Game data
+  List<Move> history;
+
+  factory Game.createEmpty() {
+    return Game(
+      // Settings
+      gameSettings: GameSettings.createDefault(),
+      globalSettings: GlobalSettings.createDefault(),
+      // Base data
+      move: Move.createEmpty(),
+      // Game data
+      history: [],
+    );
+  }
+
+  factory Game.createNew({
+    GameSettings? gameSettings,
+    GlobalSettings? globalSettings,
+  }) {
+    final GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
+    final GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
+
+    return Game(
+      // Settings
+      gameSettings: newGameSettings,
+      globalSettings: newGlobalSettings,
+      // State
+      isRunning: true,
+      // Base data
+      move: Move.createEmpty(),
+      // Game data
+      history: [],
+    );
+  }
+
+  bool get canBeResumed => isStarted && !isFinished;
+
+  void dump() {
+    printlog('');
+    printlog('## Current game dump:');
+    printlog('');
+    printlog('$Game:');
+    printlog('  Settings');
+    gameSettings.dump();
+    globalSettings.dump();
+    printlog('  State');
+    printlog('    isRunning: $isRunning');
+    printlog('    isStarted: $isStarted');
+    printlog('    isFinished: $isFinished');
+    printlog('    animationInProgress: $animationInProgress');
+    printlog('  Base data');
+    printlog('    move: $move');
+    printlog('  Game data');
+    printlog('    history: $history');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Game(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      // Settings
+      'gameSettings': gameSettings.toJson(),
+      'globalSettings': globalSettings.toJson(),
+      // State
+      'isRunning': isRunning,
+      'isStarted': isStarted,
+      'isFinished': isFinished,
+      'animationInProgress': animationInProgress,
+      // Base data
+      'move': move,
+      // Game data
+      'history': history,
+    };
+  }
+}
diff --git a/lib/models/move.dart b/lib/models/game/move.dart
similarity index 84%
rename from lib/models/move.dart
rename to lib/models/game/move.dart
index 0d47b0f..a026fbc 100644
--- a/lib/models/move.dart
+++ b/lib/models/game/move.dart
@@ -1,6 +1,7 @@
 import 'package:easy_localization/easy_localization.dart';
-import 'package:twister/models/twister_color.dart';
-import 'package:twister/models/twister_member.dart';
+
+import 'package:twister/models/game/twister_color.dart';
+import 'package:twister/models/game/twister_member.dart';
 
 class Move {
   final TwisterColor? color;
@@ -11,7 +12,7 @@ class Move {
     required this.member,
   });
 
-  factory Move.createNull() {
+  factory Move.createEmpty() {
     return Move(
       color: null,
       member: null,
@@ -34,7 +35,7 @@ class Move {
 
   @override
   String toString() {
-    return 'Move(${toJson()})';
+    return '$Move(${toJson()})';
   }
 
   String toSoundAsset() {
diff --git a/lib/models/twister_color.dart b/lib/models/game/twister_color.dart
similarity index 100%
rename from lib/models/twister_color.dart
rename to lib/models/game/twister_color.dart
diff --git a/lib/models/twister_member.dart b/lib/models/game/twister_member.dart
similarity index 100%
rename from lib/models/twister_member.dart
rename to lib/models/game/twister_member.dart
diff --git a/lib/models/settings/settings_game.dart b/lib/models/settings/settings_game.dart
new file mode 100644
index 0000000..36331ff
--- /dev/null
+++ b/lib/models/settings/settings_game.dart
@@ -0,0 +1,41 @@
+import 'package:twister/config/default_game_settings.dart';
+import 'package:twister/utils/tools.dart';
+
+class GameSettings {
+  final String timerValue;
+
+  GameSettings({
+    required this.timerValue,
+  });
+
+  static String getTimerValueFromUnsafe(String timerValue) {
+    if (DefaultGameSettings.allowedTimerValues.contains(timerValue)) {
+      return timerValue;
+    }
+
+    return DefaultGameSettings.defaultTimerValue;
+  }
+
+  factory GameSettings.createDefault() {
+    return GameSettings(
+      timerValue: DefaultGameSettings.defaultTimerValue,
+    );
+  }
+
+  void dump() {
+    printlog('$GameSettings:');
+    printlog('  ${DefaultGameSettings.parameterCodeTimerValue}: $timerValue');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GameSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeTimerValue: timerValue,
+    };
+  }
+}
diff --git a/lib/models/settings/settings_global.dart b/lib/models/settings/settings_global.dart
new file mode 100644
index 0000000..8805c92
--- /dev/null
+++ b/lib/models/settings/settings_global.dart
@@ -0,0 +1,41 @@
+import 'package:twister/config/default_global_settings.dart';
+import 'package:twister/utils/tools.dart';
+
+class GlobalSettings {
+  String skin;
+
+  GlobalSettings({
+    required this.skin,
+  });
+
+  static String getSkinValueFromUnsafe(String skin) {
+    if (DefaultGlobalSettings.allowedSkinValues.contains(skin)) {
+      return skin;
+    }
+
+    return DefaultGlobalSettings.defaultSkinValue;
+  }
+
+  factory GlobalSettings.createDefault() {
+    return GlobalSettings(
+      skin: DefaultGlobalSettings.defaultSkinValue,
+    );
+  }
+
+  void dump() {
+    printlog('$GlobalSettings:');
+    printlog('  ${DefaultGlobalSettings.parameterCodeSkin}: $skin');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GlobalSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGlobalSettings.parameterCodeSkin: skin,
+    };
+  }
+}
diff --git a/lib/ui/game/game_end.dart b/lib/ui/game/game_end.dart
new file mode 100644
index 0000000..ea2b71b
--- /dev/null
+++ b/lib/ui/game/game_end.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+import 'package:twister/models/game/game.dart';
+import 'package:twister/ui/widgets/actions/button_game_quit.dart';
+
+class GameEndWidget extends StatelessWidget {
+  const GameEndWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        const Image decorationImage = Image(
+          image: AssetImage('assets/ui/game_end.png'),
+          fit: BoxFit.fill,
+        );
+
+        return Container(
+          margin: const EdgeInsets.all(2),
+          padding: const EdgeInsets.all(2),
+          child: Table(
+            defaultColumnWidth: const IntrinsicColumnWidth(),
+            children: [
+              TableRow(
+                children: [
+                  const Column(
+                    children: [decorationImage],
+                  ),
+                  Column(
+                    children: [
+                      currentGame.animationInProgress == true
+                          ? decorationImage
+                          : const QuitGameButton()
+                    ],
+                  ),
+                  const Column(
+                    children: [decorationImage],
+                  ),
+                ],
+              ),
+            ],
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/app_titles.dart b/lib/ui/helpers/app_titles.dart
similarity index 52%
rename from lib/ui/widgets/app_titles.dart
rename to lib/ui/helpers/app_titles.dart
index 9354124..b98107b 100644
--- a/lib/ui/widgets/app_titles.dart
+++ b/lib/ui/helpers/app_titles.dart
@@ -1,8 +1,8 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 
-class AppTitle extends StatelessWidget {
-  const AppTitle({super.key, required this.text});
+class AppHeader extends StatelessWidget {
+  const AppHeader({super.key, required this.text});
 
   final String text;
 
@@ -11,37 +11,22 @@ class AppTitle extends StatelessWidget {
     return Text(
       tr(text),
       textAlign: TextAlign.start,
-      style: Theme.of(context).textTheme.headlineLarge!.apply(fontWeightDelta: 2),
+      style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
     );
   }
 }
 
-class AppTitle1 extends StatelessWidget {
-  const AppTitle1({super.key, required this.text});
+class AppTitle extends StatelessWidget {
+  const AppTitle({super.key, required this.text});
 
   final String text;
 
   @override
   Widget build(BuildContext context) {
     return Text(
-      text,
+      tr(text),
       textAlign: TextAlign.start,
       style: Theme.of(context).textTheme.titleLarge!.apply(fontWeightDelta: 2),
     );
   }
 }
-
-class AppTitle2 extends StatelessWidget {
-  const AppTitle2({super.key, required this.text});
-
-  final String text;
-
-  @override
-  Widget build(BuildContext context) {
-    return Text(
-      text,
-      textAlign: TextAlign.start,
-      style: Theme.of(context).textTheme.titleMedium!.apply(fontWeightDelta: 2),
-    );
-  }
-}
diff --git a/lib/ui/helpers/outlined_text_widget.dart b/lib/ui/helpers/outlined_text_widget.dart
new file mode 100644
index 0000000..dedfb1b
--- /dev/null
+++ b/lib/ui/helpers/outlined_text_widget.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/material.dart';
+
+import 'package:twister/utils/color_extensions.dart';
+
+class OutlinedText extends StatelessWidget {
+  const OutlinedText({
+    super.key,
+    required this.text,
+    required this.fontSize,
+    required this.textColor,
+    this.outlineColor,
+  });
+
+  final String text;
+  final double fontSize;
+  final Color textColor;
+  final Color? outlineColor;
+
+  @override
+  Widget build(BuildContext context) {
+    final double delta = fontSize / 30;
+
+    return Text(
+      text,
+      style: TextStyle(
+        inherit: true,
+        fontSize: fontSize,
+        fontWeight: FontWeight.w600,
+        color: textColor,
+        shadows: [
+          Shadow(
+            offset: Offset(-delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(-delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/layouts/game_layout.dart b/lib/ui/layouts/game_layout.dart
new file mode 100644
index 0000000..0c6cf47
--- /dev/null
+++ b/lib/ui/layouts/game_layout.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+import 'package:twister/models/game/game.dart';
+import 'package:twister/ui/game/game_end.dart';
+import 'package:twister/ui/widgets/game/game_board.dart';
+
+class GameLayout extends StatelessWidget {
+  const GameLayout({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return Container(
+          alignment: AlignmentDirectional.topCenter,
+          padding: const EdgeInsets.all(4),
+          child: Column(
+            mainAxisAlignment: MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              const GameBoardWidget(),
+              const Expanded(child: SizedBox.shrink()),
+              currentGame.isFinished ? const GameEndWidget() : const SizedBox.shrink(),
+            ],
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/layouts/parameters_layout.dart b/lib/ui/layouts/parameters_layout.dart
new file mode 100644
index 0000000..7ccf9b8
--- /dev/null
+++ b/lib/ui/layouts/parameters_layout.dart
@@ -0,0 +1,154 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/config/default_game_settings.dart';
+import 'package:twister/config/default_global_settings.dart';
+import 'package:twister/cubit/settings_game_cubit.dart';
+import 'package:twister/cubit/settings_global_cubit.dart';
+import 'package:twister/ui/parameters/parameter_image.dart';
+import 'package:twister/ui/parameters/parameter_painter.dart';
+import 'package:twister/ui/widgets/actions/button_delete_saved_game.dart';
+import 'package:twister/ui/widgets/actions/button_game_start_new.dart';
+import 'package:twister/ui/widgets/actions/button_resume_saved_game.dart';
+
+class ParametersLayout extends StatelessWidget {
+  const ParametersLayout({super.key, required this.canResume});
+
+  final bool canResume;
+
+  final double separatorHeight = 8.0;
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> lines = [];
+
+    // Game settings
+    for (String code in DefaultGameSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: false,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    lines.add(SizedBox(height: separatorHeight));
+
+    if (canResume == false) {
+      // Start new game
+      lines.add(const Expanded(
+        child: StartNewGameButton(),
+      ));
+    } else {
+      // Resume game
+      lines.add(const Expanded(
+        child: ResumeSavedGameButton(),
+      ));
+      // Delete saved game
+      lines.add(SizedBox.square(
+        dimension: MediaQuery.of(context).size.width / 4,
+        child: const DeleteSavedGameButton(),
+      ));
+    }
+
+    lines.add(SizedBox(height: separatorHeight));
+
+    // Global settings
+    for (String code in DefaultGlobalSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: true,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    return Column(
+      children: lines,
+    );
+  }
+
+  List<Widget> buildParametersLine({
+    required String code,
+    required bool isGlobal,
+  }) {
+    final List<Widget> parameterButtons = [];
+
+    final List<String> availableValues = isGlobal
+        ? DefaultGlobalSettings.getAvailableValues(code)
+        : DefaultGameSettings.getAvailableValues(code);
+
+    if (availableValues.length <= 1) {
+      return [];
+    }
+
+    for (String value in availableValues) {
+      final Widget parameterButton = BlocBuilder<GameSettingsCubit, GameSettingsState>(
+        builder: (BuildContext context, GameSettingsState gameSettingsState) {
+          return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+            builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+              final GameSettingsCubit gameSettingsCubit =
+                  BlocProvider.of<GameSettingsCubit>(context);
+              final GlobalSettingsCubit globalSettingsCubit =
+                  BlocProvider.of<GlobalSettingsCubit>(context);
+
+              final String currentValue = isGlobal
+                  ? globalSettingsCubit.getParameterValue(code)
+                  : gameSettingsCubit.getParameterValue(code);
+
+              final bool isActive = (value == currentValue);
+
+              final double displayWidth = MediaQuery.of(context).size.width;
+              final double itemWidth = displayWidth / availableValues.length - 26;
+
+              final bool displayedWithAssets =
+                  DefaultGlobalSettings.displayedWithAssets.contains(code) ||
+                      DefaultGameSettings.displayedWithAssets.contains(code);
+
+              return TextButton(
+                child: Container(
+                  child: displayedWithAssets
+                      ? SizedBox.square(
+                          dimension: itemWidth,
+                          child: ParameterImage(
+                            code: code,
+                            value: value,
+                            isSelected: isActive,
+                          ),
+                        )
+                      : CustomPaint(
+                          size: Size(itemWidth, itemWidth),
+                          willChange: false,
+                          painter: ParameterPainter(
+                            code: code,
+                            value: value,
+                            isSelected: isActive,
+                            gameSettings: gameSettingsState.settings,
+                            globalSettings: globalSettingsState.settings,
+                          ),
+                          isComplex: true,
+                        ),
+                ),
+                onPressed: () {
+                  isGlobal
+                      ? globalSettingsCubit.setParameterValue(code, value)
+                      : gameSettingsCubit.setParameterValue(code, value);
+                },
+              );
+            },
+          );
+        },
+      );
+
+      parameterButtons.add(parameterButton);
+    }
+
+    return parameterButtons;
+  }
+}
diff --git a/lib/ui/parameters/parameter_image.dart b/lib/ui/parameters/parameter_image.dart
new file mode 100644
index 0000000..fc4b576
--- /dev/null
+++ b/lib/ui/parameters/parameter_image.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+
+class ParameterImage extends StatelessWidget {
+  const ParameterImage({
+    super.key,
+    required this.code,
+    required this.value,
+    required this.isSelected,
+  });
+
+  final String code;
+  final String value;
+  final bool isSelected;
+
+  static const Color buttonBackgroundColor = Colors.white;
+  static const Color buttonBorderColorActive = Colors.blue;
+  static const Color buttonBorderColorInactive = Colors.white;
+  static const double buttonBorderWidth = 8.0;
+  static const double buttonBorderRadius = 8.0;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      decoration: BoxDecoration(
+        color: buttonBackgroundColor,
+        borderRadius: BorderRadius.circular(buttonBorderRadius),
+        border: Border.all(
+          color: isSelected ? buttonBorderColorActive : buttonBorderColorInactive,
+          width: buttonBorderWidth,
+        ),
+      ),
+      child: Image(
+        image: AssetImage('assets/ui/${code}_$value.png'),
+        fit: BoxFit.fill,
+      ),
+    );
+  }
+}
diff --git a/lib/ui/parameters/parameter_painter.dart b/lib/ui/parameters/parameter_painter.dart
new file mode 100644
index 0000000..774c21d
--- /dev/null
+++ b/lib/ui/parameters/parameter_painter.dart
@@ -0,0 +1,90 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+import 'package:twister/models/settings/settings_game.dart';
+import 'package:twister/models/settings/settings_global.dart';
+import 'package:twister/utils/tools.dart';
+
+class ParameterPainter extends CustomPainter {
+  const ParameterPainter({
+    required this.code,
+    required this.value,
+    required this.isSelected,
+    required this.gameSettings,
+    required this.globalSettings,
+  });
+
+  final String code;
+  final String value;
+  final bool isSelected;
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    // force square
+    final double canvasSize = min(size.width, size.height);
+
+    const Color borderColorEnabled = Colors.blue;
+    const Color borderColorDisabled = Colors.white;
+
+    // "enabled/disabled" border
+    final paint = Paint();
+    paint.style = PaintingStyle.stroke;
+    paint.color = isSelected ? borderColorEnabled : borderColorDisabled;
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 10;
+    canvas.drawRect(
+        Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint);
+
+    // content
+    switch (code) {
+      default:
+        printlog('Unknown parameter: $code/$value');
+        paintUnknownParameterItem(value, canvas, canvasSize);
+    }
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) {
+    return false;
+  }
+
+  // "unknown" parameter -> simple block with text
+  void paintUnknownParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3;
+
+    paint.color = Colors.grey;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    final textSpan = TextSpan(
+      text: '?\n$value',
+      style: const TextStyle(
+        color: Colors.black,
+        fontSize: 18,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+}
diff --git a/lib/ui/screens/home.dart b/lib/ui/screens/home.dart
deleted file mode 100644
index f9adc5a..0000000
--- a/lib/ui/screens/home.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:twister/ui/widgets/game.dart';
-import 'package:unicons/unicons.dart';
-
-class ScreenHome extends StatelessWidget {
-  const ScreenHome({super.key});
-
-  static Icon navBarIcon = const Icon(UniconsLine.home);
-  static String navBarText = 'bottom_nav_game';
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      child: ListView(
-        padding: const EdgeInsets.symmetric(horizontal: 4),
-        physics: const BouncingScrollPhysics(),
-        children: const <Widget>[
-          SizedBox(height: 8),
-          Game(),
-          SizedBox(height: 36),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/page_about.dart b/lib/ui/screens/page_about.dart
new file mode 100644
index 0000000..65c1e5d
--- /dev/null
+++ b/lib/ui/screens/page_about.dart
@@ -0,0 +1,41 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+
+import 'package:twister/ui/helpers/app_titles.dart';
+
+class PageAbout extends StatelessWidget {
+  const PageAbout({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.max,
+        children: <Widget>[
+          const SizedBox(height: 8),
+          const AppTitle(text: 'about_title'),
+          const Text('about_content').tr(),
+          FutureBuilder<PackageInfo>(
+            future: PackageInfo.fromPlatform(),
+            builder: (context, snapshot) {
+              switch (snapshot.connectionState) {
+                case ConnectionState.done:
+                  return const Text('about_version').tr(
+                    namedArgs: {
+                      'version': snapshot.data!.version,
+                    },
+                  );
+                default:
+                  return const SizedBox();
+              }
+            },
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
new file mode 100644
index 0000000..6ad44e4
--- /dev/null
+++ b/lib/ui/screens/page_game.dart
@@ -0,0 +1,24 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+import 'package:twister/models/game/game.dart';
+import 'package:twister/ui/layouts/game_layout.dart';
+import 'package:twister/ui/layouts/parameters_layout.dart';
+
+class PageGame extends StatelessWidget {
+  const PageGame({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return currentGame.isRunning
+            ? const GameLayout()
+            : ParametersLayout(canResume: currentGame.canBeResumed);
+      },
+    );
+  }
+}
diff --git a/lib/ui/screens/page_settings.dart b/lib/ui/screens/page_settings.dart
new file mode 100644
index 0000000..aa5bcc7
--- /dev/null
+++ b/lib/ui/screens/page_settings.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+
+import 'package:twister/ui/helpers/app_titles.dart';
+import 'package:twister/ui/settings/settings_form.dart';
+
+class PageSettings extends StatelessWidget {
+  const PageSettings({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return const Padding(
+      padding: EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.max,
+        children: <Widget>[
+          SizedBox(height: 8),
+          AppTitle(text: 'settings_title'),
+          SizedBox(height: 8),
+          SettingsForm(),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/screens/settings.dart b/lib/ui/screens/settings.dart
deleted file mode 100644
index b0ecbd5..0000000
--- a/lib/ui/screens/settings.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-
-import 'package:twister/ui/widgets/app_titles.dart';
-import 'package:twister/ui/widgets/settings_form.dart';
-import 'package:unicons/unicons.dart';
-
-class ScreenSettings extends StatelessWidget {
-  const ScreenSettings({super.key});
-
-  static Icon navBarIcon = const Icon(UniconsLine.setting);
-  static String navBarText = 'bottom_nav_settings';
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      child: ListView(
-        padding: const EdgeInsets.symmetric(horizontal: 4),
-        physics: const BouncingScrollPhysics(),
-        children: <Widget>[
-          const SizedBox(height: 8),
-          AppTitle1(text: tr('settings_title')),
-          const SettingsForm(),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/settings/settings_form.dart b/lib/ui/settings/settings_form.dart
new file mode 100644
index 0000000..e294590
--- /dev/null
+++ b/lib/ui/settings/settings_form.dart
@@ -0,0 +1,63 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:twister/ui/settings/theme_card.dart';
+
+class SettingsForm extends StatefulWidget {
+  const SettingsForm({super.key});
+
+  @override
+  State<SettingsForm> createState() => _SettingsFormState();
+}
+
+class _SettingsFormState extends State<SettingsForm> {
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        // Light/dark theme
+        Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: <Widget>[
+            const Text('settings_label_theme').tr(),
+            const Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                ThemeCard(
+                  mode: ThemeMode.system,
+                  icon: UniconsLine.cog,
+                ),
+                ThemeCard(
+                  mode: ThemeMode.light,
+                  icon: UniconsLine.sun,
+                ),
+                ThemeCard(
+                  mode: ThemeMode.dark,
+                  icon: UniconsLine.moon,
+                )
+              ],
+            ),
+          ],
+        ),
+
+        const SizedBox(height: 16),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/settings/theme_card.dart b/lib/ui/settings/theme_card.dart
new file mode 100644
index 0000000..15f343d
--- /dev/null
+++ b/lib/ui/settings/theme_card.dart
@@ -0,0 +1,47 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/theme_cubit.dart';
+
+class ThemeCard extends StatelessWidget {
+  const ThemeCard({
+    super.key,
+    required this.mode,
+    required this.icon,
+  });
+
+  final IconData icon;
+  final ThemeMode mode;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<ThemeCubit, ThemeModeState>(
+      builder: (BuildContext context, ThemeModeState state) {
+        return Card(
+          elevation: 2,
+          shadowColor: Theme.of(context).colorScheme.shadow,
+          color: state.themeMode == mode
+              ? Theme.of(context).colorScheme.primary
+              : Theme.of(context).colorScheme.surface,
+          shape: const RoundedRectangleBorder(
+            borderRadius: BorderRadius.all(Radius.circular(12)),
+          ),
+          margin: const EdgeInsets.all(5),
+          child: InkWell(
+            onTap: () => BlocProvider.of<ThemeCubit>(context).getTheme(
+              ThemeModeState(themeMode: mode),
+            ),
+            borderRadius: const BorderRadius.all(Radius.circular(12)),
+            child: Icon(
+              icon,
+              size: 32,
+              color: state.themeMode != mode
+                  ? Theme.of(context).colorScheme.primary
+                  : Colors.white,
+            ),
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index ecc81e1..3238f96 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,40 +1,34 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:twister/cubit/bottom_nav_cubit.dart';
-import 'package:twister/ui/screens/home.dart';
-import 'package:twister/ui/screens/settings.dart';
-import 'package:twister/ui/widgets/app_bar.dart';
-import 'package:twister/ui/widgets/bottom_nav_bar.dart';
+import 'package:twister/config/menu.dart';
+import 'package:twister/cubit/nav_cubit.dart';
+import 'package:twister/ui/widgets/global_app_bar.dart';
 
-class SkeletonScreen extends StatefulWidget {
+class SkeletonScreen extends StatelessWidget {
   const SkeletonScreen({super.key});
 
-  @override
-  State<SkeletonScreen> createState() => _SkeletonScreenState();
-}
-
-class _SkeletonScreenState extends State<SkeletonScreen> {
   @override
   Widget build(BuildContext context) {
-    List<Widget> pageNavigation = <Widget>[
-      const ScreenHome(),
-      const ScreenSettings(),
-    ];
-
     return Scaffold(
-      appBar: const StandardAppBar(),
+      appBar: const GlobalAppBar(),
       extendBodyBehindAppBar: false,
-      body: BlocBuilder<BottomNavCubit, int>(
-        builder: (BuildContext context, int state) {
-          return AnimatedSwitcher(
-            duration: const Duration(milliseconds: 300),
-            child: pageNavigation.elementAt(state),
-          );
-        },
+      body: Material(
+        color: Theme.of(context).colorScheme.surface,
+        child: BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            return Padding(
+              padding: const EdgeInsets.only(
+                top: 8,
+                left: 2,
+                right: 2,
+              ),
+              child: Menu.getPageWidget(pageIndex),
+            );
+          },
+        ),
       ),
-      backgroundColor: Theme.of(context).colorScheme.background,
-      bottomNavigationBar: const BottomNavBar(),
+      backgroundColor: Theme.of(context).colorScheme.surface,
     );
   }
 }
diff --git a/lib/ui/widgets/actions/button_delete_saved_game.dart b/lib/ui/widgets/actions/button_delete_saved_game.dart
new file mode 100644
index 0000000..4036c28
--- /dev/null
+++ b/lib/ui/widgets/actions/button_delete_saved_game.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+
+class DeleteSavedGameButton extends StatelessWidget {
+  const DeleteSavedGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return TextButton(
+      child: const Image(
+        image: AssetImage('assets/ui/button_delete_saved_game.png'),
+        fit: BoxFit.fill,
+      ),
+      onPressed: () {
+        BlocProvider.of<GameCubit>(context).deleteSavedGame();
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/actions/button_game_quit.dart b/lib/ui/widgets/actions/button_game_quit.dart
new file mode 100644
index 0000000..58cde3e
--- /dev/null
+++ b/lib/ui/widgets/actions/button_game_quit.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+
+class QuitGameButton extends StatelessWidget {
+  const QuitGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return TextButton(
+      child: const Image(
+        image: AssetImage('assets/ui/button_back.png'),
+        fit: BoxFit.fill,
+      ),
+      onPressed: () {
+        BlocProvider.of<GameCubit>(context).quitGame();
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/actions/button_game_start_new.dart b/lib/ui/widgets/actions/button_game_start_new.dart
new file mode 100644
index 0000000..fd246a8
--- /dev/null
+++ b/lib/ui/widgets/actions/button_game_start_new.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+import 'package:twister/cubit/settings_game_cubit.dart';
+import 'package:twister/cubit/settings_global_cubit.dart';
+
+class StartNewGameButton extends StatelessWidget {
+  const StartNewGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameSettingsCubit, GameSettingsState>(
+      builder: (BuildContext context, GameSettingsState gameSettingsState) {
+        return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+          builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+            return TextButton(
+              child: const Image(
+                image: AssetImage('assets/ui/button_start.png'),
+                fit: BoxFit.fill,
+              ),
+              onPressed: () {
+                BlocProvider.of<GameCubit>(context).startNewGame(
+                  gameSettings: gameSettingsState.settings,
+                  globalSettings: globalSettingsState.settings,
+                );
+              },
+            );
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/actions/button_resume_saved_game.dart b/lib/ui/widgets/actions/button_resume_saved_game.dart
new file mode 100644
index 0000000..45dc8ff
--- /dev/null
+++ b/lib/ui/widgets/actions/button_resume_saved_game.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+
+class ResumeSavedGameButton extends StatelessWidget {
+  const ResumeSavedGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return TextButton(
+      child: const Image(
+        image: AssetImage('assets/ui/button_resume_game.png'),
+        fit: BoxFit.fill,
+      ),
+      onPressed: () {
+        BlocProvider.of<GameCubit>(context).resumeSavedGame();
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart
deleted file mode 100644
index b777c21..0000000
--- a/lib/ui/widgets/app_bar.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:twister/ui/widgets/app_titles.dart';
-
-class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
-  const StandardAppBar({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return AppBar(
-      title: const AppTitle(text: 'app_name'),
-      actions: const [],
-    );
-  }
-
-  @override
-  Size get preferredSize => const Size.fromHeight(50);
-}
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
deleted file mode 100644
index 24e9a83..0000000
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ /dev/null
@@ -1,48 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:twister/cubit/bottom_nav_cubit.dart';
-import 'package:twister/ui/screens/settings.dart';
-import 'package:twister/ui/screens/home.dart';
-
-class BottomNavBar extends StatelessWidget {
-  const BottomNavBar({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: const EdgeInsets.only(top: 1, right: 4, left: 4),
-      elevation: 4,
-      shadowColor: Theme.of(context).colorScheme.shadow,
-      color: Theme.of(context).colorScheme.surfaceVariant,
-      shape: const RoundedRectangleBorder(
-        borderRadius: BorderRadius.only(
-          topLeft: Radius.circular(16),
-          topRight: Radius.circular(16),
-        ),
-      ),
-      child: BlocBuilder<BottomNavCubit, int>(builder: (BuildContext context, int state) {
-        return BottomNavigationBar(
-          currentIndex: state,
-          onTap: (int index) => context.read<BottomNavCubit>().updateIndex(index),
-          type: BottomNavigationBarType.fixed,
-          elevation: 0,
-          backgroundColor: Colors.transparent,
-          selectedItemColor: Theme.of(context).colorScheme.primary,
-          unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
-          items: <BottomNavigationBarItem>[
-            BottomNavigationBarItem(
-              icon: ScreenHome.navBarIcon,
-              label: tr(ScreenHome.navBarText),
-            ),
-            BottomNavigationBarItem(
-              icon: ScreenSettings.navBarIcon,
-              label: tr(ScreenSettings.navBarText),
-            ),
-          ],
-        );
-      }),
-    );
-  }
-}
diff --git a/lib/ui/widgets/game.dart b/lib/ui/widgets/game.dart
deleted file mode 100644
index fadc925..0000000
--- a/lib/ui/widgets/game.dart
+++ /dev/null
@@ -1,159 +0,0 @@
-import 'dart:async';
-import 'dart:math';
-
-import 'package:audioplayers/audioplayers.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:twister/cubit/game_cubit.dart';
-import 'package:twister/models/move.dart';
-import 'package:twister/models/twister_color.dart';
-import 'package:twister/models/twister_member.dart';
-import 'package:twister/ui/widgets/show_move.dart';
-
-class Game extends StatefulWidget {
-  const Game({super.key});
-
-  @override
-  State<Game> createState() => _GameState();
-}
-
-class _GameState extends State<Game> {
-  final player = AudioPlayer();
-  bool shuffling = false;
-  Move? shuffledMove;
-
-  void animate() {
-    const interval = Duration(milliseconds: 200);
-    int iterationsLeft = 10;
-
-    shuffling = true;
-    shuffledMove = null;
-
-    setState(() {});
-    Timer.periodic(
-      interval,
-      (Timer timer) {
-        if (iterationsLeft > 1) {
-          shuffledMove = Move.pickRandom();
-        }
-
-        if (iterationsLeft == 1) {
-          shuffledMove = null;
-        }
-
-        if (iterationsLeft == 0) {
-          shuffledMove = null;
-          pickNewMove();
-
-          timer.cancel();
-          shuffling = false;
-        }
-
-        setState(() {});
-        iterationsLeft--;
-      },
-    );
-  }
-
-  void pickNewMove() {
-    Move newMove = Move.pickRandom();
-
-    BlocProvider.of<GameCubit>(context).setValues(
-      move: newMove,
-    );
-
-    player.play(AssetSource(newMove.toSoundAsset()));
-  }
-
-  Widget buildCurrentStateWidget(List<Move>? history) {
-    Map<String, TwisterColor?> currentState = {};
-
-    history?.forEach((move) {
-      currentState[move.member.toString()] = move.color;
-    });
-
-    TwisterMember leftHand = TwisterMember(value: TwisterAllowedMembers.leftHand);
-    TwisterMember rightHand = TwisterMember(value: TwisterAllowedMembers.rightHand);
-    TwisterMember leftFoot = TwisterMember(value: TwisterAllowedMembers.leftFoot);
-    TwisterMember rightFoot = TwisterMember(value: TwisterAllowedMembers.rightFoot);
-
-    Move leftHandMove = Move.createFrom(
-      member: leftHand,
-      color: currentState[leftHand.toString()],
-    );
-    Move rightHandMove = Move.createFrom(
-      member: rightHand,
-      color: currentState[rightHand.toString()],
-    );
-    Move leftFootMove = Move.createFrom(
-      member: leftFoot,
-      color: currentState[leftFoot.toString()],
-    );
-    Move rightFootMove = Move.createFrom(
-      member: rightFoot,
-      color: currentState[rightFoot.toString()],
-    );
-
-    return Padding(
-      padding: const EdgeInsets.all(30),
-      child: Table(
-        children: [
-          TableRow(
-            children: [
-              Padding(
-                padding: const EdgeInsets.all(10),
-                child: ShowMove(move: leftHandMove),
-              ),
-              Padding(
-                padding: const EdgeInsets.all(10),
-                child: ShowMove(move: rightHandMove),
-              ),
-            ],
-          ),
-          TableRow(
-            children: [
-              Padding(
-                padding: const EdgeInsets.all(10),
-                child: ShowMove(move: leftFootMove),
-              ),
-              Padding(
-                padding: const EdgeInsets.all(10),
-                child: ShowMove(move: rightFootMove),
-              ),
-            ],
-          )
-        ],
-      ),
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        return Column(
-          children: [
-            GestureDetector(
-              child: shuffling
-                  ? Transform.rotate(
-                      angle: 2 * pi * Random().nextDouble(),
-                      child: ShowMove(move: shuffledMove ?? Move.createNull()),
-                    )
-                  : ShowMove(move: gameState.move ?? Move.createNull()),
-              onTap: () {
-                animate();
-              },
-            ),
-            GestureDetector(
-              child: buildCurrentStateWidget(gameState.history),
-              onTap: () {
-                BlocProvider.of<GameCubit>(context).deleteHistory();
-              },
-            ),
-          ],
-        );
-      },
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/game_board.dart b/lib/ui/widgets/game/game_board.dart
new file mode 100644
index 0000000..0fcdef2
--- /dev/null
+++ b/lib/ui/widgets/game/game_board.dart
@@ -0,0 +1,20 @@
+import 'package:flutter/material.dart';
+
+import 'package:twister/ui/widgets/game/game_current_move.dart';
+import 'package:twister/ui/widgets/game/game_moves_history.dart';
+
+class GameBoardWidget extends StatelessWidget {
+  const GameBoardWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return const Column(
+      mainAxisAlignment: MainAxisAlignment.center,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: [
+        GameCurrentMoveWidget(),
+        GameMovesHistoryWidget(),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_current_move.dart b/lib/ui/widgets/game/game_current_move.dart
new file mode 100644
index 0000000..ae0c7c4
--- /dev/null
+++ b/lib/ui/widgets/game/game_current_move.dart
@@ -0,0 +1,80 @@
+import 'dart:async';
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+import 'package:twister/models/game/move.dart';
+import 'package:twister/ui/widgets/game/move.dart';
+
+class GameCurrentMoveWidget extends StatefulWidget {
+  const GameCurrentMoveWidget({super.key});
+
+  @override
+  State<GameCurrentMoveWidget> createState() => _GameCurrentMoveWidgetState();
+}
+
+class _GameCurrentMoveWidgetState extends State<GameCurrentMoveWidget> {
+  Move? shuffledMove;
+
+  void animate() {
+    final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+    if (gameCubit.state.currentGame.animationInProgress == true) {
+      return;
+    }
+
+    const interval = Duration(milliseconds: 200);
+    int iterationsLeft = 10;
+
+    gameCubit.setAnimationIsRunning(true);
+    shuffledMove = null;
+
+    setState(() {});
+    Timer.periodic(
+      interval,
+      (Timer timer) {
+        // animate with random move
+        if (iterationsLeft > 1) {
+          shuffledMove = Move.pickRandom();
+        }
+
+        // last iteration => clear
+        if (iterationsLeft == 1) {
+          shuffledMove = null;
+        }
+
+        // end: pick and keep random move
+        if (iterationsLeft == 0) {
+          shuffledMove = null;
+          timer.cancel();
+
+          gameCubit.pickNewMove();
+          gameCubit.setAnimationIsRunning(false);
+        }
+
+        setState(() {});
+        iterationsLeft--;
+      },
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        return GestureDetector(
+          child: gameState.currentGame.animationInProgress
+              ? Transform.rotate(
+                  angle: 2 * pi * Random().nextDouble(),
+                  child: MoveWidget(move: shuffledMove ?? Move.createEmpty()),
+                )
+              : MoveWidget(move: gameState.currentGame.move ?? Move.createEmpty()),
+          onTap: () {
+            animate();
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_moves_history.dart b/lib/ui/widgets/game/game_moves_history.dart
new file mode 100644
index 0000000..67eb3e7
--- /dev/null
+++ b/lib/ui/widgets/game/game_moves_history.dart
@@ -0,0 +1,88 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/cubit/game_cubit.dart';
+import 'package:twister/models/game/move.dart';
+import 'package:twister/models/game/twister_color.dart';
+import 'package:twister/models/game/twister_member.dart';
+import 'package:twister/ui/widgets/game/move.dart';
+
+class GameMovesHistoryWidget extends StatelessWidget {
+  const GameMovesHistoryWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        return GestureDetector(
+          child: currentGlobalState(gameState.currentGame.history),
+          onTap: () {
+            BlocProvider.of<GameCubit>(context).deleteHistory();
+          },
+        );
+      },
+    );
+  }
+
+  Widget currentGlobalState(List<Move>? history) {
+    Map<String, TwisterColor?> currentState = {};
+
+    history?.forEach((move) {
+      currentState[move.member.toString()] = move.color;
+    });
+
+    TwisterMember leftHand = TwisterMember(value: TwisterAllowedMembers.leftHand);
+    TwisterMember rightHand = TwisterMember(value: TwisterAllowedMembers.rightHand);
+    TwisterMember leftFoot = TwisterMember(value: TwisterAllowedMembers.leftFoot);
+    TwisterMember rightFoot = TwisterMember(value: TwisterAllowedMembers.rightFoot);
+
+    Move leftHandMove = Move.createFrom(
+      member: leftHand,
+      color: currentState[leftHand.toString()],
+    );
+    Move rightHandMove = Move.createFrom(
+      member: rightHand,
+      color: currentState[rightHand.toString()],
+    );
+    Move leftFootMove = Move.createFrom(
+      member: leftFoot,
+      color: currentState[leftFoot.toString()],
+    );
+    Move rightFootMove = Move.createFrom(
+      member: rightFoot,
+      color: currentState[rightFoot.toString()],
+    );
+
+    return Padding(
+      padding: const EdgeInsets.all(30),
+      child: Table(
+        children: [
+          TableRow(
+            children: [
+              Padding(
+                padding: const EdgeInsets.all(10),
+                child: MoveWidget(move: leftHandMove),
+              ),
+              Padding(
+                padding: const EdgeInsets.all(10),
+                child: MoveWidget(move: rightHandMove),
+              ),
+            ],
+          ),
+          TableRow(
+            children: [
+              Padding(
+                padding: const EdgeInsets.all(10),
+                child: MoveWidget(move: leftFootMove),
+              ),
+              Padding(
+                padding: const EdgeInsets.all(10),
+                child: MoveWidget(move: rightFootMove),
+              ),
+            ],
+          )
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/show_move.dart b/lib/ui/widgets/game/move.dart
similarity index 54%
rename from lib/ui/widgets/show_move.dart
rename to lib/ui/widgets/game/move.dart
index c40dd3a..48846a9 100644
--- a/lib/ui/widgets/show_move.dart
+++ b/lib/ui/widgets/game/move.dart
@@ -1,14 +1,14 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 
-import 'package:twister/config/colors.dart';
-import 'package:twister/models/move.dart';
-import 'package:twister/models/twister_color.dart';
-import 'package:twister/models/twister_member.dart';
+import 'package:twister/config/color_theme.dart';
+import 'package:twister/models/game/move.dart';
+import 'package:twister/models/game/twister_color.dart';
+import 'package:twister/models/game/twister_member.dart';
 import 'package:twister/utils/color_extensions.dart';
 
-class ShowMove extends StatelessWidget {
-  const ShowMove({super.key, required this.move});
+class MoveWidget extends StatelessWidget {
+  const MoveWidget({super.key, required this.move});
 
   final Move move;
 
@@ -27,12 +27,6 @@ class ShowMove extends StatelessWidget {
     }
   }
 
-  Widget getImageWidget(Move move) {
-    String imageAsset = 'assets/images/${move.member?.toString() ?? 'blank'}.png';
-
-    return Image.asset(imageAsset);
-  }
-
   Widget getTextWidget(Move move) {
     TextStyle style = const TextStyle(
       color: Colors.black,
@@ -54,38 +48,34 @@ class ShowMove extends StatelessWidget {
     }
   }
 
-  Widget buildWidget(Move move, double maxWidth) {
-    Color color = getColor(move);
-
-    double containerSize = maxWidth * 0.8;
-
-    return AnimatedSwitcher(
-      duration: const Duration(milliseconds: 200),
-      transitionBuilder: (Widget child, Animation<double> animation) {
-        return ScaleTransition(scale: animation, child: child);
-      },
-      child: Container(
-        width: containerSize,
-        height: containerSize,
-        decoration: BoxDecoration(
-          color: color,
-          borderRadius: BorderRadius.all(Radius.circular(containerSize)),
-          border: Border.all(
-            color: color.darken(15),
-            width: 15,
-          ),
-        ),
-        child: getImageWidget(move),
-      ),
-    );
-  }
-
   @override
   Widget build(BuildContext context) {
     return LayoutBuilder(
       builder: (context, constraints) {
         final double maxWidth = constraints.maxWidth;
-        return buildWidget(move, maxWidth);
+        Color color = getColor(move);
+
+        double containerSize = maxWidth * 0.8;
+
+        return AnimatedSwitcher(
+          duration: const Duration(milliseconds: 200),
+          transitionBuilder: (Widget child, Animation<double> animation) {
+            return ScaleTransition(scale: animation, child: child);
+          },
+          child: Container(
+            width: containerSize,
+            height: containerSize,
+            decoration: BoxDecoration(
+              color: color,
+              borderRadius: BorderRadius.all(Radius.circular(containerSize)),
+              border: Border.all(
+                color: color.darken(15),
+                width: 15,
+              ),
+            ),
+            child: Image.asset('assets/ui/move-${move.member?.toString() ?? 'blank'}.png'),
+          ),
+        );
       },
     );
   }
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart
new file mode 100644
index 0000000..6b6c07e
--- /dev/null
+++ b/lib/ui/widgets/global_app_bar.dart
@@ -0,0 +1,83 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:twister/config/menu.dart';
+import 'package:twister/cubit/game_cubit.dart';
+import 'package:twister/cubit/nav_cubit.dart';
+import 'package:twister/models/game/game.dart';
+import 'package:twister/ui/helpers/app_titles.dart';
+
+class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
+  const GlobalAppBar({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        return BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            final Game currentGame = gameState.currentGame;
+
+            final List<Widget> menuActions = [];
+
+            if (currentGame.isRunning && !currentGame.isFinished) {
+              menuActions.add(TextButton(
+                child: const Image(
+                  image: AssetImage('assets/ui/button_back.png'),
+                  fit: BoxFit.fill,
+                ),
+                onPressed: () {},
+                onLongPress: () {
+                  BlocProvider.of<GameCubit>(context).quitGame();
+                },
+              ));
+            } else {
+              if (pageIndex == Menu.indexGame) {
+                // go to Settings page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToSettingsPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemSettings.icon,
+                ));
+
+                // go to About page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToAboutPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemAbout.icon,
+                ));
+              } else {
+                // back to Home page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToGamePage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemGame.icon,
+                ));
+              }
+            }
+
+            return AppBar(
+              title: const AppHeader(text: 'app_name'),
+              actions: menuActions,
+            );
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Size get preferredSize => const Size.fromHeight(50);
+}
diff --git a/lib/ui/widgets/settings_form.dart b/lib/ui/widgets/settings_form.dart
deleted file mode 100644
index 81fac9e..0000000
--- a/lib/ui/widgets/settings_form.dart
+++ /dev/null
@@ -1,113 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:unicons/unicons.dart';
-
-import 'package:twister/config/default_settings.dart';
-import 'package:twister/cubit/settings_cubit.dart';
-import 'package:twister/ui/widgets/app_titles.dart';
-import 'package:twister/ui/widgets/theme_card.dart';
-
-class SettingsForm extends StatefulWidget {
-  const SettingsForm({super.key});
-
-  @override
-  State<SettingsForm> createState() => _SettingsFormState();
-}
-
-class _SettingsFormState extends State<SettingsForm> {
-  int timerValue = DefaultSettings.defaultTimerValue;
-
-  List<bool> _selectedTimerValue = [];
-
-  @override
-  void didChangeDependencies() {
-    SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
-
-    timerValue = settings.getTimerValue();
-
-    _selectedTimerValue =
-        DefaultSettings.allowedTimerValues.map((e) => (e == timerValue)).toList();
-
-    super.didChangeDependencies();
-  }
-
-  @override
-  void dispose() {
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    void saveSettings() {
-      BlocProvider.of<SettingsCubit>(context).setValues(
-        timerValue: timerValue,
-      );
-    }
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.start,
-      mainAxisSize: MainAxisSize.max,
-      children: <Widget>[
-        const SizedBox(height: 8),
-
-        // Light/dark theme
-        Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: <Widget>[
-            const Text('settings_label_theme').tr(),
-            const Row(
-              mainAxisAlignment: MainAxisAlignment.end,
-              crossAxisAlignment: CrossAxisAlignment.center,
-              children: [
-                ThemeCard(
-                  mode: ThemeMode.system,
-                  icon: UniconsLine.cog,
-                ),
-                ThemeCard(
-                  mode: ThemeMode.light,
-                  icon: UniconsLine.sun,
-                ),
-                ThemeCard(
-                  mode: ThemeMode.dark,
-                  icon: UniconsLine.moon,
-                )
-              ],
-            ),
-          ],
-        ),
-
-        const SizedBox(height: 16),
-
-        AppTitle2(text: tr('settings_title_game')),
-
-        // Timer value
-        Row(
-          mainAxisAlignment: MainAxisAlignment.end,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            const Text('settings_label_game_timer_value').tr(),
-            ToggleButtons(
-              onPressed: (int index) {
-                setState(() {
-                  timerValue = DefaultSettings.allowedTimerValues[index];
-                  for (int i = 0; i < _selectedTimerValue.length; i++) {
-                    _selectedTimerValue[i] = i == index;
-                  }
-                });
-                saveSettings();
-              },
-              borderRadius: const BorderRadius.all(Radius.circular(8)),
-              constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
-              isSelected: _selectedTimerValue,
-              children:
-                  DefaultSettings.allowedTimerValues.map((e) => Text(e.toString())).toList(),
-            ),
-          ],
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/widgets/theme_card.dart b/lib/ui/widgets/theme_card.dart
deleted file mode 100644
index bd935ab..0000000
--- a/lib/ui/widgets/theme_card.dart
+++ /dev/null
@@ -1,45 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:twister/cubit/theme_cubit.dart';
-
-class ThemeCard extends StatelessWidget {
-  const ThemeCard({
-    super.key,
-    required this.mode,
-    required this.icon,
-  });
-
-  final IconData icon;
-  final ThemeMode mode;
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<ThemeCubit, ThemeModeState>(
-        builder: (BuildContext context, ThemeModeState state) {
-      return Card(
-        elevation: 2,
-        shadowColor: Theme.of(context).colorScheme.shadow,
-        color: state.themeMode == mode
-            ? Theme.of(context).colorScheme.primary
-            : Theme.of(context).colorScheme.surface,
-        shape: const RoundedRectangleBorder(
-          borderRadius: BorderRadius.all(Radius.circular(12)),
-        ),
-        margin: const EdgeInsets.all(5),
-        child: InkWell(
-          onTap: () => BlocProvider.of<ThemeCubit>(context).getTheme(
-            ThemeModeState(themeMode: mode),
-          ),
-          borderRadius: const BorderRadius.all(Radius.circular(12)),
-          child: Icon(
-            icon,
-            size: 32,
-            color:
-                state.themeMode != mode ? Theme.of(context).colorScheme.primary : Colors.white,
-          ),
-        ),
-      );
-    });
-  }
-}
diff --git a/pubspec.lock b/pubspec.lock
index fe15305..fc3ef49 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,10 +5,10 @@ packages:
     dependency: transitive
     description:
       name: args
-      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+      sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.4.2"
+    version: "2.5.0"
   async:
     dependency: transitive
     description:
@@ -21,66 +21,66 @@ packages:
     dependency: "direct main"
     description:
       name: audioplayers
-      sha256: c05c6147124cd63e725e861335a8b4d57300b80e6e92cea7c145c739223bbaef
+      sha256: "752039d6aa752597c98ec212e9759519061759e402e7da59a511f39d43aa07d2"
       url: "https://pub.dev"
     source: hosted
-    version: "5.2.1"
+    version: "6.0.0"
   audioplayers_android:
     dependency: transitive
     description:
       name: audioplayers_android
-      sha256: b00e1a0e11365d88576320ec2d8c192bc21f1afb6c0e5995d1c57ae63156acb5
+      sha256: de576b890befe27175c2f511ba8b742bec83765fa97c3ce4282bba46212f58e4
       url: "https://pub.dev"
     source: hosted
-    version: "4.0.3"
+    version: "5.0.0"
   audioplayers_darwin:
     dependency: transitive
     description:
       name: audioplayers_darwin
-      sha256: "3034e99a6df8d101da0f5082dcca0a2a99db62ab1d4ddb3277bed3f6f81afe08"
+      sha256: e507887f3ff18d8e5a10a668d7bedc28206b12e10b98347797257c6ae1019c3b
       url: "https://pub.dev"
     source: hosted
-    version: "5.0.2"
+    version: "6.0.0"
   audioplayers_linux:
     dependency: transitive
     description:
       name: audioplayers_linux
-      sha256: "60787e73fefc4d2e0b9c02c69885402177e818e4e27ef087074cf27c02246c9e"
+      sha256: "3d3d244c90436115417f170426ce768856d8fe4dfc5ed66a049d2890acfa82f9"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.0"
+    version: "4.0.0"
   audioplayers_platform_interface:
     dependency: transitive
     description:
       name: audioplayers_platform_interface
-      sha256: "365c547f1bb9e77d94dd1687903a668d8f7ac3409e48e6e6a3668a1ac2982adb"
+      sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5"
       url: "https://pub.dev"
     source: hosted
-    version: "6.1.0"
+    version: "7.0.0"
   audioplayers_web:
     dependency: transitive
     description:
       name: audioplayers_web
-      sha256: "22cd0173e54d92bd9b2c80b1204eb1eb159ece87475ab58c9788a70ec43c2a62"
+      sha256: db8fc420dadf80da18e2286c18e746fb4c3b2c5adbf0c963299dde046828886d
       url: "https://pub.dev"
     source: hosted
-    version: "4.1.0"
+    version: "5.0.0"
   audioplayers_windows:
     dependency: transitive
     description:
       name: audioplayers_windows
-      sha256: "9536812c9103563644ada2ef45ae523806b0745f7a78e89d1b5fb1951de90e1a"
+      sha256: "8605762dddba992138d476f6a0c3afd9df30ac5b96039929063eceed416795c2"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.0"
+    version: "4.0.0"
   bloc:
     dependency: transitive
     description:
       name: bloc
-      sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e
+      sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.3"
+    version: "8.1.4"
   characters:
     dependency: transitive
     description:
@@ -117,10 +117,10 @@ packages:
     dependency: "direct main"
     description:
       name: easy_localization
-      sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c
+      sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.5"
+    version: "3.0.7"
   easy_logger:
     dependency: transitive
     description:
@@ -170,18 +170,18 @@ packages:
     dependency: "direct main"
     description:
       name: flutter_bloc
-      sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1"
+      sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.4"
+    version: "8.1.6"
   flutter_lints:
     dependency: "direct dev"
     description:
       name: flutter_lints
-      sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
+      sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "4.0.0"
   flutter_localizations:
     dependency: transitive
     description: flutter
@@ -220,34 +220,26 @@ packages:
     dependency: "direct main"
     description:
       name: hydrated_bloc
-      sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d"
+      sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c
       url: "https://pub.dev"
     source: hosted
-    version: "9.1.4"
+    version: "9.1.5"
   intl:
     dependency: transitive
     description:
       name: intl
-      sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
+      sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
       url: "https://pub.dev"
     source: hosted
-    version: "0.18.1"
-  js:
-    dependency: transitive
-    description:
-      name: js
-      sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
-      url: "https://pub.dev"
-    source: hosted
-    version: "0.6.7"
+    version: "0.19.0"
   lints:
     dependency: transitive
     description:
       name: lints
-      sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
+      sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.0"
+    version: "4.0.0"
   material_color_utilities:
     dependency: transitive
     description:
@@ -260,10 +252,10 @@ packages:
     dependency: transitive
     description:
       name: meta
-      sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
+      sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
       url: "https://pub.dev"
     source: hosted
-    version: "1.11.0"
+    version: "1.12.0"
   nested:
     dependency: transitive
     description:
@@ -272,6 +264,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.0"
+  package_info_plus:
+    dependency: "direct main"
+    description:
+      name: package_info_plus
+      sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
+      url: "https://pub.dev"
+    source: hosted
+    version: "8.0.0"
+  package_info_plus_platform_interface:
+    dependency: transitive
+    description:
+      name: package_info_plus_platform_interface
+      sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.0"
   path:
     dependency: transitive
     description:
@@ -284,26 +292,26 @@ packages:
     dependency: "direct main"
     description:
       name: path_provider
-      sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
+      sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.3"
   path_provider_android:
     dependency: transitive
     description:
       name: path_provider_android
-      sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
+      sha256: "9c96da072b421e98183f9ea7464898428e764bc0ce5567f27ec8693442e72514"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.5"
   path_provider_foundation:
     dependency: transitive
     description:
       name: path_provider_foundation
-      sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
+      sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.2"
+    version: "2.4.0"
   path_provider_linux:
     dependency: transitive
     description:
@@ -332,10 +340,10 @@ packages:
     dependency: transitive
     description:
       name: platform
-      sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
+      sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.4"
+    version: "3.1.5"
   plugin_platform_interface:
     dependency: transitive
     description:
@@ -356,26 +364,26 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences
-      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
+      sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.3"
   shared_preferences_android:
     dependency: transitive
     description:
       name: shared_preferences_android
-      sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
+      sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.1"
+    version: "2.2.3"
   shared_preferences_foundation:
     dependency: transitive
     description:
       name: shared_preferences_foundation
-      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
+      sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.5"
+    version: "2.4.0"
   shared_preferences_linux:
     dependency: transitive
     description:
@@ -473,10 +481,10 @@ packages:
     dependency: transitive
     description:
       name: uuid
-      sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
+      sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
       url: "https://pub.dev"
     source: hosted
-    version: "4.3.3"
+    version: "4.4.0"
   vector_math:
     dependency: transitive
     description:
@@ -489,18 +497,18 @@ packages:
     dependency: transitive
     description:
       name: web
-      sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad"
+      sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.0"
+    version: "0.5.1"
   win32:
     dependency: transitive
     description:
       name: win32
-      sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
+      sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
       url: "https://pub.dev"
     source: hosted
-    version: "5.2.0"
+    version: "5.5.1"
   xdg_directories:
     dependency: transitive
     description:
@@ -510,5 +518,5 @@ packages:
     source: hosted
     version: "1.0.4"
 sdks:
-  dart: ">=3.3.0 <4.0.0"
-  flutter: ">=3.19.0"
+  dart: ">=3.4.0 <4.0.0"
+  flutter: ">=3.22.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 4efd07a..16ca4fa 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,33 +1,37 @@
 name: twister
-description: twister game companion
+description: Twister game companion
 
-publish_to: 'none'
+publish_to: "none"
 
-version: 0.0.23+23
+version: 0.1.0+24
 
 environment:
-  sdk: '^3.0.0'
+  sdk: "^3.0.0"
 
 dependencies:
   flutter:
     sdk: flutter
 
-  audioplayers: ^5.2.1
+  # base
   easy_localization: ^3.0.1
   equatable: ^2.0.5
   flutter_bloc: ^8.1.1
   hive: ^2.2.3
-  path_provider: ^2.0.11
   hydrated_bloc: ^9.0.0
+  package_info_plus: ^8.0.0
+  path_provider: ^2.0.11
   unicons: ^2.1.1
 
+  # specific
+  audioplayers: ^6.0.0
+
 dev_dependencies:
-  flutter_lints: ^3.0.1
+  flutter_lints: ^4.0.0
 
 flutter:
-  uses-material-design: false
+  uses-material-design: true
   assets:
-    - assets/images/
+    - assets/ui/
     - assets/translations/
     - assets/voices/
 
@@ -42,3 +46,4 @@ flutter:
           weight: 400
         - asset: assets/fonts/Nunito-Light.ttf
           weight: 300
+
diff --git a/icons/build_repository_icons.sh b/resources/app/build_application_resources.sh
similarity index 98%
rename from icons/build_repository_icons.sh
rename to resources/app/build_application_resources.sh
index 27dbe26..6d67b8f 100755
--- a/icons/build_repository_icons.sh
+++ b/resources/app/build_application_resources.sh
@@ -6,7 +6,7 @@ command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not ins
 command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
 
 CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
-BASE_DIR="$(dirname "${CURRENT_DIR}")"
+BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
 
 SOURCE_ICON="${CURRENT_DIR}/icon.svg"
 SOURCE_FASTLANE="${CURRENT_DIR}/featureGraphic.svg"
diff --git a/icons/featureGraphic.svg b/resources/app/featureGraphic.svg
similarity index 100%
rename from icons/featureGraphic.svg
rename to resources/app/featureGraphic.svg
diff --git a/icons/icon.svg b/resources/app/icon.svg
similarity index 100%
rename from icons/icon.svg
rename to resources/app/icon.svg
diff --git a/resources/build_resources.sh b/resources/build_resources.sh
new file mode 100755
index 0000000..68bc1d0
--- /dev/null
+++ b/resources/build_resources.sh
@@ -0,0 +1,7 @@
+#! /bin/bash
+
+CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+
+${CURRENT_DIR}/app/build_application_resources.sh
+${CURRENT_DIR}/ui/build_ui_resources.sh
+${CURRENT_DIR}/tts/generate_sounds.sh
diff --git a/tts/generate_sounds.sh b/resources/tts/generate_sounds.sh
similarity index 98%
rename from tts/generate_sounds.sh
rename to resources/tts/generate_sounds.sh
index 660e16f..a5fe84c 100755
--- a/tts/generate_sounds.sh
+++ b/resources/tts/generate_sounds.sh
@@ -4,7 +4,7 @@
 command -v pico2wave >/dev/null 2>&1 || { echo >&2 "I require pico2wave (libttspico-utils) but it's not installed. Aborting."; exit 1; }
 
 CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
-BASE_DIR="$(dirname "${CURRENT_DIR}")"
+BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
 
 OUTPUT_BASE_FOLDER="${BASE_DIR}/assets/voices"
 mkdir -p "${OUTPUT_BASE_FOLDER}"
diff --git a/resources/ui/build_ui_resources.sh b/resources/ui/build_ui_resources.sh
new file mode 100755
index 0000000..93344c8
--- /dev/null
+++ b/resources/ui/build_ui_resources.sh
@@ -0,0 +1,111 @@
+#! /bin/bash
+
+# Check dependencies
+command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
+command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; }
+command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
+
+CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
+ASSETS_DIR="${BASE_DIR}/assets"
+
+OPTIPNG_OPTIONS="-preserve -quiet -o7"
+ICON_SIZE=512
+ICON_SIZE=192
+
+#######################################################
+
+# Game images (svg files found in `images` folder)
+AVAILABLE_GAME_IMAGES=""
+if [ -d "${CURRENT_DIR}/images" ]; then
+  AVAILABLE_GAME_IMAGES="$(find "${CURRENT_DIR}/images" -type f -name "*.svg" | awk -F/ '{print $NF}' | cut -d"." -f1 | sort)"
+fi
+
+# Skins (subfolders found in `skins` folder)
+AVAILABLE_SKINS=""
+if [ -d "${CURRENT_DIR}/skins" ]; then
+  AVAILABLE_SKINS="$(find "${CURRENT_DIR}/skins" -mindepth 1 -type d | awk -F/ '{print $NF}')"
+fi
+
+# Images per skin (svg files found recursively in `skins` folder and subfolders)
+SKIN_IMAGES=""
+if [ -d "${CURRENT_DIR}/skins" ]; then
+  SKIN_IMAGES="$(find "${CURRENT_DIR}/skins" -type f -name "*.svg" | awk -F/ '{print $NF}' | cut -d"." -f1 | sort | uniq)"
+fi
+
+#######################################################
+
+# optimize svg
+function optimize_svg() {
+  SOURCE="$1"
+
+  cp ${SOURCE} ${SOURCE}.tmp
+  scour \
+      --remove-descriptive-elements \
+      --enable-id-stripping \
+      --enable-viewboxing \
+      --enable-comment-stripping \
+      --nindent=4 \
+      --quiet \
+      -i ${SOURCE}.tmp \
+      -o ${SOURCE}
+  rm ${SOURCE}.tmp
+}
+
+# build icons
+function build_image() {
+  SOURCE="$1"
+  TARGET="$2"
+
+  echo "Building ${TARGET}"
+
+  if [ ! -f "${SOURCE}" ]; then
+    echo "Missing file: ${SOURCE}"
+    exit 1
+  fi
+
+  optimize_svg "${SOURCE}"
+
+  mkdir -p "$(dirname "${TARGET}")"
+
+  inkscape \
+      --export-width=${ICON_SIZE} \
+      --export-height=${ICON_SIZE} \
+      --export-filename=${TARGET} \
+      "${SOURCE}"
+
+  optipng ${OPTIPNG_OPTIONS} "${TARGET}"
+}
+
+function build_image_for_skin() {
+  SKIN_CODE="$1"
+
+  # skin images
+  for SKIN_IMAGE in ${SKIN_IMAGES}
+  do
+    build_image ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png
+  done
+}
+
+#######################################################
+
+# Delete existing generated images
+if [ -d "${ASSETS_DIR}/ui" ]; then
+  find ${ASSETS_DIR}/ui -type f -name "*.png" -delete
+fi
+if [ -d "${ASSETS_DIR}/skins" ]; then
+  find ${ASSETS_DIR}/skins -type f -name "*.png" -delete
+fi
+
+# build game images
+for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}
+do
+  build_image ${CURRENT_DIR}/images/${GAME_IMAGE}.svg ${ASSETS_DIR}/ui/${GAME_IMAGE}.png
+done
+
+# build skins images
+for SKIN in ${AVAILABLE_SKINS}
+do
+  build_image_for_skin "${SKIN}"
+done
+
diff --git a/resources/ui/images/button_back.svg b/resources/ui/images/button_back.svg
new file mode 100644
index 0000000..2622a57
--- /dev/null
+++ b/resources/ui/images/button_back.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#e41578" stroke="#fff" stroke-width=".238"/><path d="m59.387 71.362c1.1248 1.1302 4.0012 1.1302 4.0012 0v-45.921c0-1.1316-2.8832-1.1316-4.0121 0l-37.693 20.918c-1.1289 1.1248-1.1479 2.9551-0.02171 4.084z" fill="#fefeff" stroke="#930e4e" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m57.857 68.048c0.96243 0.96706 3.4236 0.96706 3.4236 0v-39.292c0-0.96825-2.467-0.96825-3.4329 0l-32.252 17.898c-0.96594 0.96243-0.9822 2.5285-0.01858 3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
diff --git a/resources/ui/images/button_delete_saved_game.svg b/resources/ui/images/button_delete_saved_game.svg
new file mode 100644
index 0000000..ac7eefe
--- /dev/null
+++ b/resources/ui/images/button_delete_saved_game.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#ee7d49" stroke="#fff" stroke-width=".238"/><path d="m61.07 35.601-1.7399 27.837c-0.13442 2.1535-1.9205 3.8312-4.0781 3.8312h-16.84c-2.1576 0-3.9437-1.6777-4.0781-3.8312l-1.7399-27.837h-2.6176c-0.84621 0-1.5323-0.68613-1.5323-1.5323 0-0.84655 0.68613-1.5323 1.5323-1.5323h33.711c0.84621 0 1.5323 0.68578 1.5323 1.5323 0 0.84621-0.68613 1.5323-1.5323 1.5323zm-3.2617 0h-21.953l1.4715 26.674c0.05985 1.0829 0.95531 1.9305 2.0403 1.9305h14.929c1.085 0 1.9804-0.84757 2.0403-1.9305zm-10.977 3.0647c0.78977 0 1.4301 0.6403 1.4301 1.4301v19.614c0 0.78977-0.6403 1.4301-1.4301 1.4301s-1.4301-0.6403-1.4301-1.4301v-19.614c0-0.78977 0.6403-1.4301 1.4301-1.4301zm-6.1293 0c0.80004 0 1.4588 0.62935 1.495 1.4286l0.89647 19.719c0.03182 0.70016-0.50998 1.2933-1.2101 1.3255-0.01915 7.02e-4 -0.03831 1e-3 -0.05781 1e-3 -0.74462 0-1.3596-0.58215-1.4003-1.3261l-1.0757-19.719c-0.0407-0.74701 0.53188-1.3852 1.2786-1.4259 0.02462-0.0014 0.04926-2e-3 0.07388-2e-3zm12.259 0c0.74804 0 1.3541 0.60609 1.3541 1.3541 0 0.02462-3.28e-4 0.04926-0.0017 0.07388l-1.0703 19.618c-0.04379 0.80106-0.70597 1.4281-1.5081 1.4281-0.74804 0-1.3541-0.60609-1.3541-1.3541 0-0.02462 3.49e-4 -0.04925 0.0017-0.07388l1.0703-19.618c0.04379-0.80106 0.70597-1.4281 1.5081-1.4281zm-10.216-12.259h8.1728c2.2567 0 4.086 1.8293 4.086 4.086v2.0433h-16.344v-2.0433c0-2.2567 1.8293-4.086 4.086-4.086zm0.20453 3.0647c-0.67725 0-1.2259 0.54863-1.2259 1.2259v1.8388h10.215v-1.8388c0-0.67725-0.54863-1.2259-1.2259-1.2259z" fill="#fff" fill-rule="evenodd" stroke="#bd4812" stroke-width=".75383"/></svg>
diff --git a/resources/ui/images/button_resume_game.svg b/resources/ui/images/button_resume_game.svg
new file mode 100644
index 0000000..6ad8b64
--- /dev/null
+++ b/resources/ui/images/button_resume_game.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m39.211 31.236c-0.84086-0.84489-2.9911-0.84489-2.9911 0v34.329c0 0.84594 2.1554 0.84594 2.9993 0l28.178-15.637c0.84392-0.84086 0.85812-2.2091 0.01623-3.053z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.1726"/><path d="m40.355 33.714c-0.71948-0.72294-2.5594-0.72294-2.5594 0v29.373c0 0.72383 1.8442 0.72383 2.5663 0l24.11-13.38c0.7221-0.71948 0.73426-1.8902 0.01389-2.6124z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.225"/><path d="m28.369 66.919v-37.591" fill="#105ca2" stroke="#105ca2" stroke-linecap="round" stroke-width="4.0337"/></svg>
diff --git a/resources/ui/images/button_start.svg b/resources/ui/images/button_start.svg
new file mode 100644
index 0000000..e9d49d2
--- /dev/null
+++ b/resources/ui/images/button_start.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
diff --git a/resources/ui/images/game_end.svg b/resources/ui/images/game_end.svg
new file mode 100644
index 0000000..fe20923
--- /dev/null
+++ b/resources/ui/images/game_end.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.17604 0 0 .17604 7.9341 1.7716)"><path d="m101.92 496.35c-1.8555 0-3.7109-0.69532-5.1484-2.0898-2.9297-2.8438-3-7.5234-0.15234-10.453l9.1875-9.4648c2.8438-2.9297 7.5234-3 10.453-0.15625s3 7.5234 0.15625 10.453l-9.1914 9.4648c-1.4492 1.4961-3.375 2.2461-5.3047 2.2461z" fill="#ff4e61"/><path d="m201.65 133.26c-1.8516 0-3.7109-0.69531-5.1445-2.0898-2.9297-2.8438-3-7.5234-0.15625-10.449l9.1914-9.4688c2.8438-2.9297 7.5195-3 10.449-0.15625s3 7.5234 0.15625 10.453l-9.1914 9.4688c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#ff4e61"/><path d="m413.8 100.39c-1.8555 0-3.7109-0.69141-5.1484-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l9.1914-9.4688c2.8438-2.9258 7.5234-2.9961 10.453-0.15234 2.9297 2.8398 3 7.5234 0.15625 10.449l-9.1914 9.4688c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#5c73bc"/><path d="m413.8 463.77c-1.8555 0-3.7109-0.69532-5.1484-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l9.1914-9.4688c2.8438-2.9258 7.5234-3 10.453-0.15625s3 7.5234 0.15625 10.453l-9.1914 9.4688c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#fa0"/><path d="m63.07 112.91c-1.8516 0-3.7109-0.69141-5.1445-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l9.1914-9.4687c2.8438-2.9258 7.5234-2.9961 10.453-0.15234 2.9258 2.8438 2.9961 7.5234 0.15234 10.449l-9.1914 9.4688c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#fa0"/><path d="m12.309 278.82c-1.8516 0-3.7109-0.69141-5.1445-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l9.1875-9.4688c2.8438-2.9297 7.5234-3 10.453-0.15625 2.9297 2.8438 3 7.5234 0.15625 10.453l-9.1914 9.4688c-1.4453 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#2dc471"/><path d="m216.29 278.49-23.996 12.996c-6.2226 3.3711-13.496-2.0742-12.309-9.2148l4.582-27.523c0.47266-2.8359-0.4375-5.7266-2.4375-7.7344l-19.414-19.496c-5.0352-5.0547-2.2578-13.863 4.7031-14.906l26.824-4.0156c2.7656-0.41407 5.1524-2.1992 6.3867-4.7812l12-25.043c3.1133-6.4922 12.102-6.4922 15.215 0l11.996 25.043c1.2383 2.582 3.625 4.3672 6.3867 4.7812l26.828 4.0156c6.957 1.043 9.7344 9.8516 4.6992 14.906l-19.41 19.496c-2 2.0078-2.9141 4.8984-2.4414 7.7344l4.582 27.523c1.1914 7.1406-6.082 12.586-12.305 9.2148l-23.996-12.996c-2.4727-1.3398-5.4258-1.3398-7.8945 0z" fill="#ffd02f"/><path d="m220.24 512c-4.082 0-7.3906-3.3086-7.3906-7.3906v-115.59c0-4.082 3.3086-7.3945 7.3906-7.3945s7.3906 3.3125 7.3906 7.3945v115.59c0 4.082-3.3086 7.3906-7.3906 7.3906z" fill="#5c73bc"/><path d="m220.3 357.42h-0.11328c-4.082 0-7.3945-3.3125-7.3945-7.3945s3.3086-7.3906 7.3945-7.3906h0.11328c4.082 0 7.3906 3.3086 7.3906 7.3906s-3.3086 7.3945-7.3906 7.3945z" fill="#5c73bc"/><path d="m220.3 332h-0.14838c-4.082-0.0156-7.375-3.3398-7.3594-7.4219 0.0195-4.0742 3.3242-7.3594 7.3906-7.3594h0.14848c4.082 0.0156 7.375 3.3398 7.3594 7.4219-0.0156 4.0703-3.3242 7.3594-7.3906 7.3594z" fill="#fa0"/><path d="m87.234 230.89c-1.9297 0-3.8555-0.75-5.3047-2.2422l-79.34-81.738c-2.8438-2.9297-2.7773-7.6094 0.15234-10.449 2.9297-2.8438 7.6094-2.7734 10.453 0.15235l79.344 81.738c2.8438 2.9258 2.7734 7.6094-0.15625 10.449-1.4375 1.3945-3.293 2.0898-5.1484 2.0898z" fill="#ff4e61"/><path d="m113.95 258.5c-1.8633 0-3.7266-0.69922-5.1641-2.1055-2.9219-2.8516-2.9766-7.5312-0.125-10.453l0.082-0.082c2.8516-2.918 7.5312-2.9766 10.453-0.12109 2.9219 2.8516 2.9766 7.5312 0.12109 10.453l-0.0781 0.082c-1.4492 1.4805-3.3672 2.2266-5.2891 2.2266z" fill="#fa0"/><path d="m131.4 276.48c-1.8555 0-3.7109-0.69531-5.1484-2.0898-2.9258-2.8438-2.9961-7.5234-0.15235-10.449l0.0781-0.0859c2.8476-2.9297 7.5273-2.9961 10.453-0.15235 2.9297 2.8438 3 7.5234 0.15625 10.453l-0.082 0.082c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#5c73bc"/><path d="m353.24 227.99c-1.8555 0-3.7109-0.69141-5.1445-2.0859-2.9297-2.8438-3-7.5234-0.15625-10.453l79.34-81.734c2.8438-2.9297 7.5234-3 10.453-0.15625 2.9297 2.8438 3 7.5234 0.15625 10.453l-79.344 81.734c-1.4492 1.4922-3.375 2.2422-5.3047 2.2422z" fill="#fa0"/><path d="m326.52 255.6c-1.9141 0-3.8242-0.73828-5.2695-2.2109l-0.082-0.082c-2.8633-2.9141-2.8203-7.5938 0.0899-10.453 2.9141-2.8633 7.5938-2.8203 10.453 0.0898l0.082 0.082c2.8594 2.9141 2.8203 7.5938-0.0937 10.453-1.4375 1.4141-3.3086 2.1211-5.1797 2.1211z" fill="#ff4e61"/><path d="m309.07 273.58c-1.9297 0-3.8555-0.75-5.3047-2.2422l-0.082-0.082c-2.8398-2.9297-2.7734-7.6094 0.15625-10.453s7.6094-2.7734 10.453 0.15234l0.082 0.082c2.8398 2.9297 2.7734 7.6094-0.15625 10.453-1.4375 1.3945-3.293 2.0898-5.1484 2.0898z" fill="#fa0"/><path d="m300.65 116.69c-1.2422 0-2.5-0.3125-3.6523-0.97266-3.5469-2.0234-4.7812-6.5391-2.7578-10.082l56.863-99.652c2.0234-3.543 6.5352-4.7773 10.082-2.7539 3.5469 2.0234 4.7812 6.5391 2.7578 10.082l-56.863 99.652c-1.3633 2.3867-3.8594 3.7266-6.4297 3.7266z" fill="#62d38f"/><path d="m281.52 150.33c-1.293 0-2.5977-0.33593-3.7891-1.0469l-0.0976-0.0586c-3.5-2.0938-4.6445-6.6328-2.5469-10.137 2.0938-3.5078 6.6328-4.6445 10.137-2.5508l0.0977 0.0586c3.5039 2.0938 4.6445 6.6328 2.5508 10.137-1.3867 2.3164-3.8359 3.5976-6.3516 3.5976z" fill="#fa0"/><path d="m269.02 172.25c-1.3008 0-2.6172-0.34375-3.8086-1.0625l-0.0977-0.0586c-3.4961-2.1094-4.6211-6.6523-2.5156-10.148 2.1094-3.4961 6.6523-4.6172 10.148-2.5117l0.0976 0.0586c3.4961 2.1094 4.6211 6.6523 2.5117 10.148-1.3867 2.3008-3.832 3.5742-6.3359 3.5742z" fill="#2dc471"/><path d="m139.96 116.69c-2.5703 0-5.0664-1.3398-6.4297-3.7305l-56.863-99.648c-2.0234-3.5469-0.78906-8.0586 2.7539-10.082 3.5469-2.0234 8.0625-0.79297 10.086 2.7539l56.863 99.648c2.0234 3.5469 0.78906 8.0625-2.7539 10.086-1.1562 0.66016-2.4141 0.97266-3.6562 0.97266z" fill="#5c73bc"/><path d="m159.09 150.33c-2.5078 0-4.957-1.2773-6.3438-3.582-2.1016-3.5-0.96875-8.043 2.5273-10.145l0.10157-0.0586c3.5-2.1016 8.0391-0.97266 10.141 2.5273 2.1055 3.5 0.97266 8.0391-2.5273 10.145l-0.0977 0.0586c-1.1914 0.71484-2.5039 1.0547-3.8008 1.0547z" fill="#ff4e61"/><path d="m171.6 172.25c-2.5 0-4.9375-1.2656-6.3281-3.5625-2.1172-3.4922-1-8.0352 2.4883-10.152l0.0977-0.0586c3.4961-2.1133 8.0391-1 10.156 2.4922 2.1133 3.4922 1 8.0352-2.4922 10.152l-0.0977 0.0586c-1.1992 0.72656-2.5195 1.0703-3.8242 1.0703z" fill="#fa0"/><path d="m402.14 357.28-15.523 11.602c-4.0234 3.0117-9.6523-0.043-9.5234-5.1641l0.5039-19.75c0.0508-2.0352-0.87109-3.9648-2.4688-5.1641l-15.508-11.621c-4.0234-3.0156-2.9453-9.4726 1.8242-10.93l18.391-5.6094c1.8906-0.57812 3.3906-2.082 4-4.0156l5.9375-18.785c1.5391-4.875 7.8359-5.8125 10.652-1.5898l10.863 16.285c1.1211 1.6758 2.9688 2.6797 4.9414 2.6797l19.18 0.0117c4.9766 4e-3 7.7891 5.8828 4.7578 9.9492l-11.676 15.672c-1.2031 1.6172-1.5586 3.7383-0.94922 5.6719l5.918 18.797c1.5312 4.875-3.0273 9.4453-7.7148 7.7344l-18.078-6.5977c-1.8594-0.67969-3.9258-0.37109-5.5273 0.82422z" fill="#ffd02f"/><path d="m261.51 512c-4.082 0-7.3906-3.3086-7.3906-7.3906 0-57.23 22.832-95.922 41.984-118.3 20.828-24.332 41.613-35.023 42.488-35.469 3.6406-1.8477 8.0898-0.39063 9.9336 3.2539 1.8438 3.6367 0.39453 8.0781-3.2422 9.9297-0.3125 0.16016-19.5 10.164-38.367 32.395-25.227 29.719-38.016 66.121-38.016 108.2 0 4.082-3.3086 7.3906-7.3906 7.3906z" fill="#ff4e61"/><path d="m102.86 397.35 11.766 15.605c3.0547 4.0469 9.2852 2.7305 10.547-2.2266l4.8633-19.113c0.5-1.9648 1.9102-3.5547 3.7695-4.2461l18.039-6.707c4.6797-1.7383 5.3906-8.25 1.207-11.016l-16.141-10.672c-1.6602-1.1016-2.6914-2.9726-2.7578-5.0039l-0.61719-19.75c-0.15625-5.1211-5.9492-7.832-9.7969-4.5859l-14.84 12.516c-1.5312 1.2891-3.5781 1.7227-5.4726 1.1562l-18.422-5.5c-4.7773-1.4258-9.0703 3.4102-7.2617 8.1836l6.9688 18.41c0.71875 1.8945 0.48438 4.0352-0.625 5.7188l-10.77 16.348c-2.793 4.2422 0.34375 9.9375 5.3125 9.6445l19.145-1.1406c1.9727-0.11719 3.875 0.77343 5.0859 2.3789z" fill="#ffd02f"/><path d="m179.02 512c-4.082 0-7.3906-3.3086-7.3906-7.3906 0-30.059-6.6797-57.559-19.852-81.734-1.9531-3.5859-0.62891-8.0742 2.957-10.027 3.5859-1.9531 8.0742-0.62891 10.027 2.9531 14.363 26.375 21.648 56.254 21.648 88.809 0 4.082-3.3086 7.3906-7.3906 7.3906z" fill="#fa0"/><path d="m268.93 55.898c0-11.285-8.8828-20.434-19.836-20.434-10.957 0-19.836 9.1484-19.836 20.434 0 11.285 8.8789 20.438 19.836 20.438 10.953 0 19.836-9.1523 19.836-20.438z" fill="#ffd02f"/><path d="m373.08 446.81c0-11.285-8.8789-20.434-19.832-20.434-10.957 0-19.836 9.1484-19.836 20.434s8.8789 20.434 19.836 20.434c10.953 0 19.832-9.1484 19.832-20.434z" fill="#5c73bc"/><path d="m44.129 450.86c0-9.0508-7.1211-16.387-15.91-16.387-8.7852 0-15.906 7.3359-15.906 16.387 0 9.0547 7.1211 16.391 15.906 16.391 8.7891 0 15.91-7.3359 15.91-16.391z" fill="#62d38f"/><path d="m88.172 288.35c0-9.0508-7.1211-16.387-15.91-16.387-8.7852 0-15.906 7.3359-15.906 16.387s7.1211 16.391 15.906 16.391c8.7891 0 15.91-7.3398 15.91-16.391z" fill="#5c73bc"/><g fill="#ff4e61"><path d="m210.84 16.391c0-9.0547-7.1211-16.391-15.906-16.391-8.7891 0-15.91 7.3359-15.91 16.391 0 9.0508 7.1211 16.387 15.91 16.387 8.7852 0 15.906-7.3359 15.906-16.387z"/><path d="m365.23 152.88c0-9.0508-7.125-16.391-15.91-16.391-8.7852 0-15.91 7.3398-15.91 16.391s7.125 16.387 15.91 16.387c8.7852 0 15.91-7.3359 15.91-16.387z"/><path d="m139.96 32.746c-1.8555 0-3.7109-0.69141-5.1484-2.0898-2.9297-2.8438-3-7.5195-0.15625-10.449l9.1914-9.4688c2.8438-2.9297 7.5234-3 10.449-0.15625 2.9297 2.8438 3 7.5234 0.15625 10.453l-9.1875 9.4688c-1.4492 1.4922-3.3789 2.2422-5.3047 2.2422z"/></g></g></svg>
diff --git a/images/blank.svg b/resources/ui/images/move-blank.svg
similarity index 100%
rename from images/blank.svg
rename to resources/ui/images/move-blank.svg
diff --git a/images/left-foot.svg b/resources/ui/images/move-left-foot.svg
similarity index 100%
rename from images/left-foot.svg
rename to resources/ui/images/move-left-foot.svg
diff --git a/images/left-hand.svg b/resources/ui/images/move-left-hand.svg
similarity index 100%
rename from images/left-hand.svg
rename to resources/ui/images/move-left-hand.svg
diff --git a/images/right-foot.svg b/resources/ui/images/move-right-foot.svg
similarity index 100%
rename from images/right-foot.svg
rename to resources/ui/images/move-right-foot.svg
diff --git a/images/right-hand.svg b/resources/ui/images/move-right-hand.svg
similarity index 100%
rename from images/right-hand.svg
rename to resources/ui/images/move-right-hand.svg
diff --git a/resources/ui/images/placeholder.svg b/resources/ui/images/placeholder.svg
new file mode 100644
index 0000000..23ace81
--- /dev/null
+++ b/resources/ui/images/placeholder.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"/>
-- 
GitLab