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