google_play_games_manager.dart 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. import 'package:games_services/games_services.dart';
  2. import 'dart:async';
  3. import 'dart:io';
  4. /// Manages Google Play Games Services integration
  5. class GooglePlayGamesManager {
  6. static GooglePlayGamesManager? _instance;
  7. static GooglePlayGamesManager get instance {
  8. _instance ??= GooglePlayGamesManager._internal();
  9. return _instance!;
  10. }
  11. GooglePlayGamesManager._internal();
  12. // Feature flag to enable/disable Google Play Games Services
  13. static const bool _isEnabled = false; // Set to true to enable Google Play Games
  14. bool _isInitialized = false;
  15. bool _isSignedIn = false;
  16. String? _playerId;
  17. String? _playerName;
  18. // Achievement IDs - These need to be configured in Google Play Console
  19. static const String achievementFirstBubble = 'achievement_first_bubble';
  20. static const String achievement100Bubbles = 'achievement_100_bubbles';
  21. static const String achievement1000Bubbles = 'achievement_1000_bubbles';
  22. static const String achievement5000Bubbles = 'achievement_5000_bubbles';
  23. static const String achievementZenMaster = 'achievement_zen_master';
  24. static const String achievementSpeedDemon = 'achievement_speed_demon';
  25. static const String achievementPerfectSession = 'achievement_perfect_session';
  26. // Leaderboard IDs - These need to be configured in Google Play Console
  27. static const String leaderboardHighScore = 'leaderboard_high_score';
  28. static const String leaderboardZenMode = 'leaderboard_zen_mode';
  29. static const String leaderboardTotalBubbles = 'leaderboard_total_bubbles';
  30. static const String leaderboardLongestSession = 'leaderboard_longest_session';
  31. /// Initialize Google Play Games Services
  32. Future<bool> initialize() async {
  33. if (!_isEnabled) {
  34. print('Google Play Games Services is disabled via feature flag');
  35. return false;
  36. }
  37. if (_isInitialized) return true;
  38. try {
  39. // Only available on Android
  40. if (!Platform.isAndroid) {
  41. print('Google Play Games Services only available on Android');
  42. return false;
  43. }
  44. _isInitialized = true;
  45. return true;
  46. } catch (e) {
  47. print('Error initializing Google Play Games: $e');
  48. return false;
  49. }
  50. }
  51. /// Sign in to Google Play Games
  52. Future<bool> signIn() async {
  53. if (!_isEnabled) {
  54. print('Google Play Games Services is disabled via feature flag');
  55. return false;
  56. }
  57. if (!_isInitialized) {
  58. await initialize();
  59. }
  60. try {
  61. final result = await GamesServices.signIn();
  62. _isSignedIn = result != null && result.isNotEmpty;
  63. if (_isSignedIn) {
  64. _playerId = result;
  65. print('Successfully signed in to Google Play Games: $_playerId');
  66. // Get player name
  67. try {
  68. final playerName = await GamesServices.getPlayerName();
  69. _playerName = playerName;
  70. print('Player name: $_playerName');
  71. } catch (e) {
  72. print('Could not get player name: $e');
  73. }
  74. }
  75. return _isSignedIn;
  76. } catch (e) {
  77. print('Error signing in to Google Play Games: $e');
  78. _isSignedIn = false;
  79. return false;
  80. }
  81. }
  82. /// Sign out from Google Play Games
  83. Future<void> signOut() async {
  84. try {
  85. // Note: games_services package doesn't have a signOut method
  86. // We'll just reset our local state
  87. _isSignedIn = false;
  88. _playerId = null;
  89. _playerName = null;
  90. print('Successfully signed out from Google Play Games');
  91. } catch (e) {
  92. print('Error signing out from Google Play Games: $e');
  93. }
  94. }
  95. /// Check if signed in
  96. bool get isSignedIn => _isSignedIn;
  97. /// Check if Google Play Games is enabled via feature flag
  98. bool get isEnabled => _isEnabled;
  99. /// Get player ID
  100. String? get playerId => _playerId;
  101. /// Get player name
  102. String? get playerName => _playerName;
  103. /// Submit score to leaderboard
  104. Future<bool> submitScore(String leaderboardId, int score) async {
  105. if (!_isEnabled) {
  106. print('Google Play Games Services is disabled via feature flag');
  107. return false;
  108. }
  109. if (!_isSignedIn) {
  110. print('Not signed in to Google Play Games');
  111. return false;
  112. }
  113. try {
  114. await GamesServices.submitScore(
  115. score: Score(
  116. androidLeaderboardID: leaderboardId,
  117. value: score,
  118. ),
  119. );
  120. print('Score $score submitted to leaderboard $leaderboardId');
  121. return true;
  122. } catch (e) {
  123. print('Error submitting score: $e');
  124. return false;
  125. }
  126. }
  127. /// Show leaderboards
  128. Future<void> showLeaderboards() async {
  129. if (!_isEnabled) {
  130. print('Google Play Games Services is disabled via feature flag');
  131. return;
  132. }
  133. if (!_isSignedIn) {
  134. print('Not signed in to Google Play Games');
  135. return;
  136. }
  137. try {
  138. await GamesServices.showLeaderboards();
  139. } catch (e) {
  140. print('Error showing leaderboards: $e');
  141. }
  142. }
  143. /// Show specific leaderboard
  144. Future<void> showLeaderboard(String leaderboardId) async {
  145. if (!_isEnabled) {
  146. print('Google Play Games Services is disabled via feature flag');
  147. return;
  148. }
  149. if (!_isSignedIn) {
  150. print('Not signed in to Google Play Games');
  151. return;
  152. }
  153. try {
  154. await GamesServices.showLeaderboards(
  155. androidLeaderboardID: leaderboardId,
  156. );
  157. } catch (e) {
  158. print('Error showing leaderboard: $e');
  159. }
  160. }
  161. /// Unlock achievement
  162. Future<bool> unlockAchievement(String achievementId) async {
  163. if (!_isEnabled) {
  164. print('Google Play Games Services is disabled via feature flag');
  165. return false;
  166. }
  167. if (!_isSignedIn) {
  168. print('Not signed in to Google Play Games');
  169. return false;
  170. }
  171. try {
  172. await GamesServices.unlock(
  173. achievement: Achievement(
  174. androidID: achievementId,
  175. ),
  176. );
  177. print('Achievement $achievementId unlocked');
  178. return true;
  179. } catch (e) {
  180. print('Error unlocking achievement: $e');
  181. return false;
  182. }
  183. }
  184. /// Increment achievement (for incremental achievements)
  185. Future<bool> incrementAchievement(String achievementId, int steps) async {
  186. if (!_isEnabled) {
  187. print('Google Play Games Services is disabled via feature flag');
  188. return false;
  189. }
  190. if (!_isSignedIn) {
  191. print('Not signed in to Google Play Games');
  192. return false;
  193. }
  194. try {
  195. await GamesServices.increment(
  196. achievement: Achievement(
  197. androidID: achievementId,
  198. steps: steps,
  199. ),
  200. );
  201. print('Achievement $achievementId incremented by $steps steps');
  202. return true;
  203. } catch (e) {
  204. print('Error incrementing achievement: $e');
  205. return false;
  206. }
  207. }
  208. /// Show achievements
  209. Future<void> showAchievements() async {
  210. if (!_isEnabled) {
  211. print('Google Play Games Services is disabled via feature flag');
  212. return;
  213. }
  214. if (!_isSignedIn) {
  215. print('Not signed in to Google Play Games');
  216. return;
  217. }
  218. try {
  219. await GamesServices.showAchievements();
  220. } catch (e) {
  221. print('Error showing achievements: $e');
  222. }
  223. }
  224. /// Check achievement-related milestones for bubble popping
  225. Future<void> checkBubbleAchievements(int totalBubbles) async {
  226. if (!_isEnabled) return;
  227. if (!_isSignedIn) return;
  228. // First bubble achievement
  229. if (totalBubbles >= 1) {
  230. await unlockAchievement(achievementFirstBubble);
  231. }
  232. // 100 bubbles achievement
  233. if (totalBubbles >= 100) {
  234. await unlockAchievement(achievement100Bubbles);
  235. }
  236. // 1000 bubbles achievement
  237. if (totalBubbles >= 1000) {
  238. await unlockAchievement(achievement1000Bubbles);
  239. }
  240. // 5000 bubbles achievement
  241. if (totalBubbles >= 5000) {
  242. await unlockAchievement(achievement5000Bubbles);
  243. }
  244. }
  245. /// Check zen mode achievements
  246. Future<void> checkZenModeAchievements(double sessionTime) async {
  247. if (!_isEnabled) return;
  248. if (!_isSignedIn) return;
  249. // Zen master achievement (10 minutes in zen mode)
  250. if (sessionTime >= 600) {
  251. await unlockAchievement(achievementZenMaster);
  252. }
  253. }
  254. /// Check score-based achievements
  255. Future<void> checkScoreAchievements(int score, double timeToReachScore) async {
  256. if (!_isEnabled) return;
  257. if (!_isSignedIn) return;
  258. // Speed demon achievement (reach 1000 points in under 2 minutes)
  259. if (score >= 1000 && timeToReachScore <= 120) {
  260. await unlockAchievement(achievementSpeedDemon);
  261. }
  262. }
  263. /// Submit various scores to leaderboards
  264. Future<void> submitGameResults({
  265. required int finalScore,
  266. required bool isZenMode,
  267. required int totalBubblesPopped,
  268. required double sessionLength,
  269. }) async {
  270. if (!_isEnabled) return;
  271. if (!_isSignedIn) return;
  272. // Submit to appropriate leaderboards
  273. if (isZenMode) {
  274. await submitScore(leaderboardZenMode, sessionLength.round());
  275. } else {
  276. await submitScore(leaderboardHighScore, finalScore);
  277. }
  278. await submitScore(leaderboardTotalBubbles, totalBubblesPopped);
  279. await submitScore(leaderboardLongestSession, sessionLength.round());
  280. // Check achievements
  281. await checkBubbleAchievements(totalBubblesPopped);
  282. if (isZenMode) {
  283. await checkZenModeAchievements(sessionLength);
  284. } else {
  285. await checkScoreAchievements(finalScore, sessionLength);
  286. }
  287. }
  288. }