From cbca859226bb19c1a4e355bc9278ee91cfc7f82b Mon Sep 17 00:00:00 2001 From: marco Date: Fri, 8 Oct 2021 21:50:47 -0600 Subject: [PATCH] Added connections to the firo_runner_server. Fixed a couple introduced bugs. Added flag for non tournament version of the code for Google Play/ Apple. --- lib/deposit.dart | 80 ++++++++++ lib/leader_board.dart | 173 +++++++++++++++++++++ lib/lose_menu_overlay.dart | 23 +-- lib/main.dart | 139 +++++++++-------- lib/main_menu_overlay.dart | 303 +++++++++++++++++++++++++------------ lib/runner.dart | 2 - lib/sign_in_overlay.dart | 151 ++++++++++++++++++ pubspec.lock | 58 ++++++- pubspec.yaml | 2 + 9 files changed, 762 insertions(+), 169 deletions(-) create mode 100644 lib/deposit.dart create mode 100644 lib/leader_board.dart create mode 100644 lib/sign_in_overlay.dart diff --git a/lib/deposit.dart b/lib/deposit.dart new file mode 100644 index 0000000..1ac3c6e --- /dev/null +++ b/lib/deposit.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; + +import 'main.dart'; +import 'package:qr_flutter/qr_flutter.dart'; + +class DepositOverlay extends StatelessWidget { + const DepositOverlay({ + Key? key, + required this.game, + }) : super(key: key); + + final Color textColor = Colors.cyan; + final Color cardColor = const Color(0xff262b3f); + final Color titleColor = const Color(0xff68d9cc); + + final MyGame game; + + List getDepositAddress(double width) { + List list = []; + if (game.address.length != 34) {} + list.add(QrImage( + data: game.address, + version: QrVersions.auto, + size: width / 5, + backgroundColor: Colors.white, + )); + list.add(Padding( + padding: EdgeInsets.all(width * 0.01), + child: Card( + color: cardColor, + shape: RoundedRectangleBorder( + side: BorderSide(color: titleColor, width: 3), + borderRadius: BorderRadius.circular(10.0)), + child: Padding( + padding: EdgeInsets.all(width * 0.01), + child: SelectableText( + game.address, + style: TextStyle( + color: textColor, + fontSize: width * 0.03, + ), + ), + ), + ), + )); + return list; + } + + @override + Widget build(BuildContext context) { + double width = MediaQuery.of(context).size.width; + return Material( + color: Colors.transparent, + child: InkWell( + child: Center( + child: Container( + height: game.viewport.canvasSize.y, + width: game.viewport.canvasSize.x, + decoration: const BoxDecoration( + image: DecorationImage( + image: lossImage, + fit: BoxFit.fill, + ), + ), + child: SizedBox( + width: width / 3, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: getDepositAddress(width), + ), + ), + ), + ), + onTap: () { + game.overlays.remove('deposit'); + }, + ), + ); + } +} diff --git a/lib/leader_board.dart b/lib/leader_board.dart new file mode 100644 index 0000000..a83c712 --- /dev/null +++ b/lib/leader_board.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; + +import 'main.dart'; + +class LeaderBoardOverlay extends StatelessWidget { + const LeaderBoardOverlay({ + Key? key, + required this.game, + }) : super(key: key); + + final Color textColor = Colors.cyan; + final Color cardColor = const Color(0xff262b3f); + final Color borderColor = const Color(0xdfd675e1); + final Color titleColor = const Color(0xff68d9cc); + + // final Color textColor = Colors.black; + + final MyGame game; + + List getLeaderboard(double width) { + List leaders = []; + List list = game.leaderboard.split("\n"); + + if (list.isEmpty || list.length % 2 != 1 || list.length == 1) { + leaders.add( + Card( + color: cardColor, + shape: RoundedRectangleBorder( + side: BorderSide(color: titleColor, width: 3), + borderRadius: BorderRadius.circular(10.0)), + child: FractionallySizedBox( + widthFactor: 0.5, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: EdgeInsets.all(width * 0.01), + child: Text( + "No Internet Connection.", + style: TextStyle( + color: textColor, + fontSize: width * 0.03, + ), + ), + ) + ], + ), + ), + ), + ); + return leaders; + } + + leaders.add( + Card( + color: cardColor, + shape: RoundedRectangleBorder( + side: BorderSide(color: titleColor, width: 3), + borderRadius: BorderRadius.circular(10.0)), + child: FractionallySizedBox( + widthFactor: 0.4, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: EdgeInsets.all(width * 0.01), + child: Text( + "Username", + style: TextStyle( + color: textColor, + fontSize: width * 0.03, + ), + ), + ), + SizedBox( + width: width / 11, + ), + Padding( + padding: EdgeInsets.all(width * 0.01), + child: Text( + "Score", + style: TextStyle( + color: textColor, + fontSize: width * 0.03, + ), + ), + ), + ], + ), + ), + ), + ); + for (int i = 0; i < list.length - 2; i = i + 2) { + String name = list.elementAt(i); + String score = list.elementAt(i + 1); + leaders.add( + Card( + color: cardColor, + shape: RoundedRectangleBorder( + side: BorderSide(color: borderColor, width: 3), + borderRadius: BorderRadius.circular(10.0)), + child: FractionallySizedBox( + widthFactor: 0.4, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: EdgeInsets.all(width * 0.01), + child: Text( + name.substring(0, name.length < 10 ? name.length : 10), + style: TextStyle( + color: textColor, + fontSize: width * 0.03, + ), + ), + ), + SizedBox( + width: width / 11, + ), + Padding( + padding: EdgeInsets.all(width * 0.01), + child: Text( + score, + style: TextStyle( + color: textColor, + fontSize: width * 0.03, + ), + ), + ), + ], + ), + ), + ), + ); + } + return leaders; + } + + @override + Widget build(BuildContext context) { + double width = MediaQuery.of(context).size.width; + return Material( + color: Colors.transparent, + child: InkWell( + child: Center( + child: Container( + height: game.viewport.canvasSize.y, + width: game.viewport.canvasSize.x, + decoration: const BoxDecoration( + image: DecorationImage( + image: lossImage, + fit: BoxFit.fill, + ), + ), + child: SizedBox( + width: width / 3, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: getLeaderboard(width), + ), + ), + ), + ), + onTap: () { + game.overlays.remove('leaderboard'); + }, + ), + ); + } +} diff --git a/lib/lose_menu_overlay.dart b/lib/lose_menu_overlay.dart index 4f8b789..1e08036 100644 --- a/lib/lose_menu_overlay.dart +++ b/lib/lose_menu_overlay.dart @@ -88,22 +88,27 @@ class LoseMenuOverlay extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - " REPLAY ", + " REPLAY${game.competitive ? " ${game.tries}" : ""} ", style: TextStyle( - color: Colors.cyan, + color: game.competitive && game.tries <= 0 + ? Colors.grey + : Colors.cyan, fontSize: width * 0.03, ), ), ), ), // ), - onPressed: () async { - await FlameAudio.audioCache.play('sfx/button_click.mp3', - mode: PlayerMode.LOW_LATENCY); - game.runner.friend = await FlameAudio.audioCache - .loop('sfx/robot_friend_beep.mp3'); - game.reset(); - }, + onPressed: game.competitive && game.tries <= 0 + ? null + : () async { + await FlameAudio.audioCache.play( + 'sfx/button_click.mp3', + mode: PlayerMode.LOW_LATENCY); + game.runner.friend = await FlameAudio.audioCache + .loop('sfx/robot_friend_beep.mp3'); + game.reset(); + }, ), ], ), diff --git a/lib/main.dart b/lib/main.dart index 11a6075..53a9cf1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,17 +1,18 @@ import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; import 'dart:math'; import 'package:firo_runner/bug_holder.dart'; import 'package:firo_runner/circuit_background.dart'; import 'package:firo_runner/coin_holder.dart'; import 'package:firo_runner/debris_holder.dart'; +import 'package:firo_runner/deposit.dart'; import 'package:firo_runner/firework.dart'; import 'package:firo_runner/game_state.dart'; +import 'package:firo_runner/leader_board.dart'; import 'package:firo_runner/moving_object.dart'; import 'package:firo_runner/platform.dart'; import 'package:firo_runner/platform_holder.dart'; +import 'package:firo_runner/sign_in_overlay.dart'; import 'package:firo_runner/wall_holder.dart'; import 'package:firo_runner/wire.dart'; import 'package:firo_runner/wire_holder.dart'; @@ -30,6 +31,14 @@ import 'package:http/http.dart' as http; import 'package:firo_runner/lose_menu_overlay.dart'; import 'package:firo_runner/main_menu_overlay.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +// TODO Set NO_TOURNAMENT to false, and then set the SERVER and PORT for the +// firo runner server instance. +const NO_TOURNAMENT = false; + +const SERVER = "http://10.0.0.224"; +const PORT = "50067"; const COLOR = Color(0xFFDDC0A3); const int LOADING_TIME = 2000000; @@ -88,6 +97,15 @@ void main() async { ), ); }, + 'leaderboard': (_, myGame) { + return LeaderBoardOverlay(game: myGame); + }, + 'deposit': (_, myGame) { + return DepositOverlay(game: myGame); + }, + 'signin': (_, myGame) { + return SignInOverlay(game: myGame); + }, 'mainMenu': (_, myGame) { return MainMenuOverlay(game: myGame); }, @@ -118,6 +136,12 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { config: const TextPaintConfig(fontSize: 16.0, color: COLOR), ); + String leaderboard = ""; + String address = ""; + String username = ""; + int tries = 0; + bool competitive = false; + late CircuitBackground circuitBackground; late PlatformHolder platformHolder; late CoinHolder coinHolder; @@ -146,7 +170,18 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { @override Future onLoad() async { - // debugMode = true; + if (!NO_TOURNAMENT) { + final prefs = await SharedPreferences.getInstance(); + username = prefs.getString('username') ?? ""; + tries = prefs.getInt('tries') ?? 0; + String result = await connectServer("gettries", "user=$username"); + try { + tries = int.parse(result); + prefs.setInt('tries', tries); + } catch (e) { + print(e); + } + } FlameAudio.bgm.initialize(); await FlameAudio.audioCache.loadAll([ @@ -312,56 +347,30 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { bool shouldReset = false; - // late Socket socket; - // void dataHandler(data) { - // print(new String.fromCharCodes(data).trim()); - // } - // - // void errorHandler(error, StackTrace trace) { - // print(error); - // } - // - // void doneHandler() { - // socket.destroy(); - // } - - // Future connectServer() async { - // try { - // Socket.connect('10.0.0.224', 50018).then((Socket sock) { - // socket = sock; - // socket.listen(dataHandler, - // onError: errorHandler, onDone: doneHandler, cancelOnError: false); - // }); - // } catch (e) { - // print(e); - // } - // // try { - // // final response = await http.post( - // // Uri.parse('http://10.0.0.224:50017'), - // // headers: { - // // 'Content-Type': 'application/json; charset=UTF-8', - // // }, - // // body: jsonEncode({ - // // 'title': "hi", - // // }), - // // ); - // // if (response.statusCode == 201) { - // // // If the server did return a 201 CREATED response, - // // // then parse the JSON. - // // print("hello"); - // // print(response); - // // print(response.body); - // // } else { - // // // If the server did not return a 201 CREATED response, - // // // then throw an exception. - // // throw Exception('Failed to create album.'); - // // } - // // // var value = await channel.stream.first; - // // // print(value); - // // } catch (e) { - // // print(e); - // // } - // } + Future connectServer(String command, String arguments) async { + try { + final response = await http.post( + Uri.parse("$SERVER:$PORT/$command?$arguments"), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }, + ); + if (response.statusCode == 200) { + // If the server did return a 200, + // then parse the JSON. + return response.body; + } else { + // If the server did not return a 201 CREATED response, + // then throw an exception. + throw Exception('Failed to connect to Firo Runner server.'); + } + // var value = await channel.stream.first; + // print(value); + } catch (e) { + print(e); + return ""; + } + } Future displayLoss() async { if (!(runner.sprite.animation?.done() ?? false) && @@ -369,7 +378,6 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { firstDeath) { return; } - // await connectServer(); firstDeath = false; overlays.add('gameOver'); } @@ -390,8 +398,23 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { setUp(); } - void die() { + Future die() async { gameState.setPaused(); + if (!NO_TOURNAMENT) { + final prefs = await SharedPreferences.getInstance(); + if (username != "" && competitive) { + await connectServer( + "newscore", "user=$username&score=${gameState.getPlayerScore()}"); + } + tries = prefs.getInt('tries') ?? 0; + String result = await connectServer("gettries", "user=$username"); + try { + tries = int.parse(result); + prefs.setInt('tries', tries); + } catch (e) { + print(e); + } + } shouldReset = true; } @@ -425,12 +448,6 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { circuitBackground.render(canvas); fireworks.renderText(canvas); super.render(canvas); - // final fpsCount = fps(10000); - // fireworksPaint.render( - // canvas, - // fpsCount.toString(), - // Vector2(0, 0), - // ); coinHolder.renderCoinScore(canvas); } } diff --git a/lib/main_menu_overlay.dart b/lib/main_menu_overlay.dart index 5f6500e..fe900c5 100644 --- a/lib/main_menu_overlay.dart +++ b/lib/main_menu_overlay.dart @@ -2,7 +2,9 @@ import 'package:flame_audio/flame_audio.dart'; import 'package:flutter/material.dart'; import 'package:audioplayers/src/api/player_mode.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'main.dart'; +import 'package:flutter/foundation.dart' show kIsWeb; class MainMenuOverlay extends StatelessWidget { const MainMenuOverlay({ @@ -27,111 +29,220 @@ class MainMenuOverlay extends StatelessWidget { ), child: Row( mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: NO_TOURNAMENT + ? MainAxisAlignment.spaceEvenly + : MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Column( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - // const SizedBox( - // height: 32.0, - // ), - // const SizedBox( - // height: 32.0, - // ), - // const SizedBox( - // height: 32.0, - // ), - MaterialButton( - padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), - textColor: Colors.white, - splashColor: Colors.greenAccent, - elevation: 8.0, - child: Container( - decoration: const BoxDecoration( - image: - DecorationImage(image: buttonImage, fit: BoxFit.fill), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - " START ", - style: TextStyle( - color: Colors.cyan, - fontSize: width * 0.03, + const SizedBox( + height: 16.0, + ), + const SizedBox( + height: 16.0, + ), + const SizedBox( + height: 16.0, + ), + Row( + children: [ + MaterialButton( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), + textColor: Colors.white, + splashColor: Colors.greenAccent, + elevation: 8.0, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: buttonImage, fit: BoxFit.fill), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + " START ", + style: TextStyle( + color: Colors.cyan, + fontSize: width * 0.025, + ), + ), ), ), + onPressed: () async { + // Go to the Main Menu + FlameAudio.audioCache.play('sfx/menu_button.mp3', + mode: PlayerMode.LOW_LATENCY); + game.competitive = false; + game.reset(); + game.runner.boost = FlameAudio.audioCache.play( + 'sfx/laser.mp3', + volume: 0.0, + mode: PlayerMode.LOW_LATENCY); + FlameAudio.bgm.stop(); + FlameAudio.bgm.play('Infinite_Spankage_M.mp3'); + game.runner.friend = await FlameAudio.audioCache.loop( + 'sfx/robot_friend_beep.mp3', + volume: 0.25, + mode: PlayerMode.LOW_LATENCY); + }, ), - ), - // ), - onPressed: () async { - // Go to the Main Menu - FlameAudio.audioCache.play('sfx/menu_button.mp3', - mode: PlayerMode.LOW_LATENCY); - game.reset(); - FlameAudio.bgm.stop(); - FlameAudio.bgm.play('Infinite_Spankage_M.mp3'); - game.runner.friend = await FlameAudio.audioCache.loop( - 'sfx/robot_friend_beep.mp3', - volume: 0.25, - mode: PlayerMode.LOW_LATENCY); - }, + ], ), - // MaterialButton( - // padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), - // textColor: Colors.white, - // splashColor: Colors.greenAccent, - // elevation: 8.0, - // child: Container( - // decoration: const BoxDecoration( - // image: - // DecorationImage(image: buttonImage, fit: BoxFit.fill), - // ), - // child: Padding( - // padding: EdgeInsets.all(8.0), - // child: Text( - // " DEPOSIT ", - // style: TextStyle( - // color: Colors.cyan, - // fontSize: width * 0.03, - // ), - // ), - // ), - // ), - // // ), - // onPressed: () { - // // Show QR code - // await FlameAudio.audioCache.play('sfx/button_click.mp3', mode: PlayerMode.LOW_LATENCY); - // }, - // ), - // MaterialButton( - // padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), - // textColor: Colors.white, - // splashColor: Colors.greenAccent, - // elevation: 8.0, - // child: Container( - // decoration: const BoxDecoration( - // image: - // DecorationImage(image: buttonImage, fit: BoxFit.fill), - // ), - // child: Padding( - // padding: EdgeInsets.all(8.0), - // child: Text( - // " LEADER BOARD ", - // style: TextStyle( - // color: Colors.cyan, - // fontSize: width * 0.03, - // ), - // ), - // ), - // ), - // // ), - // onPressed: () { - // // Show QR code - // await FlameAudio.audioCache.play('sfx/button_click.mp3', mode: PlayerMode.LOW_LATENCY); - // }, - // ), + NO_TOURNAMENT + ? const SizedBox( + height: 16.0, + ) + : Row( + children: [ + MaterialButton( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), + textColor: Colors.white, + splashColor: Colors.greenAccent, + elevation: 8.0, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: buttonImage, fit: BoxFit.fill), + ), + child: Padding( + padding: EdgeInsets.all(8.0), + child: Text( + " DEPOSIT ", + style: TextStyle( + color: game.username == "" + ? Colors.grey + : Colors.cyan, + fontSize: width * 0.025, + ), + ), + ), + ), + onPressed: game.username == "" + ? null + : () async { + game.address = await game.connectServer( + "deposit", "user=${game.username}"); + FlameAudio.audioCache.play( + 'sfx/button_click.mp3', + mode: PlayerMode.LOW_LATENCY); + game.overlays.add("deposit"); + }, + ), + MaterialButton( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), + textColor: Colors.white, + splashColor: Colors.greenAccent, + elevation: 8.0, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: buttonImage, fit: BoxFit.fill), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + " TOURNAMENT ${game.tries} ", + style: TextStyle( + color: + game.username == "" || game.tries == 0 + ? Colors.grey + : Colors.cyan, + fontSize: width * 0.025, + ), + ), + ), + ), + onPressed: game.username == "" || game.tries == 0 + ? null + : () async { + // Go to the Main Menu + FlameAudio.audioCache.play( + 'sfx/menu_button.mp3', + mode: PlayerMode.LOW_LATENCY); + game.runner.boost = FlameAudio.audioCache + .play('sfx/laser.mp3', + volume: 0.0, + mode: PlayerMode.LOW_LATENCY); + game.competitive = true; + game.reset(); + FlameAudio.bgm.stop(); + FlameAudio.bgm + .play('Infinite_Spankage_M.mp3'); + game.runner.friend = await FlameAudio + .audioCache + .loop('sfx/robot_friend_beep.mp3', + volume: 0.25, + mode: PlayerMode.LOW_LATENCY); + }, + ), + ], + ), + NO_TOURNAMENT + ? const SizedBox( + height: 16.0, + ) + : Row( + children: [ + MaterialButton( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), + textColor: Colors.white, + splashColor: Colors.greenAccent, + elevation: 8.0, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: buttonImage, fit: BoxFit.fill), + ), + child: Padding( + padding: EdgeInsets.all(8.0), + child: Text( + " ${game.username == "" ? "SIGN IN" : game.username} ", + style: TextStyle( + color: Colors.cyan, + fontSize: width * 0.025, + ), + ), + ), + ), + onPressed: () async { + FlameAudio.audioCache.play('sfx/button_click.mp3', + mode: PlayerMode.LOW_LATENCY); + game.overlays.add("signin"); + }, + ), + MaterialButton( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), + textColor: Colors.white, + splashColor: Colors.greenAccent, + elevation: 8.0, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: buttonImage, fit: BoxFit.fill), + ), + child: Padding( + padding: EdgeInsets.all(8.0), + child: Text( + " LEADER BOARD ", + style: TextStyle( + color: Colors.cyan, + fontSize: width * 0.025, + ), + ), + ), + ), + onPressed: () async { + game.leaderboard = await game.connectServer( + "leaderboard", "user=value"); + FlameAudio.audioCache.play('sfx/button_click.mp3', + mode: PlayerMode.LOW_LATENCY); + game.overlays.add("leaderboard"); + }, + ), + ], + ), ], ), const SizedBox( diff --git a/lib/runner.dart b/lib/runner.dart index 8b3d513..c8988c3 100644 --- a/lib/runner.dart +++ b/lib/runner.dart @@ -557,8 +557,6 @@ class Runner extends Component with HasGameRef { } Future load() async { - boost = FlameAudio.audioCache - .play('sfx/laser.mp3', volume: 0.0, mode: PlayerMode.LOW_LATENCY); List satellites = []; for (int i = 1; i <= 38; i++) { satellites.add(await Flame.images.load( diff --git a/lib/sign_in_overlay.dart b/lib/sign_in_overlay.dart new file mode 100644 index 0000000..739f8b2 --- /dev/null +++ b/lib/sign_in_overlay.dart @@ -0,0 +1,151 @@ +import 'package:flame_audio/flame_audio.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'main.dart'; +import 'package:audioplayers/src/api/player_mode.dart'; + +/// This is the stateful widget that the main application instantiates. +class SignInOverlay extends StatefulWidget { + const SignInOverlay({ + Key? key, + required this.game, + }) : super(key: key); + + final Color cardColor = Colors.white; + final Color textColor = Colors.black; + + final MyGame game; + + @override + State createState() => _MyStatefulWidgetState(); +} + +/// This is the private State class that goes with MyStatefulWidget. +class _MyStatefulWidgetState extends State { + final GlobalKey _formKey = GlobalKey(); + final accountController = TextEditingController(); + final keyController = TextEditingController(); + + @override + Widget build(BuildContext context) { + double width = MediaQuery.of(context).size.width; + return Material( + color: Colors.transparent, + child: InkWell( + child: Center( + child: Container( + height: widget.game.viewport.canvasSize.y, + width: widget.game.viewport.canvasSize.x, + decoration: const BoxDecoration( + image: DecorationImage( + image: lossImage, + fit: BoxFit.fill, + ), + ), + child: SingleChildScrollView( + child: Center( + child: SizedBox( + width: 2 * width / 3, + child: Container( + padding: const EdgeInsets.all(30), + color: Colors.white, + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + decoration: const InputDecoration( + hintText: 'Enter your account name', + ), + validator: (String? value) { + if (value == null || value.isEmpty) { + return 'Please enter your account name'; + } else if (value.contains(' ')) { + return 'Please input a valid account name without any spaces'; + } + return null; + }, + controller: accountController, + ), + TextFormField( + decoration: const InputDecoration( + hintText: 'Enter your receiving Firo address.', + ), + validator: (String? value) { + // if (value == null || value.isEmpty) { + // return 'Please enter your receiving Firo address.'; + // } else + if (value == null || value.isEmpty) { + print("logging in instead of signing up."); + return null; + } else if (value.length != 34) { + return 'Not a valid receiving Firo address.'; + } + return null; + }, + controller: keyController, + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: ElevatedButton( + onPressed: () async { + // // Validate will return true if the form is valid, or false if + // // the form is invalid. + FlameAudio.audioCache.play( + 'sfx/button_click.mp3', + mode: PlayerMode.LOW_LATENCY); + if (!_formKey.currentState!.validate()) { + return; + } + + // Process data. + String account = accountController.text; + String key = keyController.text; + + String username = await widget.game.connectServer( + "newuser", + "user=$account&receive=${key == "" ? "dud" : key}"); + + if (username.toLowerCase().contains("error")) { + print("There was an error"); + } else { + final prefs = + await SharedPreferences.getInstance(); + prefs.setString('username', username); + widget.game.username = + prefs.getString('username') ?? ""; + try { + String result = await widget.game + .connectServer( + "gettries", "user=$username"); + widget.game.tries = int.parse(result); + prefs.setInt('tries', widget.game.tries); + } catch (e) { + print(e); + } + } + + widget.game.overlays.remove('signin'); + }, + child: const Text('Sign In'), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + ), + onTap: () { + widget.game.overlays.remove('signin'); + }, + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 1704357..6b852ae 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -275,6 +275,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.3" + qr: + dependency: transitive + description: + name: qr + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" sky_engine: dependency: transitive description: flutter @@ -380,4 +436,4 @@ packages: version: "3.1.0" sdks: dart: ">=2.14.0 <3.0.0" - flutter: ">=2.0.0" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8038e0b..f7c74e0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,6 +26,8 @@ dependencies: flame: "^1.0.0-releasecandidate.11" flame_audio: "^1.0.0-rc.1" http: ^0.13.3 + qr_flutter: ^4.0.0 + shared_preferences: ^2.0.8 # The following adds the Cupertino Icons font to your application.