MIF_E31222389/lib/game/level2_islam.dart

1295 lines
45 KiB
Dart

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:math';
import 'package:flame/game.dart';
import '../landing_page.dart';
import 'level3_islam.dart';
import '../utils/level_manager.dart';
import '../utils/audio_manager.dart';
import 'package:permainan_kata_anak_sd/services/database_service.dart';
import 'package:firebase_auth/firebase_auth.dart';
// Pindahkan enum ke level atas
enum WordDirection { horizontal, vertical, diagonal }
// Pindahkan class ke level atas
class PlacedWord {
final String word;
final int startRow;
final int startCol;
final WordDirection direction;
PlacedWord(
{required this.word,
required this.startRow,
required this.startCol,
required this.direction});
}
class Level2Islam extends StatefulWidget {
const Level2Islam({Key? key}) : super(key: key);
@override
_Level2IslamState createState() => _Level2IslamState();
}
class _Level2IslamState extends State<Level2Islam> {
// Definisikan gridSize sebagai konstanta kelas
static const int GRID_SIZE = 15;
static const int MAX_TIME = 300; // 5 menit dalam detik
late Timer timer;
int seconds = MAX_TIME;
int elapsedSeconds =
0; // Tambah variabel untuk menghitung waktu yang digunakan
int score = 0;
// Data kata dan pertanyaan terkait dengan urutan
final List<Map<String, dynamic>> orderedQuestions = [
{
'word': 'NUKU',
'question': 'Nama Sultan yang memimpin kerajaan Tidore',
'image': 'assets/images_raja/raja_tidore.png',
'isFound': false,
'isUnlocked': true, // Pertanyaan pertama sudah unlocked
'isVisible': true, // Pertanyaan pertama sudah visible
},
{
'word': 'LONCENG',
'question':
'Cakra Donya hadiah Tiongkok untuk Samudera Pasai, berupa apa',
'image': 'assets/images_islam/peninggalan_samuderapasai.png',
'isFound': false,
'isUnlocked': false,
'isVisible': false,
},
{
'word': 'KATANGKA',
'question': 'Masjid peninggalan Kerajaan Gowa-Tallo',
'image': 'assets/images_islam/peninggalan_gowatallo.png',
'isFound': false,
'isUnlocked': false,
'isVisible': false,
},
{
'word': 'TERNATE',
'question':
'Kerajaan Islam di Maluku Utara yang terkenal dengan hasil rempah-rempahnya',
'image': 'assets/images_wilayah/wilayah_ternate.png',
'isFound': false,
'isUnlocked': false,
'isVisible': false,
},
{
'word': 'BANTEN',
'question': 'Kerajaan berkuasanya Sultan Ageng Tirtayasa',
'image': 'assets/images_raja/raja_banten.png',
'isFound': false,
'isUnlocked': false,
'isVisible': false,
}
];
int currentQuestionIndex = 0;
late List<List<String>> grid;
String? lastFoundWord;
// Untuk seleksi kata
Offset? startDrag;
Offset? currentDrag;
List<Offset> selectedCells = [];
List<Offset> correctCells = [];
@override
void initState() {
super.initState();
startTimer();
initializeGame();
WidgetsBinding.instance.addPostFrameCallback((_) {
_showQuestionCountDialog();
});
}
void initializeGame() {
grid = List.generate(GRID_SIZE, (_) => List.filled(GRID_SIZE, ''));
placeWords();
fillEmptySpaces();
}
void placeWords() {
// Ambil kata-kata dari orderedQuestions
List<String> words =
orderedQuestions.map((q) => q['word'] as String).toList();
// Urutkan kata dari yang terpanjang ke terpendek
words.sort((a, b) => b.length.compareTo(a.length));
// Bersihkan grid
grid = List.generate(GRID_SIZE, (_) => List.filled(GRID_SIZE, ''));
// Safe zones lebih banyak dan menyebar
final List<List<int>> safeZones = [
[2, 2],
[2, GRID_SIZE - 3],
[GRID_SIZE ~/ 2, GRID_SIZE ~/ 2],
[GRID_SIZE - 3, 2],
[GRID_SIZE - 3, GRID_SIZE - 3],
[6, GRID_SIZE - 5],
[GRID_SIZE - 7, 6],
[GRID_SIZE ~/ 3, GRID_SIZE ~/ 3],
[GRID_SIZE - 5, GRID_SIZE ~/ 2],
[GRID_SIZE ~/ 2, GRID_SIZE - 5],
];
final random = Random();
for (int i = 0; i < words.length; i++) {
String word = words[i];
bool placed = false;
List<List<int>> availableZones = List.from(safeZones);
availableZones.shuffle(random);
for (var zone in availableZones) {
// Offset acak lebih luas (-3 sampai +3)
List<List<int>> offsets = [];
for (int dr = -3; dr <= 3; dr++) {
for (int dc = -3; dc <= 3; dc++) {
offsets.add([dr, dc]);
}
}
offsets.shuffle(random);
for (var offset in offsets) {
int startRow = zone[0] + offset[0];
int startCol = zone[1] + offset[1];
List<WordDirection> directions = [];
if (startCol + word.length <= GRID_SIZE - 1)
directions.add(WordDirection.horizontal);
if (startRow + word.length <= GRID_SIZE - 1)
directions.add(WordDirection.vertical);
directions.shuffle(random);
for (var direction in directions) {
if (canPlaceWord(word, startRow, startCol, direction)) {
placeWordInGrid(PlacedWord(
word: word,
startRow: startRow,
startCol: startCol,
direction: direction,
));
placed = true;
break;
}
}
if (placed) break;
}
if (placed) break;
}
// Fallback: coba seluruh grid dengan interval lebih besar
if (!placed) {
for (int row = 0; row < GRID_SIZE; row += 2) {
for (int col = 0; col < GRID_SIZE; col += 2) {
List<WordDirection> directions = [
WordDirection.horizontal,
WordDirection.vertical
];
directions.shuffle(random);
for (var direction in directions) {
if (canPlaceWord(word, row, col, direction)) {
placeWordInGrid(PlacedWord(
word: word,
startRow: row,
startCol: col,
direction: direction,
));
placed = true;
break;
}
}
if (placed) break;
}
if (placed) break;
}
}
// Fallback terakhir: posisi benar-benar acak
if (!placed) {
for (int attempt = 0; attempt < 100 && !placed; attempt++) {
int row = random.nextInt(GRID_SIZE - word.length);
int col = random.nextInt(GRID_SIZE - word.length);
List<WordDirection> directions = [
WordDirection.horizontal,
WordDirection.vertical
];
directions.shuffle(random);
for (var direction in directions) {
if (canPlaceWord(word, row, col, direction)) {
placeWordInGrid(PlacedWord(
word: word,
startRow: row,
startCol: col,
direction: direction,
));
placed = true;
break;
}
}
}
}
}
fillEmptySpaces();
}
bool canPlaceWord(
String word, int startRow, int startCol, WordDirection direction) {
if (startRow < 0 || startCol < 0) return false;
int row = startRow;
int col = startCol;
// Cek apakah kata muat dalam grid dengan margin aman
if (direction == WordDirection.horizontal) {
if (col + word.length + 1 > GRID_SIZE) return false;
} else if (direction == WordDirection.vertical) {
if (row + word.length + 1 > GRID_SIZE) return false;
}
// Cek area sekitar kata dengan margin 1
for (int i = -1; i <= word.length; i++) {
for (int j = -1; j <= 1; j++) {
int checkRow =
direction == WordDirection.horizontal ? row + j : row + i;
int checkCol =
direction == WordDirection.horizontal ? col + i : col + j;
if (checkRow >= 0 &&
checkRow < GRID_SIZE &&
checkCol >= 0 &&
checkCol < GRID_SIZE) {
if (grid[checkRow][checkCol].isNotEmpty) return false;
}
}
}
return true;
}
void placeWordInGrid(PlacedWord word) {
int row = word.startRow;
int col = word.startCol;
for (int i = 0; i < word.word.length; i++) {
if (!isValidPosition(row, col)) break;
grid[row][col] = word.word[i];
switch (word.direction) {
case WordDirection.horizontal:
col++;
break;
case WordDirection.vertical:
row++;
break;
case WordDirection.diagonal:
break; // Tidak menggunakan diagonal
}
}
}
void updateSelectedCells(Offset currentPosition) {
if (startDrag == null) return;
final RenderBox box = context.findRenderObject() as RenderBox;
final Offset localStart = box.globalToLocal(startDrag!);
final Offset localCurrent = box.globalToLocal(currentPosition);
// Dapatkan ukuran dan posisi grid
final gridStart =
Offset(16.0, 120.0); // Sesuaikan dengan padding dan posisi grid
final gridSize = box.size.width - 32.0; // Kurangi padding kiri dan kanan
final cellSize = gridSize / GRID_SIZE;
// Hitung posisi sel dengan mempertimbangkan offset grid
int startRow =
((localStart.dy - gridStart.dy) ~/ cellSize).clamp(0, GRID_SIZE - 1);
int startCol =
((localStart.dx - gridStart.dx) ~/ cellSize).clamp(0, GRID_SIZE - 1);
int currentRow =
((localCurrent.dy - gridStart.dy) ~/ cellSize).clamp(0, GRID_SIZE - 1);
int currentCol =
((localCurrent.dx - gridStart.dx) ~/ cellSize).clamp(0, GRID_SIZE - 1);
setState(() {
selectedCells =
calculateSelectedCells(startRow, startCol, currentRow, currentCol);
});
}
bool isValidPosition(int row, int col) {
return row >= 0 && row < GRID_SIZE && col >= 0 && col < GRID_SIZE;
}
List<Offset> calculateSelectedCells(
int startRow, int startCol, int endRow, int endCol) {
List<Offset> cells = [];
// Hitung arah
final int rowStep = startRow == endRow ? 0 : (endRow - startRow).sign;
final int colStep = startCol == endCol ? 0 : (endCol - startCol).sign;
// Hitung jumlah sel
final int steps = max((endRow - startRow).abs(), (endCol - startCol).abs());
// Tambahkan sel ke seleksi
for (int i = 0; i <= steps; i++) {
final int row = startRow + (i * rowStep);
final int col = startCol + (i * colStep);
if (isValidPosition(row, col)) {
cells.add(Offset(col.toDouble(), row.toDouble()));
}
}
return cells;
}
void fillEmptySpaces() {
final random = Random();
const letters = 'AEIMNRSTUW';
for (int i = 0; i < GRID_SIZE; i++) {
for (int j = 0; j < GRID_SIZE; j++) {
if (grid[i][j].isEmpty) {
grid[i][j] = letters[random.nextInt(letters.length)];
}
}
}
}
void checkSelection() {
if (selectedCells.length < 2) return;
String selectedWord = '';
List<Offset> orderedCells = List.from(selectedCells);
// Urutkan sel berdasarkan arah seleksi
if (orderedCells.first.dx > orderedCells.last.dx) {
// Jika seleksi dari kanan ke kiri, balik urutan sel
orderedCells = orderedCells.reversed.toList();
}
for (var cell in orderedCells) {
int row = cell.dy.toInt();
int col = cell.dx.toInt();
selectedWord += grid[row][col];
}
// Cek kata normal dan terbalik
if ((selectedWord == orderedQuestions[currentQuestionIndex]['word'] ||
selectedWord ==
orderedQuestions[currentQuestionIndex]['word']
.split('')
.reversed
.join()) &&
!orderedQuestions[currentQuestionIndex]['isFound']) {
setState(() {
orderedQuestions[currentQuestionIndex]['isFound'] = true;
correctCells.addAll(selectedCells);
score += 20;
// Unlock pertanyaan berikutnya jika ada
if (currentQuestionIndex < orderedQuestions.length - 1) {
currentQuestionIndex++;
orderedQuestions[currentQuestionIndex]['isUnlocked'] = true;
orderedQuestions[currentQuestionIndex]['isVisible'] = true;
}
showCorrectAnswerDialog();
// Cek apakah semua pertanyaan sudah ditemukan
if (orderedQuestions.every((q) => q['isFound'])) {
showCompletionDialog();
}
});
}
}
void showCorrectAnswerDialog() {
AudioManager.successsound();
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => Dialog(
backgroundColor: Colors.transparent,
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: double.infinity,
height: 400,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/dialog_complete.png'),
fit: BoxFit.fill,
),
borderRadius: BorderRadius.circular(16),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Anda menemukan kata "${orderedQuestions[currentQuestionIndex - 1]['word']}"',
style: const TextStyle(
fontFamily: 'Bestime',
fontSize: 14,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
if (currentQuestionIndex < orderedQuestions.length)
Padding(
padding: const EdgeInsets.only(top: 10),
child: Text(
'Pertanyaan selanjutnya telah dibuka',
style: const TextStyle(
fontFamily: 'Bestime',
fontSize: 14,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 30),
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pop(context);
},
child: Container(
width: 150,
height: 50,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/button.png'),
fit: BoxFit.fill,
),
),
child: const Center(
child: Text(
'OK',
style: TextStyle(
fontFamily: 'Bestime',
fontSize: 16,
color: Color.fromARGB(255, 65, 44, 23),
),
),
),
),
),
],
),
),
],
),
),
);
}
void showCompletionDialog() async {
AudioManager.winsound();
timer.cancel();
LevelManager.setLevelCompleted(2, true, LevelManager.TYPE_ISLAM);
final user = FirebaseAuth.instance.currentUser;
if (user != null) {
await DatabaseService().saveScore(
userId: user.uid,
score: score,
formattedTime: formatTime(elapsedSeconds),
levelName: "Level 2",
category: "Islam",
);
}
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => Dialog(
backgroundColor: Colors.transparent,
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: double.infinity,
height: 400, // Sesuaikan tinggi background
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/dialog_complete.png'),
fit: BoxFit.fill,
),
borderRadius: BorderRadius.circular(16),
),
),
// Isi konten berada tepat di tengah gambar
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Anda telah menyelesaikan semua jawaban dengan benar.',
style: TextStyle(
fontFamily: 'Bestime',
fontSize: 14,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
Text(
'Total Skor: $score',
style: const TextStyle(
fontFamily: 'Bestime',
fontSize: 12,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Total Waktu: ${formatTime(elapsedSeconds)}',
style: const TextStyle(
fontFamily: 'Bestime',
fontSize: 12,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 25),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const Level2Islam(),
),
);
},
child: Container(
width: 40,
height: 40,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/restart.png'),
fit: BoxFit.contain,
),
),
),
),
const SizedBox(width: 20),
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => LandingPage(
onStart: () {},
onStats: () {},
),
),
(route) => false,
);
},
child: Container(
width: 40,
height: 40,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/stats.png'),
fit: BoxFit.contain,
),
),
),
),
const SizedBox(width: 20),
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const Level3Islam(),
),
);
},
child: Container(
width: 40,
height: 40,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/next.png'),
fit: BoxFit.contain,
),
),
),
),
],
),
],
),
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
AudioManager.playClickSound();
_showMenuDialog(context);
return false;
},
child: Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/background_permainan.png'),
fit: BoxFit.cover,
),
),
child: Column(
children: [
const SizedBox(height: 40),
// Header (Timer, Menu, Score)
Row(
children: [
// Kiri (Timer)
Flexible(
flex: 2,
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 22.0),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 5),
width: 120,
height: 45,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/grey_button.png'),
fit: BoxFit.fill,
),
),
child: Center(
child: Text(
'${formatTime(seconds)}',
style: const TextStyle(
fontSize: 20,
color: Colors.black,
fontFamily: 'Bestime',
),
overflow: TextOverflow.ellipsis,
),
),
),
),
),
),
// Tengah (Menu Icon)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: GestureDetector(
onTap: () {
AudioManager.playClickSound();
_showMenuDialog(context);
},
child: Container(
width: 40,
height: 40,
margin: const EdgeInsets.symmetric(horizontal: 8),
child: Image.asset(
'assets/icons/menu.png',
fit: BoxFit.contain,
),
),
),
),
// Kanan (Skor)
Flexible(
flex: 2,
child: Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 22.0),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 5),
width: 120,
height: 45,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/grey_button.png'),
fit: BoxFit.fill,
),
),
child: Center(
child: Text(
'$score',
style: const TextStyle(
fontSize: 20,
color: Colors.black,
fontFamily: 'Bestime',
),
overflow: TextOverflow.ellipsis,
),
),
),
),
),
),
],
),
const SizedBox(height: 15),
// Grid Area
Expanded(
child: SingleChildScrollView(
physics:
const NeverScrollableScrollPhysics(), // Prevent scrolling while selecting
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// Word Search Grid
AspectRatio(
aspectRatio: 1, // Make grid square
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
),
child: GestureDetector(
onPanStart: (details) {
setState(() {
startDrag = details.globalPosition;
selectedCells.clear();
});
},
onPanUpdate: (details) {
updateSelectedCells(details.globalPosition);
},
onPanEnd: (details) {
checkSelection();
setState(() {
startDrag = null;
selectedCells.clear();
});
},
child: GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(16.0),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: GRID_SIZE,
childAspectRatio: 1,
crossAxisSpacing: 1,
mainAxisSpacing: 1,
),
itemCount: GRID_SIZE * GRID_SIZE,
itemBuilder: (context, index) {
final row = index ~/ GRID_SIZE;
final col = index % GRID_SIZE;
final isSelected = selectedCells.contains(
Offset(col.toDouble(), row.toDouble()));
final isCorrect = correctCells.contains(
Offset(col.toDouble(), row.toDouble()));
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5)),
color: isCorrect
? Colors.green.withOpacity(0.3)
: isSelected
? Colors.blue.withOpacity(0.3)
: Colors.white,
),
child: Center(
child: Text(
grid[row][col],
style: const TextStyle(
fontSize: 15,
fontFamily: 'Bestime',
),
),
),
);
},
),
),
),
),
// Gambar peninggalan
Container(
height: 200,
width: double.infinity,
margin: const EdgeInsets.symmetric(vertical: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.asset(
orderedQuestions[currentQuestionIndex]['image'],
fit: BoxFit.fill,
errorBuilder: (context, error, stackTrace) {
return Container(
color: Colors.grey[200],
child: const Center(
child: Icon(
Icons.image_not_supported,
size: 60,
color: Colors.grey,
),
),
);
},
),
),
),
// Pertanyaan yang sedang aktif
Container(
padding: const EdgeInsets.all(16),
child: Stack(
children: [
// Outline text
Text(
orderedQuestions[currentQuestionIndex]
['question'],
style: TextStyle(
fontFamily: 'Bestime',
fontSize: 15,
foreground: Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2
..color =
const Color.fromARGB(255, 65, 44, 23),
),
textAlign: TextAlign.center,
),
// Fill text
Text(
orderedQuestions[currentQuestionIndex]
['question'],
style: const TextStyle(
fontFamily: 'Bestime',
fontSize: 15,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
],
),
),
],
),
),
),
),
],
),
),
),
);
}
String formatTime(int seconds) {
int minutes = seconds ~/ 60;
int remainingSeconds = seconds % 60;
return '${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}';
}
void startTimer() {
timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
if (seconds > 0) {
seconds--;
elapsedSeconds++; // Increment waktu yang telah berlalu
} else {
timer.cancel();
showTimeUpDialog();
}
});
});
}
void showTimeUpDialog() async {
AudioManager.losesound();
final user = FirebaseAuth.instance.currentUser;
if (user != null) {
await DatabaseService().saveScore(
userId: user.uid,
score: score,
formattedTime: formatTime(elapsedSeconds),
levelName: "Level 2",
category: "Islam",
);
}
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => Dialog(
backgroundColor: Colors.transparent,
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: double.infinity,
height: 400, // Sesuaikan dengan tinggi gambar background
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/timeout.png'),
fit: BoxFit.fill,
),
borderRadius: BorderRadius.circular(16),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Waktu permainan telah habis.',
style: TextStyle(
fontFamily: 'Bestime',
fontSize: 14,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
Text(
'Total Skor: $score',
style: const TextStyle(
fontFamily: 'Bestime',
fontSize: 12,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Total Waktu: ${formatTime(elapsedSeconds)}',
style: const TextStyle(
fontFamily: 'Bestime',
fontSize: 12,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 30),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const Level2Islam(),
),
);
},
child: Container(
width: 40,
height: 40,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/restart.png'),
fit: BoxFit.contain,
),
),
),
),
const SizedBox(width: 20),
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => LandingPage(
onStart: () {},
onStats: () {},
),
),
(route) => false,
);
},
child: Container(
width: 40,
height: 40,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/stats.png'),
fit: BoxFit.contain,
),
),
),
),
],
),
],
),
),
],
),
),
);
}
@override
void dispose() {
timer.cancel();
super.dispose();
}
void _showMenuDialog(BuildContext context) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: double.infinity,
height: 400,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/cover_menu.png'),
fit: BoxFit.fill,
),
borderRadius: BorderRadius.circular(16),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Button Lanjut
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pop(context);
},
child: Container(
width: 170,
height: 50,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/grey_button.png'),
fit: BoxFit.fill,
),
),
child: const Center(
child: Text(
'Lanjut',
style: TextStyle(
fontFamily: 'Bestime',
fontSize: 16,
color: Color.fromARGB(255, 65, 44, 23),
),
),
),
),
),
const SizedBox(height: 18),
// Button Restart
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const Level2Islam(),
),
);
},
child: Container(
width: 170,
height: 50,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/grey_button.png'),
fit: BoxFit.fill,
),
),
child: const Center(
child: Text(
'Restart',
style: TextStyle(
fontFamily: 'Bestime',
fontSize: 16,
color: Color.fromARGB(255, 65, 44, 23),
),
),
),
),
),
const SizedBox(height: 18),
// Button Keluar
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => LandingPage(
onStart: () {},
onStats: () {},
),
),
(route) => false,
);
},
child: Container(
width: 170,
height: 50,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/grey_button.png'),
fit: BoxFit.fill,
),
),
child: const Center(
child: Text(
'Keluar',
style: TextStyle(
fontFamily: 'Bestime',
fontSize: 16,
color: Color.fromARGB(255, 65, 44, 23),
),
),
),
),
),
],
),
),
],
),
);
},
);
}
void _showQuestionCountDialog() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => Dialog(
backgroundColor: Colors.transparent,
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: double.infinity,
height: 300,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/covertext.png'),
fit: BoxFit.fill,
),
borderRadius: BorderRadius.circular(16),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Level ini memiliki total ${orderedQuestions.length} pertanyaan.',
style: const TextStyle(
fontFamily: 'Bestime',
fontSize: 14,
color: Color.fromARGB(255, 182, 134, 86),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 30),
GestureDetector(
onTap: () {
AudioManager.playClickSound();
Navigator.pop(context);
},
child: Container(
width: 150,
height: 50,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/icons/button.png'),
fit: BoxFit.fill,
),
),
child: const Center(
child: Text(
'Mulai',
style: TextStyle(
fontFamily: 'Bestime',
fontSize: 16,
color: Color.fromARGB(255, 65, 44, 23),
),
),
),
),
),
],
),
),
],
),
),
);
}
}
// Game level 1
class GameLevel2 extends FlameGame {
@override
Color backgroundColor() => Colors.white;
@override
Future<void> onLoad() async {
// Bisa ditambahkan komponen lain jika diperlukan
}
}