Added the Main Menu #12, Mobile Icons #18. Runner animations finished in previous commit #6. Also implemented text scaling for different devices.
@ -3,7 +3,7 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<application
|
<application
|
||||||
android:label="firo_runner"
|
android:label="firo_runner"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/launcher_icon">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
BIN
android/app/src/main/res/mipmap-hdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
assets/icon/head-logo.png
Normal file
After Width: | Height: | Size: 170 KiB |
BIN
assets/images/button-new.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
assets/images/mm3.gif
Normal file
After Width: | Height: | Size: 4.0 MiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 16 KiB |
@ -1,4 +1,5 @@
|
|||||||
import 'package:firo_runner/holder.dart';
|
import 'package:firo_runner/holder.dart';
|
||||||
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame/flame.dart';
|
import 'package:flame/flame.dart';
|
||||||
|
|
||||||
import 'package:firo_runner/coin.dart';
|
import 'package:firo_runner/coin.dart';
|
||||||
@ -8,10 +9,49 @@ import 'package:firo_runner/platform.dart';
|
|||||||
|
|
||||||
class CoinHolder extends Holder {
|
class CoinHolder extends Holder {
|
||||||
late Image coin;
|
late Image coin;
|
||||||
|
late SpriteAnimationGroupComponent sprite;
|
||||||
|
late MyGame personalGameRef;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future load() async {
|
Future load() async {
|
||||||
coin = await Flame.images.load("coin-frames.png");
|
coin = await Flame.images.load("coin-frames.png");
|
||||||
|
SpriteAnimation normal = SpriteAnimation.fromFrameData(
|
||||||
|
coin,
|
||||||
|
SpriteAnimationData.sequenced(
|
||||||
|
amount: 12,
|
||||||
|
stepTime: 0.1,
|
||||||
|
textureSize: Vector2(512, 512),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
sprite = SpriteAnimationGroupComponent(
|
||||||
|
animations: {
|
||||||
|
CoinState.normal: normal,
|
||||||
|
},
|
||||||
|
current: CoinState.normal,
|
||||||
|
);
|
||||||
|
|
||||||
|
sprite.changePriorityWithoutResorting(COIN_PRIORITY);
|
||||||
|
|
||||||
|
sprite.size = Vector2(20, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPersonalGameRef(MyGame gameRef) {
|
||||||
|
personalGameRef = gameRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void resize(Vector2 newSize, double xRatio, double yRatio) {
|
||||||
|
super.resize(newSize, xRatio, yRatio);
|
||||||
|
sprite.x *= xRatio;
|
||||||
|
sprite.y *= yRatio;
|
||||||
|
sprite.width *= xRatio;
|
||||||
|
sprite.height *= yRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderCoinScore(Canvas c) {
|
||||||
|
sprite.position = Vector2(personalGameRef.size.x - 33, 10);
|
||||||
|
sprite.render(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image getCoin() {
|
Image getCoin() {
|
||||||
|
@ -12,22 +12,29 @@ class LoseMenuOverlay extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
double width = MediaQuery.of(context).size.width;
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: game.viewport.canvasSize.y,
|
height: game.viewport.canvasSize.y,
|
||||||
width: game.viewport.canvasSize.x,
|
width: game.viewport.canvasSize.x,
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: AssetImage('assets/images/overlay100.png'),
|
image: lossImage,
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.fill,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Material(
|
||||||
'Score: ' + game.gameState.getPlayerScore().toString(),
|
type: MaterialType.transparency,
|
||||||
style: overlayText,
|
child: Text(
|
||||||
|
'Score: ${game.gameState.getPlayerScore()}',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: width * 0.05,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 32.0),
|
const SizedBox(height: 32.0),
|
||||||
Row(
|
Row(
|
||||||
@ -40,21 +47,24 @@ class LoseMenuOverlay extends StatelessWidget {
|
|||||||
elevation: 8.0,
|
elevation: 8.0,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
image: DecorationImage(
|
image:
|
||||||
image: AssetImage('assets/images/button.png'),
|
DecorationImage(image: buttonImage, fit: BoxFit.fill),
|
||||||
fit: BoxFit.fill),
|
|
||||||
),
|
),
|
||||||
child: const Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
" Main Menu ",
|
" Main Menu ",
|
||||||
style: overlayText,
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: width * 0.03,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// ),
|
// ),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Go to the Main Menu
|
// Go to the Main Menu
|
||||||
|
game.mainMenu();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@ -67,15 +77,17 @@ class LoseMenuOverlay extends StatelessWidget {
|
|||||||
elevation: 8.0,
|
elevation: 8.0,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
image: DecorationImage(
|
image:
|
||||||
image: AssetImage('assets/images/button.png'),
|
DecorationImage(image: buttonImage, fit: BoxFit.fill),
|
||||||
fit: BoxFit.fill),
|
|
||||||
),
|
),
|
||||||
child: const Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
" Replay ",
|
" Replay ",
|
||||||
style: overlayText,
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: width * 0.03,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
168
lib/main.dart
@ -29,8 +29,10 @@ import 'package:flutter/foundation.dart' show kIsWeb;
|
|||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
import 'package:firo_runner/lose_menu_overlay.dart';
|
import 'package:firo_runner/lose_menu_overlay.dart';
|
||||||
|
import 'package:firo_runner/main_menu_overlay.dart';
|
||||||
|
|
||||||
const COLOR = Color(0xFFDDC0A3);
|
const COLOR = Color(0xFFDDC0A3);
|
||||||
|
const int LOADING_TIME = 2000000;
|
||||||
|
|
||||||
const LEVEL2 = 10000000;
|
const LEVEL2 = 10000000;
|
||||||
const LEVEL3 = 20000000;
|
const LEVEL3 = 20000000;
|
||||||
@ -50,24 +52,47 @@ const WIRE_PRIORITY = 25;
|
|||||||
const FIREWORK_PRIORITY = 15;
|
const FIREWORK_PRIORITY = 15;
|
||||||
const WINDOW_PRIORITY = 10;
|
const WINDOW_PRIORITY = 10;
|
||||||
|
|
||||||
const overlayText = TextStyle(
|
// const overlayText = TextStyle(
|
||||||
fontSize: 30,
|
// fontSize: 30,
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
);
|
// );
|
||||||
|
|
||||||
|
const AssetImage mainMenuImage = AssetImage('assets/images/mm3.gif');
|
||||||
|
const AssetImage lossImage = AssetImage('assets/images/overlay100.png');
|
||||||
|
const AssetImage buttonImage = AssetImage('assets/images/button-new.png');
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await Flame.device.fullScreen();
|
await Flame.device.fullScreen();
|
||||||
await Flame.device.setLandscape();
|
await Flame.device.setLandscape();
|
||||||
final myGame = MyGame();
|
final myGame = MyGame();
|
||||||
runApp(GameWidget<MyGame>(
|
runApp(MaterialApp(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
home: GameWidget<MyGame>(
|
||||||
game: myGame,
|
game: myGame,
|
||||||
overlayBuilderMap: {
|
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) {
|
'gameOver': (_, myGame) {
|
||||||
return LoseMenuOverlay(game: myGame);
|
return LoseMenuOverlay(game: myGame);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int getNearestPlatform(int level) {
|
int getNearestPlatform(int level) {
|
||||||
@ -110,6 +135,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
late Wire wire;
|
late Wire wire;
|
||||||
late TextComponent _distance;
|
late TextComponent _distance;
|
||||||
late TextComponent _coins;
|
late TextComponent _coins;
|
||||||
|
int startLoading = 0;
|
||||||
|
|
||||||
MyGame() : super() {
|
MyGame() : super() {
|
||||||
viewport.resize(Vector2(1920, 1080));
|
viewport.resize(Vector2(1920, 1080));
|
||||||
@ -125,6 +151,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
platformHolder = PlatformHolder();
|
platformHolder = PlatformHolder();
|
||||||
await platformHolder.load();
|
await platformHolder.load();
|
||||||
coinHolder = CoinHolder();
|
coinHolder = CoinHolder();
|
||||||
|
coinHolder.setPersonalGameRef(this);
|
||||||
await coinHolder.load();
|
await coinHolder.load();
|
||||||
wireHolder = WireHolder();
|
wireHolder = WireHolder();
|
||||||
await wireHolder.load();
|
await wireHolder.load();
|
||||||
@ -142,19 +169,22 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
runner = Runner();
|
runner = Runner();
|
||||||
await runner.load(loadSpriteAnimation);
|
await runner.load(loadSpriteAnimation);
|
||||||
|
|
||||||
if (!kIsWeb) {
|
|
||||||
playMusic();
|
|
||||||
}
|
|
||||||
loaded = true;
|
loaded = true;
|
||||||
_distance = TextComponent("Distance: 0",
|
_distance = TextComponent("Distance: 0",
|
||||||
position: Vector2(size.x - 100, 10), textRenderer: scoresPaint)
|
position: Vector2(size.x - 100, 10), textRenderer: scoresPaint)
|
||||||
..anchor = Anchor.topRight;
|
..anchor = Anchor.topRight;
|
||||||
_distance.changePriorityWithoutResorting(OVERLAY_PRIORITY);
|
_distance.changePriorityWithoutResorting(OVERLAY_PRIORITY);
|
||||||
_coins = TextComponent("Coins: 0",
|
_coins = TextComponent(": 0",
|
||||||
position: Vector2(size.x - 10, 10), textRenderer: scoresPaint)
|
position: Vector2(size.x - 35, 10), textRenderer: scoresPaint)
|
||||||
..anchor = Anchor.topRight;
|
..anchor = Anchor.topRight;
|
||||||
_coins.changePriorityWithoutResorting(OVERLAY_PRIORITY);
|
_coins.changePriorityWithoutResorting(OVERLAY_PRIORITY);
|
||||||
|
overlays.add("gameOver");
|
||||||
|
overlays.remove('gameOver');
|
||||||
|
overlays.add("mainMenu");
|
||||||
|
overlays.add('loading');
|
||||||
setUp();
|
setUp();
|
||||||
|
gameState.setPaused();
|
||||||
|
startLoading = DateTime.now().microsecondsSinceEpoch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void playMusic() {
|
void playMusic() {
|
||||||
@ -248,56 +278,56 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
|
|
||||||
bool shouldReset = false;
|
bool shouldReset = false;
|
||||||
|
|
||||||
late Socket socket;
|
// late Socket socket;
|
||||||
void dataHandler(data) {
|
// void dataHandler(data) {
|
||||||
print(new String.fromCharCodes(data).trim());
|
// print(new String.fromCharCodes(data).trim());
|
||||||
}
|
|
||||||
|
|
||||||
void errorHandler(error, StackTrace trace) {
|
|
||||||
print(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
void doneHandler() {
|
|
||||||
socket.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> 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: <String, String>{
|
|
||||||
// 'Content-Type': 'application/json; charset=UTF-8',
|
|
||||||
// },
|
|
||||||
// body: jsonEncode(<String, String>{
|
|
||||||
// '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);
|
// void errorHandler(error, StackTrace trace) {
|
||||||
|
// print(error);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void doneHandler() {
|
||||||
|
// socket.destroy();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> 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) {
|
// } catch (e) {
|
||||||
// print(e);
|
// print(e);
|
||||||
// }
|
// }
|
||||||
}
|
// // try {
|
||||||
|
// // final response = await http.post(
|
||||||
|
// // Uri.parse('http://10.0.0.224:50017'),
|
||||||
|
// // headers: <String, String>{
|
||||||
|
// // 'Content-Type': 'application/json; charset=UTF-8',
|
||||||
|
// // },
|
||||||
|
// // body: jsonEncode(<String, String>{
|
||||||
|
// // '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<void> displayLoss() async {
|
Future<void> displayLoss() async {
|
||||||
if (!(runner.sprite.animation?.done() ?? false) &&
|
if (!(runner.sprite.animation?.done() ?? false) &&
|
||||||
@ -305,14 +335,20 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
firstDeath) {
|
firstDeath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await connectServer();
|
// await connectServer();
|
||||||
firstDeath = false;
|
firstDeath = false;
|
||||||
overlays.add('gameOver');
|
overlays.add('gameOver');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mainMenu() {
|
||||||
|
overlays.remove('gameOver');
|
||||||
|
overlays.add('mainMenu');
|
||||||
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
runner.sprite.animation!.reset();
|
runner.sprite.animation!.reset();
|
||||||
overlays.remove('gameOver');
|
overlays.remove('gameOver');
|
||||||
|
overlays.remove('mainMenu');
|
||||||
shouldReset = false;
|
shouldReset = false;
|
||||||
components.clear();
|
components.clear();
|
||||||
setUp();
|
setUp();
|
||||||
@ -349,6 +385,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void render(Canvas canvas) {
|
void render(Canvas canvas) {
|
||||||
|
if (!overlays.isActive('mainMenu')) {
|
||||||
circuitBackground.render(canvas);
|
circuitBackground.render(canvas);
|
||||||
fireworks.renderText(canvas);
|
fireworks.renderText(canvas);
|
||||||
super.render(canvas);
|
super.render(canvas);
|
||||||
@ -358,10 +395,19 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
fpsCount.toString(),
|
fpsCount.toString(),
|
||||||
Vector2(0, 0),
|
Vector2(0, 0),
|
||||||
);
|
);
|
||||||
|
coinHolder.renderCoinScore(canvas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void update(double dt) {
|
void update(double dt) {
|
||||||
|
if (overlays.isActive('loading') &&
|
||||||
|
(DateTime.now().microsecondsSinceEpoch - startLoading) > LOADING_TIME) {
|
||||||
|
overlays.remove('loading');
|
||||||
|
if (!kIsWeb) {
|
||||||
|
playMusic();
|
||||||
|
}
|
||||||
|
}
|
||||||
fireworks.update(dt);
|
fireworks.update(dt);
|
||||||
platformHolder.removePast(this);
|
platformHolder.removePast(this);
|
||||||
coinHolder.removePast(this);
|
coinHolder.removePast(this);
|
||||||
@ -381,8 +427,10 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
wallHolder.update(dt);
|
wallHolder.update(dt);
|
||||||
|
|
||||||
_distance.text = "Distance: ${gameState.getPlayerDistance()}";
|
_distance.text = "Distance: ${gameState.getPlayerDistance()}";
|
||||||
_coins.text = "Coins: ${gameState.numCoins}";
|
_coins.text = " ${gameState.numCoins}";
|
||||||
if (shouldReset && !overlays.isActive('gameOver')) {
|
if (shouldReset &&
|
||||||
|
!overlays.isActive('gameOver') &&
|
||||||
|
!overlays.isActive('mainMenu')) {
|
||||||
displayLoss();
|
displayLoss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
142
lib/main_menu_overlay.dart
Normal file
@ -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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -177,16 +177,11 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
}
|
}
|
||||||
previousState = runnerState;
|
previousState = runnerState;
|
||||||
sprite.clearEffects();
|
sprite.clearEffects();
|
||||||
level = 11;
|
|
||||||
sprite.addEffect(MoveEffect(
|
|
||||||
path: [Vector2(sprite.position.x, gameRef.blockSize * 11)],
|
|
||||||
duration: 2,
|
|
||||||
curve: Curves.bounceOut,
|
|
||||||
onComplete: () {},
|
|
||||||
));
|
|
||||||
runnerState = event;
|
runnerState = event;
|
||||||
sprite.current = RunnerState.die;
|
sprite.current = RunnerState.die;
|
||||||
|
dead = true;
|
||||||
gameRef.die();
|
gameRef.die();
|
||||||
|
sprite.addEffect(getFallingEffect());
|
||||||
break;
|
break;
|
||||||
case "electrocute":
|
case "electrocute":
|
||||||
if (dead) {
|
if (dead) {
|
||||||
@ -194,16 +189,11 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
}
|
}
|
||||||
previousState = runnerState;
|
previousState = runnerState;
|
||||||
sprite.clearEffects();
|
sprite.clearEffects();
|
||||||
level = 11;
|
|
||||||
sprite.addEffect(MoveEffect(
|
|
||||||
path: [Vector2(sprite.position.x, gameRef.blockSize * 11)],
|
|
||||||
duration: 1,
|
|
||||||
curve: Curves.bounceOut,
|
|
||||||
onComplete: () {},
|
|
||||||
));
|
|
||||||
runnerState = event;
|
runnerState = event;
|
||||||
sprite.current = RunnerState.electrocute;
|
sprite.current = RunnerState.electrocute;
|
||||||
|
dead = true;
|
||||||
gameRef.die();
|
gameRef.die();
|
||||||
|
sprite.addEffect(getFallingEffect());
|
||||||
break;
|
break;
|
||||||
case "glitch":
|
case "glitch":
|
||||||
if (dead) {
|
if (dead) {
|
||||||
@ -211,15 +201,9 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
}
|
}
|
||||||
previousState = runnerState;
|
previousState = runnerState;
|
||||||
sprite.clearEffects();
|
sprite.clearEffects();
|
||||||
level = 11;
|
|
||||||
sprite.addEffect(MoveEffect(
|
|
||||||
path: [Vector2(sprite.position.x, gameRef.blockSize * 11)],
|
|
||||||
duration: 1,
|
|
||||||
curve: Curves.bounceOut,
|
|
||||||
onComplete: () {},
|
|
||||||
));
|
|
||||||
runnerState = event;
|
runnerState = event;
|
||||||
sprite.current = RunnerState.glitch;
|
sprite.current = RunnerState.glitch;
|
||||||
|
dead = true;
|
||||||
gameRef.die();
|
gameRef.die();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -283,7 +267,7 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
}
|
}
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case "up":
|
case "up":
|
||||||
if (runnerState == "run") {
|
if (runnerState == "run" || runnerState == "kick") {
|
||||||
event("jump");
|
event("jump");
|
||||||
} else if (runnerState == "float" && previousState == "jump") {
|
} else if (runnerState == "float" && previousState == "jump") {
|
||||||
event("double_jump");
|
event("double_jump");
|
||||||
@ -293,7 +277,7 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "down":
|
case "down":
|
||||||
if (runnerState == "run") {
|
if (runnerState == "run" || runnerState == "kick") {
|
||||||
event("duck");
|
event("duck");
|
||||||
} else if (runnerState == "float" && onTopOfPlatform()) {
|
} else if (runnerState == "float" && onTopOfPlatform()) {
|
||||||
sprite.clearEffects();
|
sprite.clearEffects();
|
||||||
@ -304,7 +288,7 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "right":
|
case "right":
|
||||||
if (runnerState == "run") {
|
if (runnerState == "run" || runnerState == "kick") {
|
||||||
event("kick");
|
event("kick");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -332,12 +316,14 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
}
|
}
|
||||||
// If the animation is finished
|
// If the animation is finished
|
||||||
if (sprite.animation?.done() ?? false) {
|
if (sprite.animation?.done() ?? false) {
|
||||||
|
if (!dead) {
|
||||||
sprite.animation!.reset();
|
sprite.animation!.reset();
|
||||||
if (runnerState == "kick") {
|
if (runnerState == "kick") {
|
||||||
event("run");
|
event("run");
|
||||||
}
|
}
|
||||||
sprite.current = RunnerState.run;
|
sprite.current = RunnerState.run;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (runnerState == "float" || runnerState == "double_jump") {
|
if (runnerState == "float" || runnerState == "double_jump") {
|
||||||
if (onTopOfPlatform()) {
|
if (onTopOfPlatform()) {
|
||||||
@ -425,8 +411,11 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (intersectState == "none") {
|
if (intersectState == "none") {
|
||||||
Rect above = Rect.fromLTRB(runnerRect.left, runnerRect.top - 1,
|
Rect above = Rect.fromLTRB(
|
||||||
runnerRect.right, runnerRect.bottom);
|
runnerRect.left + sprite.width / 3,
|
||||||
|
runnerRect.top - 1,
|
||||||
|
runnerRect.right - sprite.width / 3,
|
||||||
|
runnerRect.bottom);
|
||||||
String aboveIntersect = bugLevel[i].intersect(above);
|
String aboveIntersect = bugLevel[i].intersect(above);
|
||||||
if (aboveIntersect != "none" &&
|
if (aboveIntersect != "none" &&
|
||||||
(runnerState == "duck" || runnerState == "float")) {
|
(runnerState == "duck" || runnerState == "float")) {
|
||||||
@ -570,24 +559,29 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
SpriteAnimation floating =
|
SpriteAnimation floating =
|
||||||
SpriteAnimation.spriteList(floats, stepTime: 0.02, loop: true);
|
SpriteAnimation.spriteList(floats, stepTime: 0.02, loop: true);
|
||||||
|
|
||||||
// TODO Falling animations
|
List<Sprite> falls = [];
|
||||||
// List<Sprite> falls = [];
|
for (int i = 1; i <= 38; i++) {
|
||||||
// for (int i = 1; i <= 38; i++) {
|
final composition = ImageComposition()
|
||||||
// falls.add(Sprite(await Flame.images.load(
|
..add(satellites.elementAt(i - 1), Vector2(0, 0))
|
||||||
// 'runner/run/run00${i < 10 ? "0" + i.toString() : i.toString()}.png')));
|
..add(
|
||||||
// }
|
await Flame.images.load(
|
||||||
//
|
'runner/run/run00${i < 10 ? "0" + i.toString() : i.toString()}.png'),
|
||||||
// SpriteAnimation falling =
|
Vector2(0, 0));
|
||||||
// SpriteAnimation.spriteList(falls, stepTime: 0.02, loop: true);
|
|
||||||
|
|
||||||
SpriteAnimation falling = await loadSpriteAnimation(
|
falls.add(Sprite(await composition.compose()));
|
||||||
'fall-frames.png',
|
}
|
||||||
SpriteAnimationData.sequenced(
|
|
||||||
amount: 7,
|
SpriteAnimation falling =
|
||||||
stepTime: 0.1,
|
SpriteAnimation.spriteList(falls, stepTime: 0.02, loop: false);
|
||||||
textureSize: Vector2(512, 512),
|
|
||||||
),
|
// SpriteAnimation falling = await loadSpriteAnimation(
|
||||||
);
|
// 'fall-frames.png',
|
||||||
|
// SpriteAnimationData.sequenced(
|
||||||
|
// amount: 7,
|
||||||
|
// stepTime: 0.1,
|
||||||
|
// textureSize: Vector2(512, 512),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
|
||||||
List<Sprite> dies = [];
|
List<Sprite> dies = [];
|
||||||
for (int i = 1; i <= 57; i++) {
|
for (int i = 1; i <= 57; i++) {
|
||||||
|
51
pubspec.lock
@ -1,6 +1,20 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
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:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -104,6 +118,13 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
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:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -135,6 +156,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
|
image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.7"
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -219,6 +247,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.1"
|
version: "1.11.1"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.3.0"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -329,6 +364,20 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
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:
|
sdks:
|
||||||
dart: ">=2.13.0 <3.0.0"
|
dart: ">=2.14.0 <3.0.0"
|
||||||
flutter: ">=2.0.0"
|
flutter: ">=2.0.0"
|
||||||
|
@ -32,10 +32,16 @@ dependencies:
|
|||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
|
|
||||||
|
flutter_icons:
|
||||||
|
android: "launcher_icon"
|
||||||
|
ios: true
|
||||||
|
image_path: "assets/icon/head-logo.png"
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^1.0.4
|
flutter_lints: ^1.0.4
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_launcher_icons: "^0.9.2"
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 72 KiB |