Skip to content

Commit

Permalink
feat: add countdown and word entry details card
Browse files Browse the repository at this point in the history
  • Loading branch information
jeroen-meijer committed Jul 20, 2020
1 parent e58425e commit c203d07
Show file tree
Hide file tree
Showing 30 changed files with 630 additions and 232 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Run the dict_parser by using the included script:
Here are some things I still need/want to implement.

- Actually being able to play the game.
- Kana-insensitive word search (i.e., refactor and improve `package:kana`)
- Backend integration to play against other players preferably using Firebase.
- More pretty animations.

Expand Down
2 changes: 1 addition & 1 deletion app/lib/app/app_root.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:provider/provider.dart';
import 'package:shiritori/assets/assets.dart';
import 'package:shiritori/backend/backend.dart';
import 'package:shiritori/intl/intl.dart';
import 'package:shiritori/theme/theme.dart';
import 'package:shiritori/ui/routes/routes.dart';
Expand Down
2 changes: 1 addition & 1 deletion app/lib/assets/assets.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export 'dictionaries.dart';
export 'dictionary_files.dart';
export 'fonts.dart';
export 'images.dart';
7 changes: 7 additions & 0 deletions app/lib/assets/dictionary_files.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:shiritori/backend/backend.dart';

const _basePath = 'assets/dicts';

final dictionaryFiles = <Language, String>{
Language.japanese: '$_basePath/dict_ja.json',
};
1 change: 1 addition & 0 deletions app/lib/backend/backend.dart
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export 'models/models.dart';
export 'repositories/repositories.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
import 'package:provider/provider.dart';
import 'package:shared_models/shared_models.dart';
import 'package:shiritori/assets/assets.dart';

export 'package:shared_models/shared_models.dart';

Expand All @@ -27,8 +28,7 @@ class Dictionaries {
}

static Future<Dictionary> _loadDictionaryFromDisk(Language language) async {
final dictText =
await rootBundle.loadString('assets/dicts/dict_${language.code}.json');
final dictText = await rootBundle.loadString(dictionaryFiles[language]);
final dictJson = json.decode(dictText) as Map<String, dynamic>;

final dict = Dictionary.fromJson(dictJson);
Expand Down
41 changes: 41 additions & 0 deletions app/lib/backend/models/game.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
import 'package:provider/provider.dart';
import 'package:shiritori/backend/backend.dart';

class Game {
const Game({
@required this.settings,
@required this.guessesByPlayerIndex,
this.winningPlayerIndex,
}) : assert(settings != null),
assert(guessesByPlayerIndex != null);

factory Game.startNew(GameSettings settings) {
return Game(
settings: settings,
guessesByPlayerIndex: {0: {}, 1: {}},
winningPlayerIndex: null,
);
}

static Game of(BuildContext context) {
return Provider.of<Game>(context, listen: false);
}

final GameSettings settings;
final Map<int, Set<String>> guessesByPlayerIndex;
final int winningPlayerIndex;

Set<String> get allGuesses {
return guessesByPlayerIndex.entries.expand((entry) => entry.value).toSet();
}

bool hasBeenGuessed(String guess) {
return allGuesses.contains(guess);
}

bool isValidGuess(String guess) {
return hasBeenGuessed(guess);
}
}
60 changes: 60 additions & 0 deletions app/lib/backend/models/game_settings.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
import 'package:shiritori/backend/backend.dart';

@immutable
abstract class GameSettings {
const GameSettings({
@required this.dictionary,
@required this.answeringDuration,
@required this.enemyType,
});

final Dictionary dictionary;
final Duration answeringDuration;
final GameEnemyType enemyType;
}

@immutable
class SingleplayerGameSettings implements GameSettings {
const SingleplayerGameSettings({
@required this.dictionary,
@required this.answeringDuration,
});

@override
final Dictionary dictionary;

@override
final Duration answeringDuration;

@override
final GameEnemyType enemyType = GameEnemyType.singleplayer;
}

@immutable
class MultiplayerGameSettings implements GameSettings {
const MultiplayerGameSettings({
@required this.dictionary,
@required this.answeringDuration,
});

@override
final Dictionary dictionary;

@override
final Duration answeringDuration;

@override
final GameEnemyType enemyType = GameEnemyType.multiplayer;
}

enum GameEnemyType {
singleplayer,
multiplayer,
}

extension GameEnemyTypeX on GameEnemyType {
bool get isSingleplayer => this == GameEnemyType.singleplayer;
bool get isMultiplayer => this == GameEnemyType.multiplayer;
}
3 changes: 3 additions & 0 deletions app/lib/backend/models/models.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'dictionaries.dart';
export 'game.dart';
export 'game_settings.dart';
44 changes: 37 additions & 7 deletions app/lib/intl/arb/intl_messages.arb
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
{
"singleplayerTitle": "Singleplayer",
"@singleplayerTitle": {
"description": "The header for the Singleplayer page. Usually, this string should be the same as HomeStrings.singleplayerCardTitle.",
"type": "text",
"placeholders": {}
},
"multiplayerTitle": "Multiplayer",
"@multiplayerTitle": {
"description": "The header for the Multiplayer page. Usually, this string should be the same as HomeStrings.multiplayerCardTitle.",
"type": "text",
"placeholders": {}
},
"getReady": "Get Ready...",
"@getReady": {
"description": "Text indicating a match is about to start and the player needs to start paying attention and get themselves ready.",
"type": "text",
"placeholders": {}
},
"welcomeHeader": "Welcome back,\n{name}.",
"@welcomeHeader": {
"description": "Welcome message displayed at the top of the screen that greets the user.",
Expand Down Expand Up @@ -27,15 +45,15 @@
"type": "text",
"placeholders": {}
},
"quickPlayCardTitle": "Quick Play",
"@quickPlayCardTitle": {
"description": "Title on the Quick Play card that allows the user to start a quick play match.",
"singleplayerCardTitle": "Singleplayer",
"@singleplayerCardTitle": {
"description": "Title on the Singleplayer card that allows the user to start a quick play match.",
"type": "text",
"placeholders": {}
},
"quickPlayCardSubtitle": "PLAY AGAINST CPU",
"@quickPlayCardSubtitle": {
"description": "Subtitle on the Quick Play card that indicates it is a new game mode. Should be all capitals if applicable.",
"singleplayerCardSubtitle": "AGAINST CPU",
"@singleplayerCardSubtitle": {
"description": "Subtitle on the Singleplayer card that indicates it is a new game mode. Should be all capitals if applicable.",
"type": "text",
"placeholders": {}
},
Expand All @@ -45,7 +63,7 @@
"type": "text",
"placeholders": {}
},
"multiplayerCardSubtitle": "PLAY WITH FRIENDS",
"multiplayerCardSubtitle": "WITH FRIENDS",
"@multiplayerCardSubtitle": {
"description": "Subtitle on the Multiplayer card that indicates the user can play with friends. Should be all capitals if applicable.",
"type": "text",
Expand Down Expand Up @@ -75,10 +93,22 @@
"type": "text",
"placeholders": {}
},
"quickPlayButtonTitle": "Quick Play",
"@quickPlayButtonTitle": {
"description": "Text on the Quick Play button that instantly starts a singleplayer CPU match.",
"type": "text",
"placeholders": {}
},
"snackBarConfirmButton": "OK",
"@snackBarConfirmButton": {
"description": "Button text displayed on a snackbar that confirms and dismisses it.",
"type": "text",
"placeholders": {}
},
"back": "BACK",
"@back": {
"description": "Button text displayed on back buttons that confirms and dismisses it. Should be all capitals if applicable.",
"type": "text",
"placeholders": {}
}
}
20 changes: 20 additions & 0 deletions app/lib/intl/strings/game_strings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,24 @@ class GameStrings {
'HomeStrings.singleplayerCardTitle.',
);
}

String get multiplayerTitle {
return Intl.message(
'Multiplayer',
name: 'multiplayerTitle',
desc: 'The header for the Multiplayer page. '
'Usually, this string should be the same as '
'HomeStrings.multiplayerCardTitle.',
);
}

String get getReady {
return Intl.message(
'Get Ready...',
name: 'getReady',
desc: 'Text indicating a match is about to start '
'and the player needs to start paying attention '
'and get themselves ready.',
);
}
}
5 changes: 3 additions & 2 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:shiritori/app/app.dart';
import 'package:shiritori/backend/backend.dart';

import 'assets/assets.dart';

void main() async {
log('Initializing bindings...');

final initStopwatch = Stopwatch()..start();
WidgetsFlutterBinding.ensureInitialized();
log('Loading background image...');
final backgroundImage = await Images.loadBackground();
log('Loading dictionaries...');
final dictionaries = await Dictionaries.loadFromDisk();
initStopwatch.stop();

final seconds = (initStopwatch.elapsedMilliseconds / 1000).toStringAsFixed(3);
log('Initialization done. (took $seconds seconds)');

Expand Down
30 changes: 23 additions & 7 deletions app/lib/theme/theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ abstract class AppTheme {
static ThemeData get themeDataLight {
return ThemeData(
buttonTheme: buttonTheme,
canvasColor: veryLightGrey,
cardTheme: cardTheme,
dividerTheme: dividerTheme,
fontFamily: Fonts.hurmeGeometricSans,
Expand Down Expand Up @@ -36,19 +37,19 @@ abstract class AppTheme {
static const _letterSpacing = -0.5;
static const textTheme = TextTheme(
headline1: TextStyle(
color: white,
color: blue,
fontWeight: FontWeight.bold,
height: 1.0,
letterSpacing: _letterSpacing,
),
headline2: TextStyle(
color: white,
color: blue,
height: 1.0,
fontWeight: FontWeight.bold,
letterSpacing: _letterSpacing,
),
headline3: TextStyle(
color: white,
color: blue,
height: 1.0,
fontWeight: FontWeight.bold,
letterSpacing: _letterSpacing,
Expand All @@ -67,25 +68,40 @@ abstract class AppTheme {
),
headline6: TextStyle(
color: blue,
fontSize: 22,
height: 1.0,
fontWeight: FontWeight.bold,
letterSpacing: _letterSpacing,
),
overline: TextStyle(
bodyText1: TextStyle(
fontSize: 20,
),
bodyText2: TextStyle(
fontSize: 18,
),
subtitle1: TextStyle(
color: blue,
fontSize: 20,
fontWeight: FontWeight.bold,
letterSpacing: _letterSpacing,
),
subtitle1: TextStyle(
subtitle2: TextStyle(
color: blue,
fontSize: 18,
fontWeight: FontWeight.bold,
letterSpacing: _letterSpacing,
),
subtitle2: TextStyle(
caption: TextStyle(
color: blue,
fontSize: 16,
fontWeight: FontWeight.bold,
letterSpacing: _letterSpacing,
),
overline: TextStyle(
color: blue,
fontSize: 14,
letterSpacing: _letterSpacing,
),
);

static const white = Color(0xFFFFFFFF);
Expand Down Expand Up @@ -114,7 +130,7 @@ abstract class AppTheme {

static const colorSingleplayer = orange;

static const elevationDefault = 18.0;
static const elevationDefault = 8.0;
static const elevationDisabled = elevationDefault / 3;
static const radiusCardDefault = Radius.circular(16.0);
static const shapeDefault = RoundedRectangleBorder(
Expand Down
Loading

0 comments on commit c203d07

Please sign in to comment.