This commit is contained in:
2025-11-21 15:54:17 +09:00
parent 6335220e57
commit de84353fc5
5 changed files with 364 additions and 149 deletions
@@ -9,7 +9,6 @@ import '../models/finddiff_models.dart';
class FindDiffGameScreen extends StatefulWidget {
const FindDiffGameScreen({super.key});
@override
State<FindDiffGameScreen> createState() => _FindDiffGameScreenState();
}
@@ -17,7 +16,7 @@ class FindDiffGameScreen extends StatefulWidget {
class _FindDiffGameScreenState extends State<FindDiffGameScreen> {
bool _isDialogShowing = false;
@override
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -27,14 +26,12 @@ class _FindDiffGameScreenState extends State<FindDiffGameScreen> {
void _showGameGuide() {
final controller = context.read<FindDiffController>();
String message = "나머지와 '다른 하나'를 찾으세요.";
String message = "화면에 있는 그림들 중\n나머지와 '다른 하나'를 찾으세요.";
if (controller.difficulty.diffType == FindDiffType.color) {
message += "\n(색상이 다릅니다)";
} else if (controller.difficulty.diffType == FindDiffType.icon) {
message += "\n(모양이 다릅니다)";
} else {
message += "\n(각도가 다릅니다)";
if (controller.difficulty.diffType == FindDiffType.category) {
message += "\n(성격이 다른 이모지를 찾으세요)\n예: 동물들 속에 섞인 과일";
} else if (controller.difficulty.diffType == FindDiffType.word) {
message += "\n(글자가 다른 단어를 찾으세요)\n예: 오타 찾기";
}
showDialog(
@@ -110,11 +107,10 @@ class _FindDiffGameScreenState extends State<FindDiffGameScreen> {
if (controller.isGameCompleted && !_isDialogShowing) {
_isDialogShowing = true;
WidgetsBinding.instance.addPostFrameCallback((_) {
_showGameCompletion(controller);
_showGameCompletion(controller); // 정의 필요
});
}
// 시간 임박 경고 색상
final Color timeColor = controller.remainingTime <= 3 ? theme.colorScheme.error : theme.colorScheme.onSurface;
return Scaffold(
@@ -132,59 +128,64 @@ class _FindDiffGameScreenState extends State<FindDiffGameScreen> {
),
],
),
body: Column(
body: Stack( // [🔥 수정] Stack으로 감싸서 피드백 오버레이 구현
children: [
// 정보 바
Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("목표: ${controller.score}/10", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: theme.primaryColor)),
Text("오답: ${controller.incorrectCount}", style: const TextStyle(fontSize: 16, color: Colors.grey)),
],
),
Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("목표: ${controller.score}/10", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: theme.primaryColor)),
Text("오답: ${controller.incorrectCount}", style: const TextStyle(fontSize: 16, color: Colors.grey)),
],
),
),
// 게임 그리드
Expanded(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: LayoutBuilder(
builder: (context, constraints) {
return GridView.builder(
itemCount: controller.items.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: controller.difficulty.cols,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: 1.0,
),
itemBuilder: (context, index) {
return _buildItem(controller.items[index], controller);
},
);
},
),
),
),
],
),
// 피드백 오버레이
// [🔥 신규] 피드백 오버레이 (정답/오답 표시)
if (controller.showFeedback)
Expanded(
Container(
color: Colors.black.withOpacity(0.3),
child: Center(
child: Icon(
controller.isLastAnswerCorrect ? Icons.check_circle : Icons.cancel,
size: 100,
size: 120,
color: controller.isLastAnswerCorrect ? Colors.green : theme.colorScheme.error,
),
),
)
else
// 게임 그리드
Expanded(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: LayoutBuilder(
builder: (context, constraints) {
return GridView.builder(
itemCount: controller.items.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: controller.difficulty.cols,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: 1.0,
),
itemBuilder: (context, index) {
return _buildItem(controller.items[index], controller);
},
);
},
),
),
),
],
),
);
}
// 🔽 [🔥 핵심 수정] 아이템 빌더 (아이콘 vs 텍스트 분기)
Widget _buildItem(FindDiffItem item, FindDiffController controller) {
return GestureDetector(
onTap: () => controller.onItemTapped(item),
@@ -194,13 +195,26 @@ class _FindDiffGameScreenState extends State<FindDiffGameScreen> {
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.black12),
),
child: Transform.rotate(
angle: item.angle,
child: Icon(
item.icon,
size: 40, // 동적 크기 조절이 필요하면 LayoutBuilder 활용 가능
color: item.color,
),
child: Center(
child: item.textContent != null
? FittedBox( // 단어/이모지 모드
fit: BoxFit.scaleDown,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
item.textContent!,
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
),
),
)
: Transform.rotate( // 아이콘/회전 모드
angle: item.angle,
child: Icon(
item.icon,
size: 40,
color: item.color,
),
),
),
),
);