diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 5a3eb01..6d1d8a2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -3,7 +3,7 @@ + android:icon="@mipmap/launcher_icon"> ( - game: myGame, - overlayBuilderMap: { - 'gameOver': (_, myGame) { - return LoseMenuOverlay(game: myGame); - }, - }, - )); + runApp(MaterialApp( + debugShowCheckedModeBanner: false, + home: GameWidget( + game: myGame, + overlayBuilderMap: { + // Should be used once before all overlays are called. Flame has a slight + // delay when constructing the overlay widgets, so to make the text and + // images load together, all the other overlays should be called in the + // load section, and removed, and the loading black screen should be kept + // up until everything is finished loading. + 'loading': (_, myGame) { + return Center( + child: Container( + height: myGame.viewport.canvasSize.y, + width: myGame.viewport.canvasSize.x, + color: Colors.black, + ), + ); + }, + 'mainMenu': (_, myGame) { + return MainMenuOverlay(game: myGame); + }, + 'gameOver': (_, myGame) { + return LoseMenuOverlay(game: myGame); + }, + }, + ))); } int getNearestPlatform(int level) { @@ -110,6 +135,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { late Wire wire; late TextComponent _distance; late TextComponent _coins; + int startLoading = 0; MyGame() : super() { viewport.resize(Vector2(1920, 1080)); @@ -125,6 +151,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { platformHolder = PlatformHolder(); await platformHolder.load(); coinHolder = CoinHolder(); + coinHolder.setPersonalGameRef(this); await coinHolder.load(); wireHolder = WireHolder(); await wireHolder.load(); @@ -142,19 +169,22 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { runner = Runner(); await runner.load(loadSpriteAnimation); - if (!kIsWeb) { - playMusic(); - } loaded = true; _distance = TextComponent("Distance: 0", position: Vector2(size.x - 100, 10), textRenderer: scoresPaint) ..anchor = Anchor.topRight; _distance.changePriorityWithoutResorting(OVERLAY_PRIORITY); - _coins = TextComponent("Coins: 0", - position: Vector2(size.x - 10, 10), textRenderer: scoresPaint) + _coins = TextComponent(": 0", + position: Vector2(size.x - 35, 10), textRenderer: scoresPaint) ..anchor = Anchor.topRight; _coins.changePriorityWithoutResorting(OVERLAY_PRIORITY); + overlays.add("gameOver"); + overlays.remove('gameOver'); + overlays.add("mainMenu"); + overlays.add('loading'); setUp(); + gameState.setPaused(); + startLoading = DateTime.now().microsecondsSinceEpoch; } void playMusic() { @@ -248,56 +278,56 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { bool shouldReset = false; - late Socket socket; - void dataHandler(data) { - print(new String.fromCharCodes(data).trim()); - } + // late Socket socket; + // void dataHandler(data) { + // print(new String.fromCharCodes(data).trim()); + // } + // + // void errorHandler(error, StackTrace trace) { + // print(error); + // } + // + // void doneHandler() { + // socket.destroy(); + // } - 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() 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 displayLoss() async { if (!(runner.sprite.animation?.done() ?? false) && @@ -305,14 +335,20 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { firstDeath) { return; } - await connectServer(); + // await connectServer(); firstDeath = false; overlays.add('gameOver'); } + void mainMenu() { + overlays.remove('gameOver'); + overlays.add('mainMenu'); + } + void reset() { runner.sprite.animation!.reset(); overlays.remove('gameOver'); + overlays.remove('mainMenu'); shouldReset = false; components.clear(); setUp(); @@ -349,19 +385,29 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { @override void render(Canvas canvas) { - circuitBackground.render(canvas); - fireworks.renderText(canvas); - super.render(canvas); - final fpsCount = fps(10000); - fireworksPaint.render( - canvas, - fpsCount.toString(), - Vector2(0, 0), - ); + if (!overlays.isActive('mainMenu')) { + circuitBackground.render(canvas); + fireworks.renderText(canvas); + super.render(canvas); + final fpsCount = fps(10000); + fireworksPaint.render( + canvas, + fpsCount.toString(), + Vector2(0, 0), + ); + coinHolder.renderCoinScore(canvas); + } } @override void update(double dt) { + if (overlays.isActive('loading') && + (DateTime.now().microsecondsSinceEpoch - startLoading) > LOADING_TIME) { + overlays.remove('loading'); + if (!kIsWeb) { + playMusic(); + } + } fireworks.update(dt); platformHolder.removePast(this); coinHolder.removePast(this); @@ -381,8 +427,10 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { wallHolder.update(dt); _distance.text = "Distance: ${gameState.getPlayerDistance()}"; - _coins.text = "Coins: ${gameState.numCoins}"; - if (shouldReset && !overlays.isActive('gameOver')) { + _coins.text = " ${gameState.numCoins}"; + if (shouldReset && + !overlays.isActive('gameOver') && + !overlays.isActive('mainMenu')) { displayLoss(); } } diff --git a/lib/main_menu_overlay.dart b/lib/main_menu_overlay.dart new file mode 100644 index 0000000..110f212 --- /dev/null +++ b/lib/main_menu_overlay.dart @@ -0,0 +1,142 @@ +import 'package:flutter/material.dart'; + +import 'main.dart'; + +class MainMenuOverlay extends StatelessWidget { + const MainMenuOverlay({ + Key? key, + required this.game, + }) : super(key: key); + + final MyGame game; + + @override + Widget build(BuildContext context) { + double width = MediaQuery.of(context).size.width; + return Center( + child: Container( + height: game.viewport.canvasSize.y, + width: game.viewport.canvasSize.x, + decoration: const BoxDecoration( + image: DecorationImage( + image: mainMenuImage, + fit: BoxFit.fitWidth, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + 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.white, + fontSize: width * 0.03, + ), + ), + ), + ), + // ), + onPressed: () { + // Go to the Main Menu + game.reset(); + }, + ), + // 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.white, + // fontSize: width * 0.03, + // ), + // ), + // ), + // ), + // // ), + // onPressed: () { + // // Show QR code + // }, + // ), + // 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 Boards ", + // style: TextStyle( + // color: Colors.white, + // fontSize: width * 0.03, + // ), + // ), + // ), + // ), + // // ), + // onPressed: () { + // // Show QR code + // }, + // ), + ], + ), + const SizedBox( + width: 32.0, + ), + const SizedBox( + width: 32.0, + ), + const SizedBox( + width: 32.0, + ), + const SizedBox( + width: 32.0, + ), + ], + ), + ), + ); + } +} diff --git a/lib/runner.dart b/lib/runner.dart index ed81056..521f686 100644 --- a/lib/runner.dart +++ b/lib/runner.dart @@ -177,16 +177,11 @@ class Runner extends Component with HasGameRef { } previousState = runnerState; sprite.clearEffects(); - level = 11; - sprite.addEffect(MoveEffect( - path: [Vector2(sprite.position.x, gameRef.blockSize * 11)], - duration: 2, - curve: Curves.bounceOut, - onComplete: () {}, - )); runnerState = event; sprite.current = RunnerState.die; + dead = true; gameRef.die(); + sprite.addEffect(getFallingEffect()); break; case "electrocute": if (dead) { @@ -194,16 +189,11 @@ class Runner extends Component with HasGameRef { } previousState = runnerState; sprite.clearEffects(); - level = 11; - sprite.addEffect(MoveEffect( - path: [Vector2(sprite.position.x, gameRef.blockSize * 11)], - duration: 1, - curve: Curves.bounceOut, - onComplete: () {}, - )); runnerState = event; sprite.current = RunnerState.electrocute; + dead = true; gameRef.die(); + sprite.addEffect(getFallingEffect()); break; case "glitch": if (dead) { @@ -211,15 +201,9 @@ class Runner extends Component with HasGameRef { } previousState = runnerState; sprite.clearEffects(); - level = 11; - sprite.addEffect(MoveEffect( - path: [Vector2(sprite.position.x, gameRef.blockSize * 11)], - duration: 1, - curve: Curves.bounceOut, - onComplete: () {}, - )); runnerState = event; sprite.current = RunnerState.glitch; + dead = true; gameRef.die(); break; default: @@ -283,7 +267,7 @@ class Runner extends Component with HasGameRef { } switch (input) { case "up": - if (runnerState == "run") { + if (runnerState == "run" || runnerState == "kick") { event("jump"); } else if (runnerState == "float" && previousState == "jump") { event("double_jump"); @@ -293,7 +277,7 @@ class Runner extends Component with HasGameRef { } break; case "down": - if (runnerState == "run") { + if (runnerState == "run" || runnerState == "kick") { event("duck"); } else if (runnerState == "float" && onTopOfPlatform()) { sprite.clearEffects(); @@ -304,7 +288,7 @@ class Runner extends Component with HasGameRef { } break; case "right": - if (runnerState == "run") { + if (runnerState == "run" || runnerState == "kick") { event("kick"); } break; @@ -332,11 +316,13 @@ class Runner extends Component with HasGameRef { } // If the animation is finished if (sprite.animation?.done() ?? false) { - sprite.animation!.reset(); - if (runnerState == "kick") { - event("run"); + if (!dead) { + sprite.animation!.reset(); + if (runnerState == "kick") { + event("run"); + } + sprite.current = RunnerState.run; } - sprite.current = RunnerState.run; } if (runnerState == "float" || runnerState == "double_jump") { @@ -425,8 +411,11 @@ class Runner extends Component with HasGameRef { continue; } if (intersectState == "none") { - Rect above = Rect.fromLTRB(runnerRect.left, runnerRect.top - 1, - runnerRect.right, runnerRect.bottom); + Rect above = Rect.fromLTRB( + runnerRect.left + sprite.width / 3, + runnerRect.top - 1, + runnerRect.right - sprite.width / 3, + runnerRect.bottom); String aboveIntersect = bugLevel[i].intersect(above); if (aboveIntersect != "none" && (runnerState == "duck" || runnerState == "float")) { @@ -570,24 +559,29 @@ class Runner extends Component with HasGameRef { SpriteAnimation floating = SpriteAnimation.spriteList(floats, stepTime: 0.02, loop: true); - // TODO Falling animations - // List falls = []; - // for (int i = 1; i <= 38; i++) { - // falls.add(Sprite(await Flame.images.load( - // 'runner/run/run00${i < 10 ? "0" + i.toString() : i.toString()}.png'))); - // } - // - // SpriteAnimation falling = - // SpriteAnimation.spriteList(falls, stepTime: 0.02, loop: true); + List falls = []; + for (int i = 1; i <= 38; i++) { + final composition = ImageComposition() + ..add(satellites.elementAt(i - 1), Vector2(0, 0)) + ..add( + await Flame.images.load( + 'runner/run/run00${i < 10 ? "0" + i.toString() : i.toString()}.png'), + Vector2(0, 0)); - SpriteAnimation falling = await loadSpriteAnimation( - 'fall-frames.png', - SpriteAnimationData.sequenced( - amount: 7, - stepTime: 0.1, - textureSize: Vector2(512, 512), - ), - ); + falls.add(Sprite(await composition.compose())); + } + + SpriteAnimation falling = + SpriteAnimation.spriteList(falls, stepTime: 0.02, loop: false); + + // SpriteAnimation falling = await loadSpriteAnimation( + // 'fall-frames.png', + // SpriteAnimationData.sequenced( + // amount: 7, + // stepTime: 0.1, + // textureSize: Vector2(512, 512), + // ), + // ); List dies = []; for (int i = 1; i <= 57; i++) { diff --git a/pubspec.lock b/pubspec.lock index f51826b..21e665b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.5" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" async: dependency: transitive description: @@ -104,6 +118,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.2" flutter_lints: dependency: "direct dev" description: @@ -135,6 +156,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.7" js: dependency: transitive description: @@ -219,6 +247,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.11.1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.0" platform: dependency: transitive description: @@ -329,6 +364,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" sdks: - dart: ">=2.13.0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 593db1b..53fe684 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,10 +32,16 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 +flutter_icons: + android: "launcher_icon" + ios: true + image_path: "assets/icon/head-logo.png" + dev_dependencies: flutter_lints: ^1.0.4 flutter_test: sdk: flutter + flutter_launcher_icons: "^0.9.2" # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png index b749bfe..132d230 100644 Binary files a/web/icons/Icon-192.png and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png index 88cfd48..7919024 100644 Binary files a/web/icons/Icon-512.png and b/web/icons/Icon-512.png differ