-
BINassets/images/level_1_image.png
-
BINassets/images/level_2_image.png
-
BINassets/images/level_4_image.png
-
BINassets/images/level_screen_image.png
-
BINassets/images/splash_screen_image.png
-
BINassets/images/start.png
-
3assets/images/svg/check.svg
-
3assets/images/svg/lock.svg
-
3assets/images/svg/start.svg
-
3lib/main.dart
-
113lib/screens/level_list/screen/level_list_screen.dart
-
178lib/screens/level_list/widgets/level_widget.dart
-
140lib/screens/level_list/widgets/lock_level_widget.dart
-
143lib/screens/level_list/widgets/payed_level_widget.dart
-
54lib/screens/login_screen_name.dart
-
180lib/screens/menu_screen.dart
-
5lib/screens/photo/photo_screen_large.dart
-
152lib/screens/puzzle/top_bar.dart
-
220lib/screens/puzzle_screen.dart
-
489lib/screens/puzzle_solo_screen.dart
-
43lib/screens/splash/screen/splash_screen.dart
-
19lib/utils/extensions/context_extension.dart
-
4lib/utils/extensions/string_extensions.dart
-
308lib/widgets/animated_grid.dart
-
67lib/widgets/grid.dart
-
62lib/widgets/login_widgets/name_field.dart
-
72lib/widgets/login_widgets/start_game_widget.dart
-
39lib/widgets/login_widgets/start_game_widget/start_game_button.dart
-
2lib/widgets/menu_widgets/menu_widgets.dart
-
108lib/widgets/menu_widgets/multiplayer_button.dart
-
44lib/widgets/menu_widgets/solo_button.dart
-
53lib/widgets/photo_screen/pick_image_button.dart
-
28lib/widgets/puzzle_widgets/moves_text.dart
-
26lib/widgets/puzzle_widgets/player_text.dart
-
2lib/widgets/puzzle_widgets/puzzle_widgets.dart
-
73lib/widgets/puzzle_widgets/solo/timer_widget.dart
-
6lib/widgets/solo_screen/solo_screen_export.dart
-
42pubspec.lock
-
5pubspec.yaml
After Width: 70 | Height: 70 | Size: 10 KiB |
After Width: 70 | Height: 71 | Size: 11 KiB |
After Width: 70 | Height: 71 | Size: 13 KiB |
After Width: 214 | Height: 296 | Size: 54 KiB |
After Width: 266 | Height: 209 | Size: 45 KiB |
After Width: 63 | Height: 63 | Size: 1.8 KiB |
@ -0,0 +1,3 @@ |
|||||
|
<svg id="Icon_-_Check" data-name="Icon - Check" xmlns="http://www.w3.org/2000/svg" width="7.807" height="5.577" viewBox="0 0 7.807 5.577"> |
||||
|
<path id="Vector_" data-name="Vector " d="M7.564.193a.744.744,0,0,1,.05,1.05L3.9,5.333a.744.744,0,0,1-.982.1L.311,3.579a.744.744,0,1,1,.864-1.21L3.24,3.844,6.514.243A.744.744,0,0,1,7.564.193Z" transform="translate(0 0)" fill="#5f34fa"/> |
||||
|
</svg> |
@ -0,0 +1,3 @@ |
|||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="6.643" height="8.636" viewBox="0 0 6.643 8.636"> |
||||
|
<path id="Icon_ionic-ios-lock" data-name="Icon ionic-ios-lock" d="M12.562,6.364h-.5V5.394a1.993,1.993,0,1,0-3.986-.027v1h-.5a.833.833,0,0,0-.83.83V11.18a.833.833,0,0,0,.83.83h4.982a.833.833,0,0,0,.83-.83V7.194A.833.833,0,0,0,12.562,6.364Zm-2.2,2.591v1.428a.3.3,0,0,1-.276.3.291.291,0,0,1-.305-.291V8.955a.664.664,0,1,1,.581,0Zm1.121-2.591H8.66v-1a1.412,1.412,0,0,1,2.823,0Z" transform="translate(-6.75 -3.374)" fill="#6536f2"/> |
||||
|
</svg> |
@ -0,0 +1,3 @@ |
|||||
|
<svg id="icon-play" xmlns="http://www.w3.org/2000/svg" width="7.426" height="9.027" viewBox="0 0 7.426 9.027"> |
||||
|
<path id="Shape" d="M1.095,8.811A2,2,0,0,1,0,7.025V2A2,2,0,0,1,3.184.388L6.608,2.9h0a2,2,0,0,1,0,3.226L3.183,8.638a2,2,0,0,1-2.088.173Z" transform="translate(0 0)" fill="#ff9a00"/> |
||||
|
</svg> |
@ -0,0 +1,178 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_svg/flutter_svg.dart'; |
||||
|
import 'package:my_flutter_puzzle/screens/level_list/screen/level_list_screen.dart'; |
||||
|
import 'package:my_flutter_puzzle/utils/extensions/context_extension.dart'; |
||||
|
import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart'; |
||||
|
|
||||
|
class LevelWidget extends StatelessWidget { |
||||
|
final Level level; |
||||
|
|
||||
|
const LevelWidget({Key? key, required this.level}) : super(key: key); |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
return Container( |
||||
|
padding: const EdgeInsetsDirectional.only(top: 10, start: 8, end: 8, bottom: 10), |
||||
|
margin: const EdgeInsets.only(bottom: 16), |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(16), |
||||
|
gradient: const LinearGradient( |
||||
|
colors: [ |
||||
|
Color(0xff5E34F5), |
||||
|
Color(0xff4425B1), |
||||
|
], |
||||
|
begin: Alignment.topCenter, |
||||
|
end: Alignment.bottomCenter, |
||||
|
), |
||||
|
border: Border.all( |
||||
|
color: const Color(0xff6135FD), |
||||
|
width: 1, |
||||
|
), |
||||
|
), |
||||
|
child: Row( |
||||
|
crossAxisAlignment: CrossAxisAlignment.end, |
||||
|
children: [ |
||||
|
Stack( |
||||
|
alignment: AlignmentDirectional.centerEnd, |
||||
|
children: [ |
||||
|
Container( |
||||
|
width: context.width * 70 / 820, |
||||
|
height: context.width * 70 / 820, |
||||
|
margin: const EdgeInsetsDirectional.only(end: 16), |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(8), |
||||
|
image: DecorationImage( |
||||
|
image: AssetImage(level.image), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Container( |
||||
|
width: context.width * 28 / 820, |
||||
|
height: context.width * 28 / 820, |
||||
|
margin: const EdgeInsetsDirectional.only(end: 6), |
||||
|
decoration: BoxDecoration( |
||||
|
shape: BoxShape.circle, |
||||
|
color: Colors.red, |
||||
|
border: Border.all( |
||||
|
color: const Color(0xff6136FE), |
||||
|
), |
||||
|
gradient: const LinearGradient( |
||||
|
colors: [ |
||||
|
Color(0xff6135FC), |
||||
|
Color(0xff4925CE), |
||||
|
], |
||||
|
begin: Alignment.topCenter, |
||||
|
end: Alignment.bottomCenter, |
||||
|
), |
||||
|
), |
||||
|
child: Container( |
||||
|
padding: EdgeInsets.all(context.width * 5 / 820), |
||||
|
margin: EdgeInsets.all(context.width * 5 / 820), |
||||
|
decoration: const BoxDecoration( |
||||
|
color: Color(0xffF7B500), |
||||
|
shape: BoxShape.circle, |
||||
|
), |
||||
|
child: SvgPicture.asset('check'.svgPath), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
Column( |
||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||
|
children: [ |
||||
|
Row( |
||||
|
children: [ |
||||
|
Text( |
||||
|
'Level ${level.level}', |
||||
|
style: const TextStyle( |
||||
|
color: Colors.white, |
||||
|
fontSize: 20, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
const SizedBox(width: 12), |
||||
|
Text( |
||||
|
'${level.puzzleSize}*${level.puzzleSize} | 00:56', |
||||
|
style: const TextStyle( |
||||
|
color: Color(0xffBCACF4), |
||||
|
fontSize: 16, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
const SizedBox(height: 8), |
||||
|
const Text( |
||||
|
'Keyboard', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white, |
||||
|
fontSize: 18, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
const Spacer(), |
||||
|
Container( |
||||
|
padding: const EdgeInsets.all(3), |
||||
|
decoration: BoxDecoration( |
||||
|
color: const Color(0xff5F358F), |
||||
|
borderRadius: BorderRadius.circular(36), |
||||
|
), |
||||
|
child: Container( |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(31), |
||||
|
gradient: const LinearGradient( |
||||
|
colors: [ |
||||
|
Color(0xffFFC600), |
||||
|
Color(0xffFF5A00), |
||||
|
], |
||||
|
begin: Alignment.topCenter, |
||||
|
end: Alignment.bottomCenter, |
||||
|
), |
||||
|
), |
||||
|
child: Row( |
||||
|
mainAxisAlignment: MainAxisAlignment.center, |
||||
|
children: [ |
||||
|
const SizedBox(width: 6), |
||||
|
Container( |
||||
|
width: context.width * 26 / 540, |
||||
|
height: context.width * 26 / 540, |
||||
|
padding: const EdgeInsets.all(9), |
||||
|
margin: const EdgeInsets.symmetric(vertical: 3), |
||||
|
decoration: BoxDecoration( |
||||
|
border: Border.all( |
||||
|
color: Colors.white, |
||||
|
width: 1, |
||||
|
), |
||||
|
gradient: const LinearGradient( |
||||
|
colors: [ |
||||
|
Colors.white, |
||||
|
Color(0xffD5D5D5), |
||||
|
], |
||||
|
begin: Alignment.topCenter, |
||||
|
end: Alignment.bottomCenter, |
||||
|
), |
||||
|
shape: BoxShape.circle, |
||||
|
), |
||||
|
child: SvgPicture.asset('start'.svgPath), |
||||
|
), |
||||
|
const SizedBox(width: 8), |
||||
|
const Text( |
||||
|
'Start', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white, |
||||
|
fontSize: 14, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
const SizedBox(width: 14), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
@ -0,0 +1,140 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_svg/flutter_svg.dart'; |
||||
|
import 'package:my_flutter_puzzle/screens/level_list/screen/level_list_screen.dart'; |
||||
|
import 'package:my_flutter_puzzle/utils/extensions/context_extension.dart'; |
||||
|
import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart'; |
||||
|
|
||||
|
class LockLevelWidget extends StatelessWidget { |
||||
|
final Level level; |
||||
|
|
||||
|
const LockLevelWidget({Key? key, required this.level}) : super(key: key); |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
return Container( |
||||
|
padding: const EdgeInsets.all(8), |
||||
|
margin: const EdgeInsets.only(bottom: 16), |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(16), |
||||
|
gradient: LinearGradient( |
||||
|
colors: [ |
||||
|
const Color(0xff6236FF).withOpacity(0.5), |
||||
|
const Color(0xff311B80).withOpacity(0.5), |
||||
|
], |
||||
|
begin: Alignment.topCenter, |
||||
|
end: Alignment.bottomCenter, |
||||
|
), |
||||
|
border: Border.all( |
||||
|
color: const Color(0xff6135FD), |
||||
|
width: 1, |
||||
|
), |
||||
|
), |
||||
|
child: Row( |
||||
|
crossAxisAlignment: CrossAxisAlignment.end, |
||||
|
children: [ |
||||
|
Container( |
||||
|
width: context.width * 70 / 820, |
||||
|
height: context.width * 70 / 820, |
||||
|
margin: const EdgeInsetsDirectional.only(end: 16), |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(8), |
||||
|
image: DecorationImage( |
||||
|
image: AssetImage(level.image), |
||||
|
opacity: 0.8, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Column( |
||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||
|
children: [ |
||||
|
Row( |
||||
|
children: [ |
||||
|
Text( |
||||
|
'Level ${level.level}', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white.withOpacity(0.5), |
||||
|
fontSize: 20, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
const SizedBox(width: 12), |
||||
|
Text( |
||||
|
'${level.puzzleSize}*${level.puzzleSize} | 00:56', |
||||
|
style: TextStyle( |
||||
|
color: const Color(0xffBCACF4).withOpacity(0.5), |
||||
|
fontSize: 16, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
const SizedBox(height: 8), |
||||
|
Text( |
||||
|
'Keyboard', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white.withOpacity(0.5), |
||||
|
fontSize: 18, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
const Spacer(), |
||||
|
Column( |
||||
|
children: [ |
||||
|
Text( |
||||
|
'Solve lvl ${level.level - 1}', |
||||
|
style: const TextStyle( |
||||
|
color: Colors.white, |
||||
|
fontSize: 12, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
const SizedBox(height: 8), |
||||
|
Container( |
||||
|
padding: const EdgeInsets.all(3), |
||||
|
decoration: BoxDecoration( |
||||
|
color: const Color(0xff5F358F).withOpacity(0.8), |
||||
|
borderRadius: BorderRadius.circular(36), |
||||
|
), |
||||
|
child: Container( |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(31), |
||||
|
color: const Color(0xff5D32DE), |
||||
|
), |
||||
|
child: Row( |
||||
|
mainAxisAlignment: MainAxisAlignment.center, |
||||
|
children: [ |
||||
|
const SizedBox(width: 6), |
||||
|
Container( |
||||
|
width: context.width * 26 / 540, |
||||
|
height: context.width * 26 / 540, |
||||
|
padding: const EdgeInsets.all(10), |
||||
|
margin: const EdgeInsets.symmetric(vertical: 3), |
||||
|
decoration: const BoxDecoration( |
||||
|
color: Color(0xffAF99EF), |
||||
|
shape: BoxShape.circle, |
||||
|
), |
||||
|
child: SvgPicture.asset('lock'.svgPath), |
||||
|
), |
||||
|
const SizedBox(width: 8), |
||||
|
Text( |
||||
|
'Lock', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white.withOpacity(0.8), |
||||
|
fontSize: 14, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
const SizedBox(width: 14), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
@ -0,0 +1,143 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_svg/flutter_svg.dart'; |
||||
|
import 'package:my_flutter_puzzle/screens/level_list/screen/level_list_screen.dart'; |
||||
|
import 'package:my_flutter_puzzle/utils/extensions/context_extension.dart'; |
||||
|
import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart'; |
||||
|
|
||||
|
class PayedLevelWidget extends StatelessWidget { |
||||
|
final Level level; |
||||
|
|
||||
|
const PayedLevelWidget({ |
||||
|
Key? key, |
||||
|
required this.level, |
||||
|
}) : super(key: key); |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
return Container( |
||||
|
padding: const EdgeInsets.all(8), |
||||
|
margin: const EdgeInsets.only(bottom: 16), |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(16), |
||||
|
gradient: LinearGradient( |
||||
|
colors: [ |
||||
|
const Color(0xff6236FF).withOpacity(0.5), |
||||
|
const Color(0xff311B80).withOpacity(0.5), |
||||
|
], |
||||
|
begin: Alignment.topCenter, |
||||
|
end: Alignment.bottomCenter, |
||||
|
), |
||||
|
border: Border.all( |
||||
|
color: const Color(0xff6135FD), |
||||
|
width: 1, |
||||
|
), |
||||
|
), |
||||
|
child: Row( |
||||
|
crossAxisAlignment: CrossAxisAlignment.end, |
||||
|
children: [ |
||||
|
Container( |
||||
|
width: context.width * 70 / 820, |
||||
|
height: context.width * 70 / 820, |
||||
|
margin: const EdgeInsetsDirectional.only(end: 16), |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(8), |
||||
|
image: DecorationImage( |
||||
|
image: AssetImage(level.image), |
||||
|
opacity: 0.8, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Column( |
||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||
|
children: [ |
||||
|
Row( |
||||
|
children: [ |
||||
|
Text( |
||||
|
'Level ${level.level}', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white.withOpacity(0.5), |
||||
|
fontSize: 20, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
const SizedBox(width: 12), |
||||
|
Text( |
||||
|
'${level.puzzleSize}*${level.puzzleSize} | 00:56', |
||||
|
style: TextStyle( |
||||
|
color: const Color(0xffBCACF4).withOpacity(0.5), |
||||
|
fontSize: 16, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
const SizedBox(height: 8), |
||||
|
Text( |
||||
|
'Keyboard', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white.withOpacity(0.5), |
||||
|
fontSize: 18, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
const Spacer(), |
||||
|
Column( |
||||
|
children: [ |
||||
|
const Text( |
||||
|
'\$ 2', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white, |
||||
|
fontSize: 14, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
const SizedBox(height: 8), |
||||
|
Container( |
||||
|
padding: const EdgeInsets.all(3), |
||||
|
decoration: BoxDecoration( |
||||
|
color: const Color(0xff5F358F).withOpacity(0.8), |
||||
|
borderRadius: BorderRadius.circular(36), |
||||
|
), |
||||
|
child: Container( |
||||
|
decoration: BoxDecoration( |
||||
|
borderRadius: BorderRadius.circular(31), |
||||
|
color: const Color(0xff7853FF), |
||||
|
), |
||||
|
child: Row( |
||||
|
mainAxisAlignment: MainAxisAlignment.center, |
||||
|
children: [ |
||||
|
const SizedBox(width: 6), |
||||
|
Container( |
||||
|
width: context.width * 26 / 540, |
||||
|
height: context.width * 26 / 540, |
||||
|
padding: const EdgeInsets.all(10), |
||||
|
margin: const EdgeInsets.symmetric(vertical: 3), |
||||
|
decoration: const BoxDecoration( |
||||
|
color: Colors.white , |
||||
|
shape: BoxShape.circle, |
||||
|
), |
||||
|
child: SvgPicture.asset('lock'.svgPath), |
||||
|
), |
||||
|
const SizedBox(width: 8), |
||||
|
Text( |
||||
|
'Buy', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white.withOpacity(0.8), |
||||
|
fontSize: 14, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
const SizedBox(width: 14), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
@ -1,54 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:my_flutter_puzzle/widgets/login_widgets/name_field.dart'; |
|
||||
|
|
||||
class LoginScreenName extends StatefulWidget { |
|
||||
const LoginScreenName({Key? key}) : super(key: key); |
|
||||
|
|
||||
@override |
|
||||
State<LoginScreenName> createState() => _LoginScreenNameState(); |
|
||||
} |
|
||||
|
|
||||
class _LoginScreenNameState extends State<LoginScreenName> { |
|
||||
late final TextEditingController _nameTextController; |
|
||||
late final FocusNode _nameFocusNode; |
|
||||
|
|
||||
String _nameString = ''; |
|
||||
|
|
||||
@override |
|
||||
void initState() { |
|
||||
super.initState(); |
|
||||
_nameTextController = TextEditingController(); |
|
||||
_nameFocusNode = FocusNode(); |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
var screenSize = MediaQuery.of(context).size; |
|
||||
return GestureDetector( |
|
||||
onTap: () => _nameFocusNode.unfocus(), |
|
||||
child: Scaffold( |
|
||||
backgroundColor: Colors.white, |
|
||||
body: Center( |
|
||||
child: SizedBox( |
|
||||
width: screenSize.width * 0.5, |
|
||||
child: Column( |
|
||||
mainAxisAlignment: MainAxisAlignment.center, |
|
||||
children: [ |
|
||||
NameField( |
|
||||
focusNode: _nameFocusNode, |
|
||||
onChange: (value) => setState( |
|
||||
() => _nameString = value, |
|
||||
), |
|
||||
), |
|
||||
const SizedBox(height: 24), |
|
||||
// StartGameWidget( |
|
||||
// nameString: _nameString, |
|
||||
// ), |
|
||||
], |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,180 +0,0 @@ |
|||||
// import 'package:cloud_firestore/cloud_firestore.dart'; |
|
||||
// import 'package:flutter/material.dart'; |
|
||||
// import 'package:flutter_riverpod/flutter_riverpod.dart'; |
|
||||
// import 'package:my_flutter_puzzle/application/states/player_matching_state.dart'; |
|
||||
// import 'package:my_flutter_puzzle/models/user_info.dart'; |
|
||||
// import 'package:my_flutter_puzzle/providers.dart'; |
|
||||
// import 'package:my_flutter_puzzle/res/palette.dart'; |
|
||||
// import 'package:my_flutter_puzzle/utils/database_client.dart'; |
|
||||
// import 'package:my_flutter_puzzle/screens/puzzle_screen.dart'; |
|
||||
// import 'package:my_flutter_puzzle/widgets/menu_widgets/menu_widgets.dart'; |
|
||||
|
|
||||
// class MenuScreen extends ConsumerStatefulWidget { |
|
||||
// const MenuScreen({ |
|
||||
// Key? key, |
|
||||
// required this.userData, |
|
||||
// }) : super(key: key); |
|
||||
|
|
||||
// final UserData userData; |
|
||||
|
|
||||
// @override |
|
||||
// ConsumerState<ConsumerStatefulWidget> createState() => _MenuScreenState(); |
|
||||
// } |
|
||||
|
|
||||
// class _MenuScreenState extends ConsumerState<MenuScreen> { |
|
||||
// final numberList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; |
|
||||
// late final UserData userData; |
|
||||
|
|
||||
// @override |
|
||||
// void initState() { |
|
||||
// super.initState(); |
|
||||
// userData = widget.userData; |
|
||||
// numberList.shuffle(); |
|
||||
// } |
|
||||
|
|
||||
// @override |
|
||||
// Widget build(BuildContext context) { |
|
||||
// var screenSize = MediaQuery.of(context).size; |
|
||||
|
|
||||
// ref.listen(playerMatchingNotifierProvider, (previous, next) { |
|
||||
// if (next is PlayerMatched) { |
|
||||
// Navigator.of(context).push( |
|
||||
// MaterialPageRoute( |
|
||||
// builder: (context) => PuzzleScreen( |
|
||||
// initialList: numberList, |
|
||||
// id: next.id, |
|
||||
// myInfo: userData, |
|
||||
// ), |
|
||||
// ), |
|
||||
// ); |
|
||||
// } |
|
||||
// }); |
|
||||
|
|
||||
// return Scaffold( |
|
||||
// backgroundColor: Colors.white, |
|
||||
// body: Center( |
|
||||
// child: SizedBox( |
|
||||
// width: screenSize.width * 0.5, |
|
||||
// child: Consumer( |
|
||||
// builder: (context, ref, child) { |
|
||||
// final state = ref.watch(playerMatchingNotifierProvider); |
|
||||
|
|
||||
// return state.when( |
|
||||
// () => Column( |
|
||||
// mainAxisAlignment: MainAxisAlignment.center, |
|
||||
// children: [ |
|
||||
// const Text( |
|
||||
// 'Game Mode', |
|
||||
// style: TextStyle( |
|
||||
// fontSize: 30, |
|
||||
// // fontWeight: FontWeight.bold, |
|
||||
// color: Palette.crimson, |
|
||||
// ), |
|
||||
// ), |
|
||||
// const SizedBox(height: 24), |
|
||||
// MultiplayerButton( |
|
||||
// myInfo: userData, |
|
||||
// list: numberList, |
|
||||
// ), |
|
||||
// const SizedBox(height: 16), |
|
||||
// const SoloButton(), |
|
||||
// const SizedBox(height: 30), |
|
||||
// ], |
|
||||
// ), |
|
||||
// processing: () => Row( |
|
||||
// mainAxisAlignment: MainAxisAlignment.center, |
|
||||
// children: const [ |
|
||||
// CircularProgressIndicator( |
|
||||
// valueColor: |
|
||||
// AlwaysStoppedAnimation<Color>(Palette.violet), |
|
||||
// ), |
|
||||
// SizedBox(width: 16), |
|
||||
// Text( |
|
||||
// 'Finding player ...', |
|
||||
// style: TextStyle( |
|
||||
// fontSize: 24, |
|
||||
// ), |
|
||||
// ), |
|
||||
// ], |
|
||||
// ), |
|
||||
// isMatched: (id) => Row( |
|
||||
// mainAxisAlignment: MainAxisAlignment.center, |
|
||||
// children: const [ |
|
||||
// Icon( |
|
||||
// Icons.check_circle, |
|
||||
// color: Palette.violet, |
|
||||
// size: 50, |
|
||||
// ), |
|
||||
// SizedBox(width: 16), |
|
||||
// Text( |
|
||||
// 'Found player', |
|
||||
// style: TextStyle( |
|
||||
// fontSize: 24, |
|
||||
// ), |
|
||||
// ), |
|
||||
// ], |
|
||||
// ), |
|
||||
// isQueued: () => PlayerQueuedWidget( |
|
||||
// myInfo: userData, |
|
||||
// ), |
|
||||
// error: (message) => Text( |
|
||||
// message.toString(), |
|
||||
// style: const TextStyle( |
|
||||
// fontSize: 24, |
|
||||
// ), |
|
||||
// ), |
|
||||
// ); |
|
||||
// }, |
|
||||
// ), |
|
||||
// ), |
|
||||
// )); |
|
||||
// } |
|
||||
// } |
|
||||
|
|
||||
// class PlayerQueuedWidget extends ConsumerWidget { |
|
||||
// PlayerQueuedWidget({ |
|
||||
// Key? key, |
|
||||
// required this.myInfo, |
|
||||
// }) : super(key: key); |
|
||||
|
|
||||
// final UserData myInfo; |
|
||||
|
|
||||
// final _databaseClient = DatabaseClient(); |
|
||||
|
|
||||
// @override |
|
||||
// Widget build(BuildContext context, WidgetRef ref) { |
|
||||
// return StreamBuilder<DocumentSnapshot>( |
|
||||
// stream: _databaseClient.isMatched(myInfo: myInfo), |
|
||||
// builder: (context, snapshot) { |
|
||||
// if (snapshot.hasData && snapshot.data!.data() != null) { |
|
||||
// final queuedUserData = |
|
||||
// snapshot.data!.data() as Map<String, dynamic>; |
|
||||
// bool isMatched = queuedUserData['ismatched']; |
|
||||
|
|
||||
// if (isMatched) { |
|
||||
// WidgetsBinding.instance?.addPostFrameCallback((_) { |
|
||||
// ref |
|
||||
// .read(playerMatchingNotifierProvider.notifier) |
|
||||
// .foundUser(myInfo: myInfo); |
|
||||
// }); |
|
||||
// } |
|
||||
// } |
|
||||
|
|
||||
// return Row( |
|
||||
// mainAxisAlignment: MainAxisAlignment.center, |
|
||||
// children: const [ |
|
||||
// CircularProgressIndicator( |
|
||||
// valueColor: AlwaysStoppedAnimation<Color>(Palette.violet), |
|
||||
// ), |
|
||||
// SizedBox(width: 16), |
|
||||
// Text( |
|
||||
// 'Your are in queue ...', |
|
||||
// style: TextStyle( |
|
||||
// fontSize: 24, |
|
||||
// ), |
|
||||
// ), |
|
||||
// ], |
|
||||
// ); |
|
||||
// }); |
|
||||
// } |
|
||||
// } |
|
@ -1,152 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart'; |
|
||||
|
|
||||
class TopBar extends ConsumerWidget { |
|
||||
const TopBar({ |
|
||||
required Color color, |
|
||||
required int puzzleSize, |
|
||||
this.padding = const EdgeInsets.fromLTRB(24.0, 16.0, 24.0, 16.0), |
|
||||
this.tileGap = 16, |
|
||||
this.isCentered = false, |
|
||||
Key? key, |
|
||||
}) : _color = color, |
|
||||
_puzzleSize = puzzleSize, |
|
||||
super(key: key); |
|
||||
|
|
||||
final Color _color; |
|
||||
final int _puzzleSize; |
|
||||
final EdgeInsets padding; |
|
||||
final double tileGap; |
|
||||
final bool isCentered; |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context, WidgetRef ref) { |
|
||||
return Container( |
|
||||
color: _color, |
|
||||
child: Padding( |
|
||||
padding: padding, |
|
||||
child: Row( |
|
||||
mainAxisAlignment: MainAxisAlignment.center, |
|
||||
children: [ |
|
||||
isCentered ? const SizedBox() : const Spacer(), |
|
||||
// TextButton( |
|
||||
// style: _puzzleType == 'Normal' |
|
||||
// ? ButtonStyle( |
|
||||
// foregroundColor: MaterialStateProperty.resolveWith<Color>( |
|
||||
// (Set<MaterialState> states) { |
|
||||
// return Palette.blue; |
|
||||
// }, |
|
||||
// ), |
|
||||
// ) |
|
||||
// : null, |
|
||||
// onPressed: _puzzleType == 'Normal' |
|
||||
// ? null |
|
||||
// : () { |
|
||||
// ref.read(puzzleTypeNotifierProvider.notifier).changeToNormal(); |
|
||||
// }, |
|
||||
// child: Padding( |
|
||||
// padding: const EdgeInsets.all(8.0), |
|
||||
// child: Row( |
|
||||
// children: [ |
|
||||
// Opacity( |
|
||||
// opacity: _puzzleType == 'Normal' ? 1 : 0.5, |
|
||||
// child: const FaIcon(FontAwesomeIcons.rocket), |
|
||||
// ), |
|
||||
// const SizedBox(width: 8), |
|
||||
// Text( |
|
||||
// 'Normal', |
|
||||
// style: TextStyle( |
|
||||
// fontSize: 16, |
|
||||
// color: Colors.white.withOpacity(_puzzleType == 'Normal' ? 1 : 0.5), |
|
||||
// ), |
|
||||
// ), |
|
||||
// ], |
|
||||
// ), |
|
||||
// ), |
|
||||
// ), |
|
||||
// SizedBox(width: tileGap), |
|
||||
// TextButton( |
|
||||
// style: _puzzleType == 'Photo' |
|
||||
// ? ButtonStyle( |
|
||||
// foregroundColor: MaterialStateProperty.resolveWith<Color>( |
|
||||
// (Set<MaterialState> states) { |
|
||||
// return Theme.of(context).colorScheme.primary; |
|
||||
// }, |
|
||||
// ), |
|
||||
// ) |
|
||||
// : null, |
|
||||
// onPressed: _puzzleType == 'Photo' |
|
||||
// ? null |
|
||||
// : () { |
|
||||
// final state = ref.read(imageSplitterNotifierProvider); |
|
||||
// if (state is! ImageSplitterComplete) { |
|
||||
// ref.read(imageSplitterNotifierProvider.notifier).getInitialImages(puzzleSize: _puzzleSize); |
|
||||
// } |
|
||||
// |
|
||||
// ref.read(puzzleTypeNotifierProvider.notifier).changeToPhoto(); |
|
||||
// }, |
|
||||
// child: Padding( |
|
||||
// padding: const EdgeInsets.all(8.0), |
|
||||
// child: Row( |
|
||||
// children: [ |
|
||||
// Opacity( |
|
||||
// opacity: _puzzleType == 'Photo' ? 1 : 0.5, |
|
||||
// child: const FaIcon(FontAwesomeIcons.image), |
|
||||
// ), |
|
||||
// const SizedBox(width: 8), |
|
||||
// Text( |
|
||||
// 'Photo', |
|
||||
// style: TextStyle( |
|
||||
// fontSize: 16, |
|
||||
// color: Colors.white.withOpacity(_puzzleType == 'Photo' ? 1 : 0.5), |
|
||||
// ), |
|
||||
// ), |
|
||||
// ], |
|
||||
// ), |
|
||||
// ), |
|
||||
// ), |
|
||||
// SizedBox(width: tileGap), |
|
||||
// TextButton( |
|
||||
// style: _puzzleType == 'Multiplayer' |
|
||||
// ? ButtonStyle( |
|
||||
// foregroundColor: MaterialStateProperty.resolveWith<Color>( |
|
||||
// (Set<MaterialState> states) { |
|
||||
// return Palette.blue; |
|
||||
// }, |
|
||||
// ), |
|
||||
// ) |
|
||||
// : null, |
|
||||
// onPressed: _puzzleType == 'Multiplayer' |
|
||||
// ? null |
|
||||
// : () { |
|
||||
// // ref.read(puzzleTypeNotifierProvider.notifier).dispose(); |
|
||||
// |
|
||||
// ref.read(puzzleTypeNotifierProvider.notifier).changeToMultiplayer(); |
|
||||
// ref.read(emailAuthNotificationProvider.notifier).checkForSignedUser(); |
|
||||
// }, |
|
||||
// child: Padding( |
|
||||
// padding: const EdgeInsets.all(8.0), |
|
||||
// child: Row( |
|
||||
// children: [ |
|
||||
// Opacity( |
|
||||
// opacity: _puzzleType == 'Multiplayer' ? 1 : 0.5, |
|
||||
// child: const FaIcon(FontAwesomeIcons.gamepad), |
|
||||
// ), |
|
||||
// const SizedBox(width: 8), |
|
||||
// Text( |
|
||||
// 'Multiplayer', |
|
||||
// style: TextStyle( |
|
||||
// fontSize: 16, |
|
||||
// color: Colors.white.withOpacity(_puzzleType == 'Multiplayer' ? 1 : 0.5), |
|
||||
// ), |
|
||||
// ), |
|
||||
// ], |
|
||||
// ), |
|
||||
// ), |
|
||||
// ), |
|
||||
], |
|
||||
), |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,220 +0,0 @@ |
|||||
import 'dart:developer'; |
|
||||
|
|
||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:my_flutter_puzzle/models/user_info.dart'; |
|
||||
import 'package:my_flutter_puzzle/widgets/puzzle_widgets/puzzle_widgets.dart'; |
|
||||
|
|
||||
class PuzzleScreen extends StatefulWidget { |
|
||||
const PuzzleScreen({ |
|
||||
Key? key, |
|
||||
required this.initialList, |
|
||||
required this.id, |
|
||||
required this.myInfo, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
final List<int> initialList; |
|
||||
final String id; |
|
||||
final UserData myInfo; |
|
||||
|
|
||||
@override |
|
||||
_PuzzleScreenState createState() => _PuzzleScreenState(); |
|
||||
} |
|
||||
|
|
||||
class _PuzzleScreenState extends State<PuzzleScreen> { |
|
||||
late final List<int> myList; |
|
||||
late final List<int> opponentList; |
|
||||
int _moves = 0; |
|
||||
|
|
||||
onClick(index) { |
|
||||
log('-----------------------'); |
|
||||
log('Tapped index: $index'); |
|
||||
|
|
||||
int emptyTilePosIndex = myList.indexOf(0); |
|
||||
int emptyTilePosRow = emptyTilePosIndex ~/ 4; |
|
||||
int emptyTilePosCol = emptyTilePosIndex % 4; |
|
||||
|
|
||||
int currentTileRow = index ~/ 4; |
|
||||
int currentTileCol = index % 4; |
|
||||
|
|
||||
//current element moves up |
|
||||
|
|
||||
if ((currentTileRow - 1 == emptyTilePosRow) && (currentTileCol == emptyTilePosCol)) { |
|
||||
setState(() { |
|
||||
myList[emptyTilePosIndex] = myList[index]; |
|
||||
myList[index] = 0; |
|
||||
_moves++; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//current element moves down |
|
||||
|
|
||||
else if ((currentTileRow + 1 == emptyTilePosRow) && (currentTileCol == emptyTilePosCol)) { |
|
||||
setState(() { |
|
||||
myList[emptyTilePosIndex] = myList[index]; |
|
||||
myList[index] = 0; |
|
||||
_moves++; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//current element moves left |
|
||||
|
|
||||
else if ((currentTileRow == emptyTilePosRow) && (currentTileCol + 1 == emptyTilePosCol)) { |
|
||||
setState(() { |
|
||||
myList[emptyTilePosIndex] = myList[index]; |
|
||||
myList[index] = 0; |
|
||||
_moves++; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//current element moves right |
|
||||
|
|
||||
else if ((currentTileRow == emptyTilePosRow) && (currentTileCol - 1 == emptyTilePosCol)) { |
|
||||
setState(() { |
|
||||
myList[emptyTilePosIndex] = myList[index]; |
|
||||
myList[index] = 0; |
|
||||
_moves++; |
|
||||
}); |
|
||||
} else { |
|
||||
if (currentTileCol == emptyTilePosCol) { |
|
||||
int low; |
|
||||
int high; |
|
||||
|
|
||||
// multiple elements move up |
|
||||
|
|
||||
if (emptyTilePosRow < currentTileRow) { |
|
||||
low = emptyTilePosRow; |
|
||||
high = currentTileRow; |
|
||||
|
|
||||
int i = low; |
|
||||
while (i < high) { |
|
||||
setState(() { |
|
||||
myList[(i * 4) + emptyTilePosCol] = myList[(((i + 1) * 4) + emptyTilePosCol)]; |
|
||||
}); |
|
||||
|
|
||||
i += 1; |
|
||||
} |
|
||||
setState(() { |
|
||||
myList[(high * 4) + emptyTilePosCol] = 0; |
|
||||
_moves++; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//multiple elements move down |
|
||||
|
|
||||
else { |
|
||||
low = emptyTilePosRow; |
|
||||
high = currentTileRow; |
|
||||
|
|
||||
int i = low; |
|
||||
while (i > high) { |
|
||||
setState(() { |
|
||||
myList[(i * 4) + emptyTilePosCol] = myList[(((i - 1) * 4) + emptyTilePosCol)]; |
|
||||
}); |
|
||||
|
|
||||
i -= 1; |
|
||||
} |
|
||||
setState(() { |
|
||||
myList[(high * 4) + emptyTilePosCol] = 0; |
|
||||
_moves++; |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// multiple elements move left |
|
||||
|
|
||||
// multiple elements move right |
|
||||
|
|
||||
if (currentTileRow == emptyTilePosRow) { |
|
||||
int low; |
|
||||
int high; |
|
||||
|
|
||||
// multiple elements move left |
|
||||
|
|
||||
if (emptyTilePosCol < currentTileCol) { |
|
||||
low = emptyTilePosCol; |
|
||||
high = currentTileCol; |
|
||||
|
|
||||
int i = low; |
|
||||
while (i < high) { |
|
||||
setState(() { |
|
||||
myList[(emptyTilePosRow * 4) + i] = myList[(emptyTilePosRow * 4) + (i + 1)]; |
|
||||
}); |
|
||||
|
|
||||
i += 1; |
|
||||
} |
|
||||
setState(() { |
|
||||
myList[high + (emptyTilePosRow * 4)] = 0; |
|
||||
_moves++; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//multiple elements move right |
|
||||
|
|
||||
else { |
|
||||
low = emptyTilePosCol; |
|
||||
high = currentTileCol; |
|
||||
|
|
||||
int i = low; |
|
||||
while (i > high) { |
|
||||
setState(() { |
|
||||
myList[(i + (emptyTilePosRow * 4))] = myList[(i - 1) + (emptyTilePosRow * 4)]; |
|
||||
}); |
|
||||
|
|
||||
i -= 1; |
|
||||
} |
|
||||
setState(() { |
|
||||
myList[high + (emptyTilePosRow * 4)] = 0; |
|
||||
_moves++; |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// _databaseClient.updateGameState( |
|
||||
// id: widget.id, |
|
||||
// mydata: widget.myInfo, |
|
||||
// numberList: myList, |
|
||||
// moves: _moves, |
|
||||
// ); |
|
||||
|
|
||||
log('List: $myList'); |
|
||||
log('-----------------------'); |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
void initState() { |
|
||||
super.initState(); |
|
||||
myList = widget.initialList; |
|
||||
opponentList = widget.initialList; |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
return Scaffold( |
|
||||
backgroundColor: Colors.white, |
|
||||
body: Row( |
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, |
|
||||
children: [ |
|
||||
// PLAYER 1 puzzle --> my (own) |
|
||||
Column( |
|
||||
children: [ |
|
||||
const PlayerText( |
|
||||
displayName: 'PLAYER 1', |
|
||||
), |
|
||||
// TODO: Change font size |
|
||||
MovesText( |
|
||||
moves: _moves, |
|
||||
fontSize: 60, |
|
||||
), |
|
||||
], |
|
||||
), |
|
||||
Container( |
|
||||
height: MediaQuery.of(context).size.height * 0.6, |
|
||||
width: 2, |
|
||||
color: Colors.black, |
|
||||
), |
|
||||
], |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,489 +0,0 @@ |
|||||
import 'dart:developer'; |
|
||||
|
|
||||
import 'package:flutter/foundation.dart'; |
|
||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:my_flutter_puzzle/res/palette.dart'; |
|
||||
import 'package:my_flutter_puzzle/utils/puzzle_solver.dart'; |
|
||||
import 'package:my_flutter_puzzle/widgets/puzzle_widgets/puzzle_widgets.dart'; |
|
||||
|
|
||||
class PuzzleSoloScreen extends StatefulWidget { |
|
||||
const PuzzleSoloScreen({ |
|
||||
Key? key, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
@override |
|
||||
_PuzzleSoloScreenState createState() => _PuzzleSoloScreenState(); |
|
||||
} |
|
||||
|
|
||||
class _PuzzleSoloScreenState extends State<PuzzleSoloScreen> { |
|
||||
late final PuzzleSolverClient _solverClient; |
|
||||
|
|
||||
List<List<int>>? _board2D; |
|
||||
List<int>? myList; |
|
||||
int _moves = 0; |
|
||||
final _puzzleSize = 3; |
|
||||
final int _animationSpeedInMilliseconds = 300; |
|
||||
bool _isComputing = false; |
|
||||
bool _isAutoSolving = false; |
|
||||
bool _isSolved = false; |
|
||||
|
|
||||
Map<int, FractionalOffset>? _offsetMap; |
|
||||
List<int> _solvedList = []; |
|
||||
|
|
||||
@override |
|
||||
void initState() { |
|
||||
super.initState(); |
|
||||
_solverClient = PuzzleSolverClient(size: _puzzleSize); |
|
||||
initBoard(); |
|
||||
generateSolvedList(); |
|
||||
} |
|
||||
|
|
||||
generateSolvedList() { |
|
||||
for (int i = 1; i < _puzzleSize * _puzzleSize; i++) { |
|
||||
_solvedList.add(i); |
|
||||
} |
|
||||
_solvedList.add(0); |
|
||||
} |
|
||||
|
|
||||
scrambleBoard() { |
|
||||
final generated2DBoard = _solverClient.createRandomBoard(); |
|
||||
final generated1DBoard = _solverClient.convertTo1D(generated2DBoard); |
|
||||
updateOffset(generated1DBoard); |
|
||||
setState(() { |
|
||||
_board2D = generated2DBoard; |
|
||||
myList = generated1DBoard; |
|
||||
_moves = 0; |
|
||||
_isSolved = false; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
initBoard() { |
|
||||
final generated2DBoard = _solverClient.createRandomBoard(); |
|
||||
final generated1DBoard = _solverClient.convertTo1D(generated2DBoard); |
|
||||
|
|
||||
createOffset(generated1DBoard); |
|
||||
setState(() { |
|
||||
_board2D = generated2DBoard; |
|
||||
myList = generated1DBoard; |
|
||||
|
|
||||
_moves = 0; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
startAutoSolver() async { |
|
||||
if (_board2D != null) { |
|
||||
setState(() { |
|
||||
_isComputing = true; |
|
||||
}); |
|
||||
|
|
||||
List<List<int>>? boardStates = await compute(_solverClient.runner, _solverClient.convertTo2D(myList!)); |
|
||||
|
|
||||
setState(() { |
|
||||
_isComputing = false; |
|
||||
_isAutoSolving = true; |
|
||||
}); |
|
||||
|
|
||||
if (boardStates != null) { |
|
||||
for (var board in boardStates) { |
|
||||
await Future.delayed(Duration( |
|
||||
milliseconds: _animationSpeedInMilliseconds, |
|
||||
)); |
|
||||
setState(() { |
|
||||
myList = board; |
|
||||
_moves++; |
|
||||
}); |
|
||||
updateOffset(myList!); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
setState(() { |
|
||||
_isAutoSolving = false; |
|
||||
_isSolved = true; |
|
||||
}); |
|
||||
showCompleteDialogBox(context); |
|
||||
} |
|
||||
|
|
||||
isSolved(List<int> currentBoard) { |
|
||||
if (listEquals(currentBoard, _solvedList)) { |
|
||||
setState(() { |
|
||||
_isSolved = true; |
|
||||
}); |
|
||||
return true; |
|
||||
} |
|
||||
setState(() { |
|
||||
_isSolved = false; |
|
||||
}); |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
onClick(index) { |
|
||||
log('-----------------------'); |
|
||||
log('Tapped index: $index'); |
|
||||
|
|
||||
if (myList != null) { |
|
||||
int emptyTilePosIndex = myList!.indexOf(0); |
|
||||
int emptyTilePosRow = emptyTilePosIndex ~/ _puzzleSize; |
|
||||
int emptyTilePosCol = emptyTilePosIndex % _puzzleSize; |
|
||||
|
|
||||
int currentTileRow = index ~/ _puzzleSize; |
|
||||
int currentTileCol = index % _puzzleSize; |
|
||||
|
|
||||
//current element moves up |
|
||||
if ((currentTileRow - 1 == emptyTilePosRow) && (currentTileCol == emptyTilePosCol)) { |
|
||||
myList![emptyTilePosIndex] = myList![index]; |
|
||||
myList![index] = 0; |
|
||||
_moves++; |
|
||||
} |
|
||||
|
|
||||
//current element moves down |
|
||||
else if ((currentTileRow + 1 == emptyTilePosRow) && (currentTileCol == emptyTilePosCol)) { |
|
||||
myList![emptyTilePosIndex] = myList![index]; |
|
||||
myList![index] = 0; |
|
||||
_moves++; |
|
||||
} |
|
||||
|
|
||||
//current element moves left |
|
||||
else if ((currentTileRow == emptyTilePosRow) && (currentTileCol + 1 == emptyTilePosCol)) { |
|
||||
myList![emptyTilePosIndex] = myList![index]; |
|
||||
myList![index] = 0; |
|
||||
_moves++; |
|
||||
} |
|
||||
|
|
||||
//current element moves right |
|
||||
else if ((currentTileRow == emptyTilePosRow) && (currentTileCol - 1 == emptyTilePosCol)) { |
|
||||
myList![emptyTilePosIndex] = myList![index]; |
|
||||
myList![index] = 0; |
|
||||
_moves++; |
|
||||
} else { |
|
||||
if (currentTileCol == emptyTilePosCol) { |
|
||||
int low; |
|
||||
int high; |
|
||||
|
|
||||
// multiple elements move up |
|
||||
if (emptyTilePosRow < currentTileRow) { |
|
||||
low = emptyTilePosRow; |
|
||||
high = currentTileRow; |
|
||||
|
|
||||
int i = low; |
|
||||
while (i < high) { |
|
||||
myList![(i * _puzzleSize) + emptyTilePosCol] = myList![(((i + 1) * _puzzleSize) + emptyTilePosCol)]; |
|
||||
|
|
||||
i += 1; |
|
||||
} |
|
||||
|
|
||||
myList![(high * _puzzleSize) + emptyTilePosCol] = 0; |
|
||||
_moves++; |
|
||||
} |
|
||||
|
|
||||
//multiple elements move down |
|
||||
else { |
|
||||
low = emptyTilePosRow; |
|
||||
high = currentTileRow; |
|
||||
|
|
||||
int i = low; |
|
||||
while (i > high) { |
|
||||
myList![(i * _puzzleSize) + emptyTilePosCol] = myList![(((i - 1) * _puzzleSize) + emptyTilePosCol)]; |
|
||||
|
|
||||
i -= 1; |
|
||||
} |
|
||||
|
|
||||
myList![(high * _puzzleSize) + emptyTilePosCol] = 0; |
|
||||
_moves++; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// multiple elements move left or right |
|
||||
if (currentTileRow == emptyTilePosRow) { |
|
||||
int low; |
|
||||
int high; |
|
||||
|
|
||||
// multiple elements move left |
|
||||
if (emptyTilePosCol < currentTileCol) { |
|
||||
low = emptyTilePosCol; |
|
||||
high = currentTileCol; |
|
||||
|
|
||||
int i = low; |
|
||||
while (i < high) { |
|
||||
myList![(emptyTilePosRow * _puzzleSize) + i] = myList![(emptyTilePosRow * _puzzleSize) + (i + 1)]; |
|
||||
|
|
||||
i += 1; |
|
||||
} |
|
||||
|
|
||||
myList![high + (emptyTilePosRow * _puzzleSize)] = 0; |
|
||||
_moves++; |
|
||||
} |
|
||||
|
|
||||
//multiple elements move right |
|
||||
else { |
|
||||
low = emptyTilePosCol; |
|
||||
high = currentTileCol; |
|
||||
|
|
||||
int i = low; |
|
||||
while (i > high) { |
|
||||
myList![(i + (emptyTilePosRow * _puzzleSize))] = myList![(i - 1) + (emptyTilePosRow * _puzzleSize)]; |
|
||||
|
|
||||
i -= 1; |
|
||||
} |
|
||||
|
|
||||
myList![high + (emptyTilePosRow * _puzzleSize)] = 0; |
|
||||
_moves++; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Update Offset list |
|
||||
// setState(() { |
|
||||
// updateOffset(myList!); |
|
||||
// }); |
|
||||
updateOffset(myList!); |
|
||||
setState(() {}); |
|
||||
|
|
||||
if (isSolved(myList!)) { |
|
||||
showCompleteDialogBox(context); |
|
||||
} |
|
||||
|
|
||||
log('List: $myList'); |
|
||||
log('-----------------------'); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
createOffset(List<int> board) { |
|
||||
Map<int, FractionalOffset> offsetMap = {}; |
|
||||
int j = 0; |
|
||||
|
|
||||
log('BOARD: $board'); |
|
||||
|
|
||||
for (int i = 0; i < board.length; i++) { |
|
||||
final xMod = i % _puzzleSize; |
|
||||
double x = xMod / (_puzzleSize - 1); |
|
||||
|
|
||||
if (x % i == 0 && i != 0) j++; |
|
||||
int yMod = j % _puzzleSize; |
|
||||
double y = yMod / (_puzzleSize - 1); |
|
||||
|
|
||||
offsetMap.addEntries([ |
|
||||
MapEntry<int, FractionalOffset>( |
|
||||
board[i], |
|
||||
FractionalOffset(x, y), |
|
||||
) |
|
||||
]); |
|
||||
} |
|
||||
|
|
||||
log('INITIAL OFFSET MAP: $offsetMap'); |
|
||||
setState(() { |
|
||||
_offsetMap = offsetMap; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
updateOffset(List<int> board) { |
|
||||
int j = 0; |
|
||||
|
|
||||
for (int i = 0; i < board.length; i++) { |
|
||||
final xMod = i % _puzzleSize; |
|
||||
double x = xMod / (_puzzleSize - 1); |
|
||||
|
|
||||
if (x % i == 0 && i != 0) j++; |
|
||||
int yMod = j % _puzzleSize; |
|
||||
double y = yMod / (_puzzleSize - 1); |
|
||||
|
|
||||
_offsetMap![board[i]] = FractionalOffset(x, y); |
|
||||
} |
|
||||
log('OFFSET MAP: $_offsetMap'); |
|
||||
} |
|
||||
|
|
||||
showCompleteDialogBox(BuildContext context) { |
|
||||
showDialog( |
|
||||
context: context, |
|
||||
builder: (context) => Dialog( |
|
||||
child: Padding( |
|
||||
padding: const EdgeInsets.all(24.0), |
|
||||
child: Column( |
|
||||
mainAxisSize: MainAxisSize.min, |
|
||||
children: [ |
|
||||
const Text( |
|
||||
'Solved successfully!', |
|
||||
style: TextStyle(fontSize: 22), |
|
||||
), |
|
||||
const SizedBox(height: 16), |
|
||||
ElevatedButton( |
|
||||
style: ElevatedButton.styleFrom( |
|
||||
primary: Palette.violet, |
|
||||
onSurface: Palette.violet, |
|
||||
shape: RoundedRectangleBorder( |
|
||||
borderRadius: BorderRadius.circular(50), |
|
||||
), |
|
||||
), |
|
||||
onPressed: () { |
|
||||
Navigator.of(context).pop(); |
|
||||
}, |
|
||||
child: const Padding( |
|
||||
padding: EdgeInsets.all(16.0), |
|
||||
child: Text( |
|
||||
'OK', |
|
||||
style: TextStyle(fontSize: 22), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
], |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
var screenSize = MediaQuery.of(context).size; |
|
||||
|
|
||||
var boardSize = screenSize.height * 0.6; |
|
||||
|
|
||||
var spacing = 4; |
|
||||
var eachBoxSize = (boardSize / _puzzleSize) - (spacing * (_puzzleSize - 1)); |
|
||||
|
|
||||
return Scaffold( |
|
||||
backgroundColor: Colors.white, |
|
||||
body: myList != null && _offsetMap != null |
|
||||
? Column( |
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, |
|
||||
children: [ |
|
||||
Row(), |
|
||||
MovesText( |
|
||||
moves: _moves, |
|
||||
fontSize: 60, |
|
||||
), |
|
||||
SizedBox( |
|
||||
height: boardSize, |
|
||||
width: boardSize, |
|
||||
child: Stack( |
|
||||
children: [ |
|
||||
for (int i = 0; i < _offsetMap!.length; i++) |
|
||||
_offsetMap!.entries.toList()[i].key != 0 |
|
||||
? AnimatedAlign( |
|
||||
alignment: _offsetMap!.entries.toList()[i].value, |
|
||||
duration: Duration( |
|
||||
milliseconds: _animationSpeedInMilliseconds, |
|
||||
), |
|
||||
curve: Curves.easeInOut, |
|
||||
child: GestureDetector( |
|
||||
onTap: () => onClick(myList!.indexOf(_offsetMap!.entries.toList()[i].key)), |
|
||||
child: Card( |
|
||||
elevation: 4, |
|
||||
color: const Color(0xFF2868d7), |
|
||||
shape: RoundedRectangleBorder( |
|
||||
borderRadius: BorderRadius.circular(20), |
|
||||
), |
|
||||
child: SizedBox( |
|
||||
height: eachBoxSize, |
|
||||
width: eachBoxSize, |
|
||||
child: Center( |
|
||||
child: Text( |
|
||||
_offsetMap!.entries.toList()[i].key.toString(), |
|
||||
style: const TextStyle( |
|
||||
fontSize: 60, |
|
||||
fontWeight: FontWeight.bold, |
|
||||
color: Colors.white, |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
) |
|
||||
: const SizedBox(), |
|
||||
], |
|
||||
), |
|
||||
), |
|
||||
// AnimatedGrid( |
|
||||
// puzzleSize: _puzzleSize, |
|
||||
// key: UniqueKey(), |
|
||||
// number: myList!, |
|
||||
// offsetList: _offsetList!, |
|
||||
// onTap: onClick, |
|
||||
// color: const Color(0xFF2868d7), |
|
||||
// ), |
|
||||
const SizedBox(height: 30), |
|
||||
Row( |
|
||||
mainAxisSize: MainAxisSize.min, |
|
||||
children: [ |
|
||||
Padding( |
|
||||
padding: const EdgeInsets.only(bottom: 30.0), |
|
||||
child: SizedBox( |
|
||||
width: MediaQuery.of(context).size.width * 0.2, |
|
||||
child: ElevatedButton( |
|
||||
style: ElevatedButton.styleFrom( |
|
||||
primary: Palette.violet, |
|
||||
onSurface: Palette.violet, |
|
||||
shape: RoundedRectangleBorder( |
|
||||
borderRadius: BorderRadius.circular(50), |
|
||||
), |
|
||||
), |
|
||||
onPressed: _isComputing || _isAutoSolving || _isSolved |
|
||||
? null |
|
||||
: () { |
|
||||
startAutoSolver(); |
|
||||
}, |
|
||||
child: Padding( |
|
||||
padding: const EdgeInsets.all(16.0), |
|
||||
child: _isComputing || _isAutoSolving |
|
||||
? Row( |
|
||||
children: [ |
|
||||
const SizedBox( |
|
||||
width: 25, |
|
||||
height: 25, |
|
||||
child: CircularProgressIndicator( |
|
||||
color: Palette.violet, |
|
||||
strokeWidth: 2, |
|
||||
), |
|
||||
), |
|
||||
const SizedBox(width: 16), |
|
||||
Text( |
|
||||
_isComputing ? 'Computing ...' : 'Solving ...', |
|
||||
style: const TextStyle(fontSize: 20), |
|
||||
), |
|
||||
], |
|
||||
) |
|
||||
: const Text( |
|
||||
'Start Auto Solver', |
|
||||
style: TextStyle(fontSize: 22), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
const SizedBox(width: 16.0), |
|
||||
Padding( |
|
||||
padding: const EdgeInsets.only(bottom: 30.0), |
|
||||
child: SizedBox( |
|
||||
width: MediaQuery.of(context).size.width * 0.2, |
|
||||
child: ElevatedButton( |
|
||||
style: ElevatedButton.styleFrom( |
|
||||
primary: Palette.crimson, |
|
||||
onSurface: Palette.crimson, |
|
||||
shape: RoundedRectangleBorder( |
|
||||
borderRadius: BorderRadius.circular(50), |
|
||||
), |
|
||||
), |
|
||||
onPressed: _isComputing || _isAutoSolving |
|
||||
? null |
|
||||
: () { |
|
||||
scrambleBoard(); |
|
||||
}, |
|
||||
child: const Padding( |
|
||||
padding: EdgeInsets.all(16.0), |
|
||||
child: Text( |
|
||||
'Scramble', |
|
||||
style: TextStyle(fontSize: 22), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
], |
|
||||
), |
|
||||
], |
|
||||
) |
|
||||
: const SizedBox(), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,43 @@ |
|||||
|
import 'dart:async'; |
||||
|
|
||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_svg/flutter_svg.dart'; |
||||
|
import 'package:my_flutter_puzzle/screens/level_list/screen/level_list_screen.dart'; |
||||
|
import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart'; |
||||
|
|
||||
|
class SplashScreen extends StatefulWidget { |
||||
|
const SplashScreen({Key? key}) : super(key: key); |
||||
|
|
||||
|
@override |
||||
|
State<SplashScreen> createState() => _SplashScreenState(); |
||||
|
} |
||||
|
|
||||
|
class _SplashScreenState extends State<SplashScreen> { |
||||
|
@override |
||||
|
void initState() { |
||||
|
Timer(const Duration(milliseconds: 2000), () { |
||||
|
Navigator.push(context, MaterialPageRoute( |
||||
|
builder: (context) { |
||||
|
return const LevelListScreen(); |
||||
|
}, |
||||
|
)); |
||||
|
}); |
||||
|
super.initState(); |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
return Scaffold( |
||||
|
backgroundColor: const Color(0xff6236FF), |
||||
|
body: Center( |
||||
|
child: Container( |
||||
|
decoration: BoxDecoration( |
||||
|
image: DecorationImage( |
||||
|
image: AssetImage('splash_screen_image'.pngPath), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
|
||||
|
extension ContextExtentions on BuildContext { |
||||
|
double get height { |
||||
|
return MediaQuery.of(this).size.height; |
||||
|
} |
||||
|
|
||||
|
double get width { |
||||
|
return MediaQuery.of(this).size.width; |
||||
|
} |
||||
|
|
||||
|
double get horizontallyMargin { |
||||
|
return MediaQuery.of(this).size.width * 0.05; |
||||
|
} |
||||
|
|
||||
|
double get verticallyMargin { |
||||
|
return MediaQuery.of(this).size.height * 0.025; |
||||
|
} |
||||
|
} |
@ -1,308 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
|
|
||||
class AnimatedGrid extends StatefulWidget { |
|
||||
const AnimatedGrid({ |
|
||||
Key? key, |
|
||||
required this.number, |
|
||||
required this.offsetList, |
|
||||
required this.onTap, |
|
||||
required this.color, |
|
||||
required this.puzzleSize, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
final Function onTap; |
|
||||
final List<int> number; |
|
||||
final List<FractionalOffset> offsetList; |
|
||||
final Color color; |
|
||||
final int puzzleSize; |
|
||||
|
|
||||
@override |
|
||||
State<AnimatedGrid> createState() => _AnimatedGridState(); |
|
||||
} |
|
||||
|
|
||||
class _AnimatedGridState extends State<AnimatedGrid> { |
|
||||
late List<FractionalOffset> _offsetList; |
|
||||
|
|
||||
@override |
|
||||
void initState() { |
|
||||
_offsetList = widget.offsetList; |
|
||||
super.initState(); |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
var screenSize = MediaQuery.of(context).size; |
|
||||
var boardSize = screenSize.width * 0.4; |
|
||||
|
|
||||
var spacing = 4; |
|
||||
var eachBoxSize = |
|
||||
(boardSize / widget.puzzleSize) - (spacing * (widget.puzzleSize - 1)); |
|
||||
|
|
||||
return SizedBox( |
|
||||
height: boardSize, |
|
||||
width: boardSize, |
|
||||
child: Stack( |
|
||||
children: [ |
|
||||
for (int i = 0; i < widget.offsetList.length; i++) |
|
||||
widget.number[i] != 0 |
|
||||
? AnimatedAlign( |
|
||||
alignment: widget.offsetList[i], |
|
||||
duration: const Duration(seconds: 1), |
|
||||
curve: Curves.easeInOut, |
|
||||
child: GestureDetector( |
|
||||
onTap: () => widget.onTap(i), |
|
||||
child: Card( |
|
||||
elevation: 4, |
|
||||
color: widget.color, |
|
||||
shape: RoundedRectangleBorder( |
|
||||
borderRadius: BorderRadius.circular(20), |
|
||||
), |
|
||||
child: SizedBox( |
|
||||
height: eachBoxSize, |
|
||||
width: eachBoxSize, |
|
||||
child: Center( |
|
||||
child: Text( |
|
||||
widget.number[i].toString(), |
|
||||
style: const TextStyle( |
|
||||
fontSize: 60, |
|
||||
fontWeight: FontWeight.bold, |
|
||||
color: Colors.white, |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
) |
|
||||
: const SizedBox(), |
|
||||
], |
|
||||
), |
|
||||
); |
|
||||
|
|
||||
// ----------------------------- |
|
||||
// Working implementation: |
|
||||
// ----------------------------- |
|
||||
// return SizedBox( |
|
||||
// height: screenSize.height * 0.7, |
|
||||
// width: screenSize.width * 0.4, |
|
||||
// child: GridView.builder( |
|
||||
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( |
|
||||
// crossAxisCount: puzzleSize, |
|
||||
// ), |
|
||||
// itemCount: number.length, |
|
||||
// itemBuilder: (context, index) { |
|
||||
// return number[index] != 0 |
|
||||
// ? Padding( |
|
||||
// padding: const EdgeInsets.all(2.0), |
|
||||
// child: GestureDetector( |
|
||||
// onTap: () => onTap(index), |
|
||||
// child: AnimatedPositioned( |
|
||||
// duration: Duration(milliseconds: 600), |
|
||||
// child: Container( |
|
||||
// height: 20, |
|
||||
// width: 20, |
|
||||
// color: Colors.orange, |
|
||||
// ), |
|
||||
// ), |
|
||||
// ), |
|
||||
// ) |
|
||||
// // ? MouseRegion( |
|
||||
// // child: Padding( |
|
||||
// // padding: const EdgeInsets.all(2.0), |
|
||||
// // child: GestureDetector( |
|
||||
// // onTap: () => onTap(index), |
|
||||
// // child: Card( |
|
||||
// // elevation: 4, |
|
||||
// // color: color, |
|
||||
// // // dark -> 0xFF14407a |
|
||||
// // // light -> 0xFF43b9fd |
|
||||
// // shape: RoundedRectangleBorder( |
|
||||
// // borderRadius: BorderRadius.circular(20), |
|
||||
// // ), |
|
||||
// // child: SizedBox( |
|
||||
// // height: 20, |
|
||||
// // width: 20, |
|
||||
// // child: Center( |
|
||||
// // child: Text( |
|
||||
// // number[index].toString(), |
|
||||
// // style: const TextStyle( |
|
||||
// // fontSize: 60, |
|
||||
// // fontWeight: FontWeight.bold, |
|
||||
// // color: Colors.white, |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // ) |
|
||||
// : const SizedBox(); |
|
||||
// // }, |
|
||||
// // ), |
|
||||
// // ); |
|
||||
// } |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// class AnimatedGrid extends StatefulWidget { |
|
||||
// const AnimatedGrid({ |
|
||||
// Key? key, |
|
||||
// required this.number, |
|
||||
// required this.offsetList, |
|
||||
// required this.onTap, |
|
||||
// required this.color, |
|
||||
// required this.puzzleSize, |
|
||||
// }) : super(key: key); |
|
||||
|
|
||||
// final Function onTap; |
|
||||
// final List<int> number; |
|
||||
// final List<FractionalOffset> offsetList; |
|
||||
// final Color color; |
|
||||
// final int puzzleSize; |
|
||||
|
|
||||
// @override |
|
||||
// State<AnimatedGrid> createState() => _AnimatedGridState(); |
|
||||
// } |
|
||||
|
|
||||
// class _AnimatedGridState extends State<AnimatedGrid> { |
|
||||
// // FractionalOffset offset = FractionalOffset(0, 0); |
|
||||
// late final List<int> _numberList; |
|
||||
// // late final int _puzzleSize; |
|
||||
|
|
||||
// @override |
|
||||
// void initState() { |
|
||||
// _numberList = widget.number; |
|
||||
// // _puzzleSize = widget.puzzleSize; |
|
||||
// // print(_numberList); |
|
||||
// // print(widget.offsetList); |
|
||||
// super.initState(); |
|
||||
// } |
|
||||
|
|
||||
// // calculateOffset() { |
|
||||
// // List<FractionalOffset> offsetList = []; |
|
||||
|
|
||||
// // for (int i = 0; i < _puzzleSize; i++) { |
|
||||
// // int yMod = i % _puzzleSize; |
|
||||
// // double y = yMod / (_puzzleSize - 1); |
|
||||
// // for (int j = 0; j < _puzzleSize; j++) { |
|
||||
// // final xMod = _numberList[i][j] % _puzzleSize; |
|
||||
// // double x = xMod / (_puzzleSize - 1); |
|
||||
// // offsetList.add(FractionalOffset(x, y)); |
|
||||
// // } |
|
||||
// // } |
|
||||
// // } |
|
||||
|
|
||||
// @override |
|
||||
// Widget build(BuildContext context) { |
|
||||
// var screenSize = MediaQuery.of(context).size; |
|
||||
// var boardSize = screenSize.width * 0.4; |
|
||||
|
|
||||
// var spacing = 4; |
|
||||
// var eachBoxSize = |
|
||||
// (boardSize / widget.puzzleSize) - (spacing * (widget.puzzleSize - 1)); |
|
||||
|
|
||||
// return SizedBox( |
|
||||
// height: boardSize, |
|
||||
// width: boardSize, |
|
||||
// child: Stack( |
|
||||
// children: [ |
|
||||
// for (var offset in widget.offsetList) |
|
||||
// AnimatedAlign( |
|
||||
// alignment: offset, |
|
||||
// duration: const Duration(seconds: 1), |
|
||||
// curve: Curves.easeInOut, |
|
||||
// child: Container( |
|
||||
// height: eachBoxSize, |
|
||||
// width: eachBoxSize, |
|
||||
// color: Colors.black, |
|
||||
// ), |
|
||||
// ), |
|
||||
// // AnimatedAlign( |
|
||||
// // alignment: FractionalOffset(1, 0), |
|
||||
// // duration: Duration(seconds: 1), |
|
||||
// // curve: Curves.easeInOut, |
|
||||
// // child: Container( |
|
||||
// // height: eachBoxSize, |
|
||||
// // width: eachBoxSize, |
|
||||
// // color: Colors.black, |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // AnimatedAlign( |
|
||||
// // alignment: FractionalOffset(0.5, 1), |
|
||||
// // duration: Duration(seconds: 1), |
|
||||
// // curve: Curves.easeInOut, |
|
||||
// // child: Container( |
|
||||
// // height: eachBoxSize, |
|
||||
// // width: eachBoxSize, |
|
||||
// // color: Colors.black, |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// ], |
|
||||
// ), |
|
||||
// ); |
|
||||
|
|
||||
// // ----------------------------- |
|
||||
// // Working implementation: |
|
||||
// // ----------------------------- |
|
||||
// // return SizedBox( |
|
||||
// // height: screenSize.height * 0.7, |
|
||||
// // width: screenSize.width * 0.4, |
|
||||
// // child: GridView.builder( |
|
||||
// // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( |
|
||||
// // crossAxisCount: puzzleSize, |
|
||||
// // ), |
|
||||
// // itemCount: number.length, |
|
||||
// // itemBuilder: (context, index) { |
|
||||
// // return number[index] != 0 |
|
||||
// // ? Padding( |
|
||||
// // padding: const EdgeInsets.all(2.0), |
|
||||
// // child: GestureDetector( |
|
||||
// // onTap: () => onTap(index), |
|
||||
// // child: AnimatedPositioned( |
|
||||
// // duration: Duration(milliseconds: 600), |
|
||||
// // child: Container( |
|
||||
// // height: 20, |
|
||||
// // width: 20, |
|
||||
// // color: Colors.orange, |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // ), |
|
||||
// // ) |
|
||||
// // // ? MouseRegion( |
|
||||
// // // child: Padding( |
|
||||
// // // padding: const EdgeInsets.all(2.0), |
|
||||
// // // child: GestureDetector( |
|
||||
// // // onTap: () => onTap(index), |
|
||||
// // // child: Card( |
|
||||
// // // elevation: 4, |
|
||||
// // // color: color, |
|
||||
// // // // dark -> 0xFF14407a |
|
||||
// // // // light -> 0xFF43b9fd |
|
||||
// // // shape: RoundedRectangleBorder( |
|
||||
// // // borderRadius: BorderRadius.circular(20), |
|
||||
// // // ), |
|
||||
// // // child: SizedBox( |
|
||||
// // // height: 20, |
|
||||
// // // width: 20, |
|
||||
// // // child: Center( |
|
||||
// // // child: Text( |
|
||||
// // // number[index].toString(), |
|
||||
// // // style: const TextStyle( |
|
||||
// // // fontSize: 60, |
|
||||
// // // fontWeight: FontWeight.bold, |
|
||||
// // // color: Colors.white, |
|
||||
// // // ), |
|
||||
// // // ), |
|
||||
// // // ), |
|
||||
// // // ), |
|
||||
// // // ), |
|
||||
// // // ), |
|
||||
// // // ), |
|
||||
// // // ) |
|
||||
// // : const SizedBox(); |
|
||||
// // }, |
|
||||
// // ), |
|
||||
// // ); |
|
||||
// } |
|
||||
// } |
|
@ -1,67 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
|
|
||||
class Grid extends StatelessWidget { |
|
||||
const Grid({ |
|
||||
Key? key, |
|
||||
required this.number, |
|
||||
required this.onTap, |
|
||||
required this.color, |
|
||||
required this.puzzleSize, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
final Function onTap; |
|
||||
final List<dynamic> number; |
|
||||
final Color color; |
|
||||
final int puzzleSize; |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
var screenSize = MediaQuery.of(context).size; |
|
||||
|
|
||||
return SizedBox( |
|
||||
height: screenSize.height * 0.7, |
|
||||
width: screenSize.width * 0.4, |
|
||||
child: GridView.builder( |
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( |
|
||||
crossAxisCount: puzzleSize, |
|
||||
), |
|
||||
itemCount: number.length, |
|
||||
itemBuilder: (context, index) { |
|
||||
return number[index] != 0 |
|
||||
? MouseRegion( |
|
||||
child: Padding( |
|
||||
padding: const EdgeInsets.all(2.0), |
|
||||
child: GestureDetector( |
|
||||
onTap: () => onTap(index), |
|
||||
child: Card( |
|
||||
elevation: 4, |
|
||||
color: color, |
|
||||
// dark -> 0xFF14407a |
|
||||
// light -> 0xFF43b9fd |
|
||||
shape: RoundedRectangleBorder( |
|
||||
borderRadius: BorderRadius.circular(20), |
|
||||
), |
|
||||
child: SizedBox( |
|
||||
height: 20, |
|
||||
width: 20, |
|
||||
child: Center( |
|
||||
child: Text( |
|
||||
number[index].toString(), |
|
||||
style: const TextStyle( |
|
||||
fontSize: 60, |
|
||||
fontWeight: FontWeight.bold, |
|
||||
color: Colors.white, |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
) |
|
||||
: const SizedBox(); |
|
||||
}, |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,62 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:my_flutter_puzzle/res/palette.dart'; |
|
||||
|
|
||||
class NameField extends StatefulWidget { |
|
||||
final FocusNode focusNode; |
|
||||
final Function(String) onChange; |
|
||||
|
|
||||
const NameField({ |
|
||||
Key? key, |
|
||||
required this.focusNode, |
|
||||
required this.onChange, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
@override |
|
||||
State<NameField> createState() => _NameFieldState(); |
|
||||
} |
|
||||
|
|
||||
class _NameFieldState extends State<NameField> { |
|
||||
late final TextEditingController _nameTextController; |
|
||||
late final FocusNode _nameFocusNode; |
|
||||
|
|
||||
@override |
|
||||
void initState() { |
|
||||
super.initState(); |
|
||||
_nameTextController = TextEditingController(); |
|
||||
_nameFocusNode = widget.focusNode; |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
return TextField( |
|
||||
controller: _nameTextController, |
|
||||
focusNode: _nameFocusNode, |
|
||||
style: const TextStyle( |
|
||||
fontSize: 24, |
|
||||
color: Palette.crimson, |
|
||||
), |
|
||||
cursorColor: Palette.violet, |
|
||||
decoration: InputDecoration( |
|
||||
border: const UnderlineInputBorder(), |
|
||||
focusedBorder: const UnderlineInputBorder( |
|
||||
borderSide: BorderSide( |
|
||||
color: Palette.violet, |
|
||||
width: 3, |
|
||||
), |
|
||||
), |
|
||||
enabledBorder: UnderlineInputBorder( |
|
||||
borderSide: BorderSide( |
|
||||
color: Palette.violet.withOpacity(0.5), |
|
||||
width: 2, |
|
||||
), |
|
||||
), |
|
||||
hintText: 'Enter your name', |
|
||||
hintStyle: TextStyle( |
|
||||
fontSize: 22, |
|
||||
color: Palette.violet.withOpacity(0.2), |
|
||||
), |
|
||||
), |
|
||||
onChanged: (value) => widget.onChange(value), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,72 +0,0 @@ |
|||||
// import 'package:flutter/material.dart'; |
|
||||
// import 'package:flutter_riverpod/flutter_riverpod.dart'; |
|
||||
// import 'package:my_flutter_puzzle/application/states/anonymous_auth_state.dart'; |
|
||||
// import 'package:my_flutter_puzzle/providers.dart'; |
|
||||
// import 'package:my_flutter_puzzle/res/palette.dart'; |
|
||||
// import 'package:my_flutter_puzzle/screens/menu_screen.dart'; |
|
||||
// import 'package:my_flutter_puzzle/screens/puzzle_screen.dart'; |
|
||||
// import 'package:my_flutter_puzzle/widgets/login_widgets/start_game_widget/start_game_button.dart'; |
|
||||
|
|
||||
// class StartGameWidget extends ConsumerWidget { |
|
||||
// const StartGameWidget({ |
|
||||
// Key? key, |
|
||||
// required String nameString, |
|
||||
// }) : _nameString = nameString, |
|
||||
// super(key: key); |
|
||||
|
|
||||
// final String _nameString; |
|
||||
|
|
||||
// @override |
|
||||
// Widget build(BuildContext context, WidgetRef ref) { |
|
||||
// ref.listen(anonymousAuthNotificationProvider, (previous, next) { |
|
||||
// if (next is StorageDone) { |
|
||||
// Navigator.of(context).pushAndRemoveUntil( |
|
||||
// MaterialPageRoute( |
|
||||
// builder: (context) => MenuScreen( |
|
||||
// userData: next.userData, |
|
||||
// ), |
|
||||
// ), |
|
||||
// (route) => false, |
|
||||
// ); |
|
||||
// } |
|
||||
// }); |
|
||||
|
|
||||
// return Consumer( |
|
||||
// builder: (context, ref, child) { |
|
||||
// final state = ref.watch(anonymousAuthNotificationProvider); |
|
||||
|
|
||||
// return state.when( |
|
||||
// () => StartGameButton( |
|
||||
// nameString: _nameString, |
|
||||
// ), |
|
||||
// processing: () => const CircularProgressIndicator( |
|
||||
// valueColor: AlwaysStoppedAnimation<Color>(Palette.violet), |
|
||||
// ), |
|
||||
// done: (_) => const CircularProgressIndicator( |
|
||||
// valueColor: AlwaysStoppedAnimation<Color>(Palette.violet), |
|
||||
// ), |
|
||||
// storingInfo: () => const CircularProgressIndicator( |
|
||||
// valueColor: AlwaysStoppedAnimation<Color>(Palette.violet), |
|
||||
// ), |
|
||||
// storageDone: (userData) => const Icon( |
|
||||
// Icons.check, |
|
||||
// size: 50, |
|
||||
// color: Palette.violet, |
|
||||
// ), |
|
||||
// // done: (_) => const Icon( |
|
||||
// // Icons.check, |
|
||||
// // size: 50, |
|
||||
// // color: Palette.violet, |
|
||||
// // ), |
|
||||
// error: (message) => Column( |
|
||||
// children: [ |
|
||||
// Text('$message'), |
|
||||
// const SizedBox(height: 16), |
|
||||
// StartGameButton(nameString: _nameString), |
|
||||
// ], |
|
||||
// ), |
|
||||
// ); |
|
||||
// }, |
|
||||
// ); |
|
||||
// } |
|
||||
// } |
|
@ -1,39 +0,0 @@ |
|||||
// import 'package:flutter/material.dart'; |
|
||||
// import 'package:flutter_riverpod/flutter_riverpod.dart'; |
|
||||
// import 'package:my_flutter_puzzle/providers.dart'; |
|
||||
// import 'package:my_flutter_puzzle/res/palette.dart'; |
|
||||
|
|
||||
// class StartGameButton extends ConsumerWidget { |
|
||||
// const StartGameButton({ |
|
||||
// Key? key, |
|
||||
// required String nameString, |
|
||||
// }) : _nameString = nameString, |
|
||||
// super(key: key); |
|
||||
|
|
||||
// final String _nameString; |
|
||||
|
|
||||
// @override |
|
||||
// Widget build(BuildContext context, WidgetRef ref) { |
|
||||
// return SizedBox( |
|
||||
// width: double.maxFinite, |
|
||||
// child: ElevatedButton( |
|
||||
// style: ElevatedButton.styleFrom( |
|
||||
// primary: Palette.violet, |
|
||||
// onSurface: Palette.violet, |
|
||||
// ), |
|
||||
// onPressed: _nameString.isEmpty || _nameString.length < 3 |
|
||||
// ? null |
|
||||
// : () => ref |
|
||||
// .read(anonymousAuthNotificationProvider.notifier) |
|
||||
// .triggerAnonymousLogin(name: _nameString), |
|
||||
// child: const Padding( |
|
||||
// padding: EdgeInsets.all(16.0), |
|
||||
// child: Text( |
|
||||
// 'Start game', |
|
||||
// style: TextStyle(fontSize: 22), |
|
||||
// ), |
|
||||
// ), |
|
||||
// ), |
|
||||
// ); |
|
||||
// } |
|
||||
// } |
|
@ -1,2 +0,0 @@ |
|||||
export 'multiplayer_button.dart'; |
|
||||
export 'solo_button.dart'; |
|
@ -1,108 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart'; |
|
||||
import 'package:my_flutter_puzzle/models/user_info.dart'; |
|
||||
import 'package:my_flutter_puzzle/res/palette.dart'; |
|
||||
|
|
||||
class MultiplayerButton extends ConsumerStatefulWidget { |
|
||||
const MultiplayerButton({ |
|
||||
Key? key, |
|
||||
required this.myInfo, |
|
||||
required this.list, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
final UserData myInfo; |
|
||||
final List<int> list; |
|
||||
|
|
||||
@override |
|
||||
ConsumerState<ConsumerStatefulWidget> createState() => _MultiplayerButtonState(); |
|
||||
} |
|
||||
|
|
||||
class _MultiplayerButtonState extends ConsumerState<MultiplayerButton> { |
|
||||
late final List<int> numberList; |
|
||||
|
|
||||
@override |
|
||||
void initState() { |
|
||||
super.initState(); |
|
||||
numberList = widget.list; |
|
||||
numberList.shuffle(); |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
return SizedBox( |
|
||||
width: double.maxFinite, |
|
||||
child: OutlinedButton( |
|
||||
style: OutlinedButton.styleFrom( |
|
||||
primary: Palette.violet, |
|
||||
onSurface: Palette.violet, |
|
||||
shape: RoundedRectangleBorder( |
|
||||
borderRadius: BorderRadius.circular(50), |
|
||||
), |
|
||||
side: const BorderSide( |
|
||||
width: 2, |
|
||||
color: Palette.violet, |
|
||||
), |
|
||||
), |
|
||||
onPressed: () { |
|
||||
// ref |
|
||||
// .read(playerMatchingNotifierProvider.notifier) |
|
||||
// .triggerMatching(myInfo: widget.myInfo, numbers: numberList); |
|
||||
}, |
|
||||
child: const Padding( |
|
||||
padding: EdgeInsets.all(16.0), |
|
||||
child: Text( |
|
||||
'Multiplayer', |
|
||||
style: TextStyle(fontSize: 22), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// class MultiplayerButton extends StatefulWidget { |
|
||||
// final UserData myInfo; |
|
||||
// MultiplayerButton({ |
|
||||
// Key? key, |
|
||||
// required this.myInfo, |
|
||||
// }) : super(key: key); |
|
||||
|
|
||||
// @override |
|
||||
// State<MultiplayerButton> createState() => _MultiplayerButtonState(); |
|
||||
// } |
|
||||
|
|
||||
// class _MultiplayerButtonState extends State<MultiplayerButton> { |
|
||||
// final numberList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; |
|
||||
|
|
||||
// @override |
|
||||
// Widget build(BuildContext context) { |
|
||||
// return SizedBox( |
|
||||
// width: double.maxFinite, |
|
||||
// child: OutlinedButton( |
|
||||
// style: OutlinedButton.styleFrom( |
|
||||
// primary: Palette.violet, |
|
||||
// onSurface: Palette.violet, |
|
||||
// shape: RoundedRectangleBorder( |
|
||||
// borderRadius: BorderRadius.circular(50), |
|
||||
// ), |
|
||||
// side: const BorderSide( |
|
||||
// width: 2, |
|
||||
// color: Palette.violet, |
|
||||
// ), |
|
||||
// ), |
|
||||
// onPressed: () { |
|
||||
// ref.read(playerMatchingNotifierProvider.notifier).triggerMatching( |
|
||||
// myInfo: widget.myInfo, |
|
||||
// numbers: [14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 15]); |
|
||||
// }, |
|
||||
// child: const Padding( |
|
||||
// padding: EdgeInsets.all(16.0), |
|
||||
// child: Text( |
|
||||
// 'Multiplayer', |
|
||||
// style: TextStyle(fontSize: 22), |
|
||||
// ), |
|
||||
// ), |
|
||||
// ), |
|
||||
// ); |
|
||||
// } |
|
||||
// } |
|
@ -1,44 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:my_flutter_puzzle/res/palette.dart'; |
|
||||
import 'package:my_flutter_puzzle/screens/puzzle_solo_screen.dart'; |
|
||||
|
|
||||
class SoloButton extends StatelessWidget { |
|
||||
const SoloButton({ |
|
||||
Key? key, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
return SizedBox( |
|
||||
width: double.maxFinite, |
|
||||
child: OutlinedButton( |
|
||||
style: OutlinedButton.styleFrom( |
|
||||
primary: Palette.violet, |
|
||||
onSurface: Palette.violet, |
|
||||
shape: RoundedRectangleBorder( |
|
||||
borderRadius: BorderRadius.circular(50), |
|
||||
), |
|
||||
side: const BorderSide( |
|
||||
width: 2, |
|
||||
color: Palette.violet, |
|
||||
), |
|
||||
), |
|
||||
onPressed: () { |
|
||||
Navigator.of(context).pushAndRemoveUntil( |
|
||||
MaterialPageRoute( |
|
||||
builder: (context) => const PuzzleSoloScreen(), |
|
||||
), |
|
||||
(route) => false, |
|
||||
); |
|
||||
}, |
|
||||
child: const Padding( |
|
||||
padding: EdgeInsets.all(16.0), |
|
||||
child: Text( |
|
||||
'Solo', |
|
||||
style: TextStyle(fontSize: 22), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,53 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart'; |
|
||||
|
|
||||
class PickImageButton extends ConsumerWidget { |
|
||||
const PickImageButton({ |
|
||||
Key? key, |
|
||||
required this.text, |
|
||||
required this.onTap, |
|
||||
this.padding = const EdgeInsets.only(top: 13.0, bottom: 12.0), |
|
||||
this.width = 145, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
final String text; |
|
||||
final Function()? onTap; |
|
||||
final EdgeInsets padding; |
|
||||
final double width; |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context, WidgetRef ref) { |
|
||||
return SizedBox( |
|
||||
width: width, |
|
||||
child: ElevatedButton( |
|
||||
style: ButtonStyle( |
|
||||
shape: MaterialStateProperty.all<RoundedRectangleBorder>( |
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)), |
|
||||
), |
|
||||
backgroundColor: MaterialStateProperty.resolveWith<Color>( |
|
||||
(Set<MaterialState> states) { |
|
||||
if (states.contains(MaterialState.pressed)) { |
|
||||
return Theme.of(context).colorScheme.primary.withOpacity(0.5); |
|
||||
} else if (states.contains(MaterialState.disabled)) { |
|
||||
return Theme.of(context).colorScheme.primary.withOpacity(0.5); |
|
||||
} |
|
||||
|
|
||||
return Theme.of(context).colorScheme.primary; |
|
||||
}, |
|
||||
), |
|
||||
), |
|
||||
onPressed: onTap, |
|
||||
child: Padding( |
|
||||
padding: padding, |
|
||||
child: Text( |
|
||||
text, |
|
||||
style: TextStyle( |
|
||||
fontSize: 16, |
|
||||
color: Colors.white.withOpacity(onTap == null ? 0.6 : 1), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,28 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
|
|
||||
class MovesText extends StatelessWidget { |
|
||||
const MovesText({ |
|
||||
Key? key, |
|
||||
required int moves, |
|
||||
required this.fontSize, |
|
||||
}) : _moves = moves, |
|
||||
super(key: key); |
|
||||
|
|
||||
final int _moves; |
|
||||
final double fontSize; |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
return Padding( |
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 24), |
|
||||
child: Text( |
|
||||
'$_moves Moves', |
|
||||
style: TextStyle( |
|
||||
fontSize: fontSize, |
|
||||
fontWeight: FontWeight.bold, |
|
||||
color: Colors.black, |
|
||||
), |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,26 +0,0 @@ |
|||||
import 'package:flutter/material.dart'; |
|
||||
|
|
||||
class PlayerText extends StatelessWidget { |
|
||||
final String displayName; |
|
||||
|
|
||||
const PlayerText({ |
|
||||
Key? key, |
|
||||
required this.displayName, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
return Padding( |
|
||||
padding: const EdgeInsets.only(top: 24.0), |
|
||||
child: Text( |
|
||||
displayName, |
|
||||
style: const TextStyle( |
|
||||
fontSize: 20, |
|
||||
fontWeight: FontWeight.bold, |
|
||||
color: Color(0xFF14407a), |
|
||||
letterSpacing: 2, |
|
||||
), |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,2 +0,0 @@ |
|||||
export 'moves_text.dart'; |
|
||||
export 'player_text.dart'; |
|
@ -1,73 +0,0 @@ |
|||||
import 'dart:async'; |
|
||||
|
|
||||
import 'package:flutter/material.dart'; |
|
||||
|
|
||||
class TimerWidget extends StatefulWidget { |
|
||||
const TimerWidget({ |
|
||||
Key? key, |
|
||||
required this.fontSize, |
|
||||
required this.color, |
|
||||
}) : super(key: key); |
|
||||
|
|
||||
final double fontSize; |
|
||||
final Color color; |
|
||||
|
|
||||
@override |
|
||||
_TimerWidgetState createState() => _TimerWidgetState(); |
|
||||
} |
|
||||
|
|
||||
class _TimerWidgetState extends State<TimerWidget> { |
|
||||
late final Timer _timer; |
|
||||
int _start = 0; |
|
||||
|
|
||||
void startTimer() { |
|
||||
_timer = Timer.periodic( |
|
||||
const Duration(seconds: 1), |
|
||||
(Timer timer) => setState(() => _start++), |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
String printDuration() { |
|
||||
var duration = Duration(seconds: _start); |
|
||||
String twoDigits(int n) => n.toString().padLeft(2, "0"); |
|
||||
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60)); |
|
||||
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60)); |
|
||||
return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds"; |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
void initState() { |
|
||||
startTimer(); |
|
||||
super.initState(); |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
void dispose() { |
|
||||
_timer.cancel(); |
|
||||
super.dispose(); |
|
||||
} |
|
||||
|
|
||||
@override |
|
||||
Widget build(BuildContext context) { |
|
||||
return Center( |
|
||||
child: Row( |
|
||||
mainAxisSize: MainAxisSize.min, |
|
||||
children: [ |
|
||||
Text( |
|
||||
printDuration(), |
|
||||
style: TextStyle( |
|
||||
fontSize: widget.fontSize, |
|
||||
color: widget.color, |
|
||||
), |
|
||||
), |
|
||||
const SizedBox(width: 8), |
|
||||
Icon( |
|
||||
Icons.timer, |
|
||||
color: widget.color, |
|
||||
size: widget.fontSize * 1.3, |
|
||||
) |
|
||||
], |
|
||||
), |
|
||||
); |
|
||||
} |
|
||||
} |
|
@ -1,6 +0,0 @@ |
|||||
export 'animated_dash.dart'; |
|
||||
export 'countdown_widget.dart'; |
|
||||
export 'game_button_widget.dart'; |
|
||||
export 'moves_tiles_widget.dart'; |
|
||||
export 'puzzle_widget.dart'; |
|
||||
export 'timer_widget.dart'; |
|