feat: add depth to game

This commit is contained in:
2026-06-15 19:40:25 +03:30
parent fbf068c2e6
commit 73b7c136f1
4 changed files with 117 additions and 16 deletions
+7
View File
@@ -56,12 +56,19 @@ class AppTheme {
backgroundColor: AppColors.accent, backgroundColor: AppColors.accent,
foregroundColor: AppColors.text, foregroundColor: AppColors.text,
minimumSize: const Size.fromHeight(54), minimumSize: const Size.fromHeight(54),
elevation: 8,
shadowColor: Colors.black,
textStyle: const TextStyle( textStyle: const TextStyle(
fontFamily: fontFamily, fontSize: 18, fontWeight: FontWeight.bold), fontFamily: fontFamily, fontSize: 18, fontWeight: FontWeight.bold),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14), borderRadius: BorderRadius.circular(14),
side: const BorderSide(color: AppColors.gold, width: 1.5), side: const BorderSide(color: AppColors.gold, width: 1.5),
), ),
).copyWith(
// افکتِ فشار: کمی فرورفتن هنگام لمس برای حسِ عمق.
elevation: WidgetStateProperty.resolveWith(
(states) => states.contains(WidgetState.pressed) ? 2.0 : 8.0,
),
), ),
), ),
); );
@@ -106,6 +106,14 @@ class CardComponent extends PositionComponent
final radius = Radius.circular(size.x * 0.09); final radius = Radius.circular(size.x * 0.09);
final rrect = RRect.fromRectAndRadius(rect, radius); final rrect = RRect.fromRectAndRadius(rect, radius);
// سایه‌ی سبک و ارزان (بدون blurِ هر-فریمی) فقط برای کارت‌های رو ⇒ عمق بدون افت کارایی.
// (drawShadow هر فریم برای ده‌ها کارت بسیار سنگین بود و باعث لگ می‌شد.)
if (faceUp) {
final off = _dragging ? size.x * 0.10 : size.x * 0.03;
canvas.drawRRect(rrect.shift(Offset(off * 0.4, off)),
Paint()..color = Color(_dragging ? 0x66000000 : 0x44000000));
}
if (_sprite != null) { if (_sprite != null) {
canvas.save(); canvas.save();
canvas.clipRRect(rrect); canvas.clipRRect(rrect);
@@ -117,6 +125,22 @@ class CardComponent extends PositionComponent
_drawVectorBack(canvas, rrect); _drawVectorBack(canvas, rrect);
} }
// براقیتِ ملایم از بالا فقط برای کارت‌های رو.
if (faceUp) {
canvas.save();
canvas.clipRRect(rrect);
canvas.drawRect(
Rect.fromLTWH(0, 0, size.x, size.y * 0.5),
Paint()
..shader = const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0x2BFFFFFF), Color(0x00FFFFFF)],
).createShader(Rect.fromLTWH(0, 0, size.x, size.y * 0.5)),
);
canvas.restore();
}
if (dimmed) { if (dimmed) {
canvas.drawRRect(rrect, Paint()..color = const Color(0x73000000)); canvas.drawRRect(rrect, Paint()..color = const Color(0x73000000));
} }
+35 -11
View File
@@ -7,24 +7,48 @@ import 'package:flutter/material.dart';
const _gold = Color(0xFFE9B949); const _gold = Color(0xFFE9B949);
const _goldDark = Color(0xFFB8860B); const _goldDark = Color(0xFFB8860B);
/// نمدِ سبزِ بیضی‌شکلِ میز با حاشیه‌ی طلایی. /// نمدِ سبزِ بیضی‌شکلِ میز با عمق: لبه‌ی برجسته، گرادیانِ شعاعی و وینیت.
class Felt extends PositionComponent with HasGameReference { class Felt extends PositionComponent with HasGameReference {
@override @override
void render(Canvas canvas) { void render(Canvas canvas) {
final w = game.size.x, h = game.size.y; final w = game.size.x, h = game.size.y;
final rect = Rect.fromCenter( final center = Offset(w / 2, h / 2);
center: Offset(w / 2, h / 2), final rect = Rect.fromCenter(center: center, width: w * 0.86, height: h * 0.62);
width: w * 0.86, final radius = Radius.circular(h * 0.3);
height: h * 0.62, final felt = RRect.fromRectAndRadius(rect, radius);
);
final rrect = RRect.fromRectAndRadius(rect, Radius.circular(h * 0.3)); // ۱) لبه‌ی چوبیِ بیرونی (ریل) با گرادیان — حسِ برجستگی بدون drawShadowِ هر-فریمی.
canvas.drawRRect(rrect, Paint()..color = const Color(0xFF1B5E20)); final rail = RRect.fromRectAndRadius(
rect.inflate(w * 0.03), Radius.circular(h * 0.33));
canvas.drawRRect( canvas.drawRRect(
rrect, rail,
Paint()
..shader = const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xFF5A2E12), Color(0xFF2E1608)],
).createShader(rail.outerRect),
);
// ۲) حلقه‌ی طلایی بین ریل و نمد.
canvas.drawRRect(
RRect.fromRectAndRadius(rect.inflate(w * 0.008), radius),
Paint() Paint()
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
..strokeWidth = 6 ..strokeWidth = w * 0.012
..color = _goldDark, ..color = _gold,
);
// ۳) نمدِ سبز با گرادیانِ شعاعی (مرکز روشن، لبه‌ها تیره) — خودش حسِ وینیت/عمق می‌دهد.
canvas.drawRRect(
felt,
Paint()
..shader = RadialGradient(
center: Alignment.center,
radius: 0.95,
colors: const [Color(0xFF34A03F), Color(0xFF0E3614)],
stops: const [0.45, 1.0],
).createShader(rect),
); );
} }
} }
+51 -5
View File
@@ -195,13 +195,59 @@ class _MenuButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// رنگِ تیره‌ترِ پایه برای بِوِل (لبه‌ی پایینیِ برجسته).
final dark = Color.lerp(color, Colors.black, 0.45)!;
final light = Color.lerp(color, Colors.white, 0.12)!;
return SizedBox( return SizedBox(
width: 280, width: 280,
child: ElevatedButton.icon( child: Material(
style: ElevatedButton.styleFrom(backgroundColor: color), color: Colors.transparent,
onPressed: onTap, borderRadius: BorderRadius.circular(16),
icon: Icon(icon, color: AppColors.gold), child: InkWell(
label: Text(label), borderRadius: BorderRadius.circular(16),
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(vertical: 15),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [light, color, dark],
stops: const [0, 0.5, 1],
),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.gold, width: 1.6),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.55),
blurRadius: 10,
offset: const Offset(0, 5),
),
// هایلایتِ بالا برای حسِ شیشه‌ای/برجسته.
BoxShadow(
color: Colors.white.withValues(alpha: 0.12),
blurRadius: 1,
offset: const Offset(0, 1),
spreadRadius: -1,
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, color: AppColors.gold),
const SizedBox(width: 10),
Text(label,
style: const TextStyle(
color: AppColors.text,
fontSize: 18,
fontWeight: FontWeight.bold,
shadows: [Shadow(color: Colors.black54, blurRadius: 3)],
)),
],
),
),
),
), ),
); );
} }