tuesdae_assets 1.0.1 copy "tuesdae_assets: ^1.0.1" to clipboard
tuesdae_assets: ^1.0.1 copied to clipboard

Animated vehicle widgets for Flutter with clear visuals and predictable animations. Perfect for traffic games, simulations, and educational apps.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tuesdae_assets/vehicle_types.dart';
import 'package:tuesdae_assets/vehicle_widget.dart';

void main() {
  runApp(const TuesdaeAssetsExample());
}

class TuesdaeAssetsExample extends StatelessWidget {
  const TuesdaeAssetsExample({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tuesdae Assets - Vehicle Widgets',
      theme: _buildTheme(),
      home: const VehicleShowcase(),
      debugShowCheckedModeBanner: false,
    );
  }

  ThemeData _buildTheme() {
    return ThemeData(
      useMaterial3: true,
      colorScheme: ColorScheme.fromSeed(
        seedColor: const Color(0xFF6366F1),
        brightness: Brightness.light,
      ),
      fontFamily: 'SF Pro Display',
      textTheme: const TextTheme(
        headlineLarge: TextStyle(
          fontSize: 32,
          fontWeight: FontWeight.w800,
          letterSpacing: -0.5,
        ),
        headlineMedium: TextStyle(
          fontSize: 24,
          fontWeight: FontWeight.w700,
          letterSpacing: -0.3,
        ),
        bodyLarge: TextStyle(
          fontSize: 16,
          fontWeight: FontWeight.w500,
          height: 1.5,
        ),
      ),
      cardTheme: CardTheme(
        elevation: 0,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(16),
        ),
      ),
      elevatedButtonTheme: ElevatedButtonThemeData(
        style: ElevatedButton.styleFrom(
          elevation: 0,
          padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(12),
          ),
        ),
      ),
    );
  }
}

class VehicleShowcase extends StatefulWidget {
  const VehicleShowcase({super.key});

  @override
  VehicleShowcaseState createState() => VehicleShowcaseState();
}

class VehicleShowcaseState extends State<VehicleShowcase>
    with TickerProviderStateMixin {
  bool _emergencyMode = false;
  VehicleDirection _direction = VehicleDirection.north;
  double _size = 30.0;
  Color _carColor = const Color(0xFF6366F1);
  late AnimationController _heroAnimationController;
  late AnimationController _cardAnimationController;
  late Animation<double> _fadeAnimation;
  late Animation<Offset> _slideAnimation;

  @override
  void initState() {
    super.initState();
    
    _heroAnimationController = AnimationController(
      duration: const Duration(milliseconds: 1500),
      vsync: this,
    );
    
    _cardAnimationController = AnimationController(
      duration: const Duration(milliseconds: 800),
      vsync: this,
    );
    
    _fadeAnimation = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(CurvedAnimation(
      parent: _cardAnimationController,
      curve: Curves.easeOutCubic,
    ));
    
    _slideAnimation = Tween<Offset>(
      begin: const Offset(0, 0.3),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _cardAnimationController,
      curve: Curves.easeOutCubic,
    ));
    
    _heroAnimationController.forward();
    Future.delayed(const Duration(milliseconds: 300), () {
      _cardAnimationController.forward();
    });
  }
  
  @override
  void dispose() {
    _heroAnimationController.dispose();
    _cardAnimationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: const BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: [
              Color(0xFF667EEA),
              Color(0xFF764BA2),
              Color(0xFF6B73FF),
              Color(0xFF9A9CE6),
            ],
            stops: [0.0, 0.3, 0.7, 1.0],
          ),
        ),
        child: SafeArea(
          child: SingleChildScrollView(
            physics: const BouncingScrollPhysics(),
            child: Column(
              children: [
                _buildHeroSection(),
                const SizedBox(height: 20),
                _buildAnimatedContent(),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildHeroSection() {
    return Container(
      padding: const EdgeInsets.all(32),
      child: Column(
        children: [
          // Hero title with animation
          AnimatedBuilder(
            animation: _heroAnimationController,
            builder: (context, child) {
              return Transform.scale(
                scale: _heroAnimationController.value,
                child: Opacity(
                  opacity: _heroAnimationController.value,
                  child: Column(
                    children: [
                      Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 24,
                          vertical: 12,
                        ),
                        decoration: BoxDecoration(
                          gradient: const LinearGradient(
                            colors: [Color(0xFF667EEA), Color(0xFF764BA2)],
                          ),
                          borderRadius: BorderRadius.circular(25),
                          boxShadow: [
                            BoxShadow(
                              color: Colors.black.withValues(alpha: 0.2),
                              blurRadius: 20,
                              offset: const Offset(0, 10),
                            ),
                          ],
                        ),
                        child: const Text(
                          '🚗 TUESDAE ASSETS',
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 16,
                            fontWeight: FontWeight.w600,
                            letterSpacing: 2,
                          ),
                        ),
                      ),
                      const SizedBox(height: 20),
                      const Text(
                        'Beautiful Vehicle Widgets',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 36,
                          fontWeight: FontWeight.w900,
                          letterSpacing: -1,
                          shadows: [
                            Shadow(
                              color: Colors.black26,
                              offset: Offset(0, 2),
                              blurRadius: 4,
                            ),
                          ],
                        ),
                        textAlign: TextAlign.center,
                      ),
                      const SizedBox(height: 12),
                      const Text(
                        'Accessible, animated vehicles for Flutter\nPerfect for games, simulations & educational apps',
                        style: TextStyle(
                          color: Colors.white70,
                          fontSize: 16,
                          fontWeight: FontWeight.w500,
                          height: 1.4,
                        ),
                        textAlign: TextAlign.center,
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
          const SizedBox(height: 40),
          // Hero vehicles showcase
          Container(
            height: 120,
            decoration: BoxDecoration(
              color: Colors.white.withValues(alpha: 0.1),
              borderRadius: BorderRadius.circular(20),
              border: Border.all(
                color: Colors.white.withValues(alpha: 0.2),
                width: 1,
              ),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withValues(alpha: 0.1),
                  blurRadius: 30,
                  offset: const Offset(0, 15),
                ),
              ],
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                _buildHeroVehicle(
                  const TuesdaeVehicle.ambulance(
                    config: VehicleConfig(
                      primaryColor: Colors.white,
                      size: 40,
                      isFlashing: true,
                    ),
                  ),
                ),
                _buildHeroVehicle(
                  const TuesdaeVehicle.police(
                    config: VehicleConfig(
                      primaryColor: Color(0xFF1E3A8A),
                      size: 40,
                      isFlashing: true,
                    ),
                  ),
                ),
                _buildHeroVehicle(
                  const TuesdaeVehicle.schoolBus(
                    config: VehicleConfig(
                      primaryColor: Color(0xFFFBBF24),
                      size: 40,
                      showEffects: true,
                    ),
                  ),
                ),
                _buildHeroVehicle(
                  const TuesdaeVehicle.tractor(
                    config: VehicleConfig(
                      primaryColor: Color(0xFF16A34A),
                      size: 40,
                      showEffects: true,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildHeroVehicle(Widget vehicle) {
    return Container(
      width: 80,
      height: 80,
      decoration: BoxDecoration(
        color: Colors.white.withValues(alpha: 0.15),
        borderRadius: BorderRadius.circular(16),
        border: Border.all(
          color: Colors.white.withValues(alpha: 0.3),
          width: 1,
        ),
      ),
      child: Center(child: vehicle),
    );
  }

  Widget _buildAnimatedContent() {
    return AnimatedBuilder(
      animation: _fadeAnimation,
      builder: (context, child) {
        return SlideTransition(
          position: _slideAnimation,
          child: FadeTransition(
            opacity: _fadeAnimation,
            child: Container(
              margin: const EdgeInsets.symmetric(horizontal: 20),
              child: Column(
                children: [
                  _buildModernVehicleShowcase(),
                  const SizedBox(height: 24),
                  _buildModernInteractiveDemo(),
                  const SizedBox(height: 24),
                  _buildModernTrafficDemo(),
                  const SizedBox(height: 40),
                ],
              ),
            ),
          ),
        );
      },
    );
  }

  Widget _buildModernVehicleShowcase() {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(24),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.1),
            blurRadius: 30,
            offset: const Offset(0, 15),
          ),
        ],
      ),
      child: Padding(
        padding: const EdgeInsets.all(28),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    gradient: const LinearGradient(
                      colors: [Color(0xFF8B5CF6), Color(0xFFA855F7)],
                    ),
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: const Icon(
                    Icons.directions_car,
                    color: Colors.white,
                    size: 24,
                  ),
                ),
                const SizedBox(width: 16),
                const Text(
                  'Vehicle Collection',
                  style: TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.w800,
                    color: Color(0xFF1F2937),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 24),
            GridView.count(
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              crossAxisCount: 2,
              mainAxisSpacing: 16,
              crossAxisSpacing: 16,
              childAspectRatio: 1.1,
              children: [
                _buildModernVehicleCard(
                  '🚗 Regular Car',
                  'Standard passenger vehicle',
                  const TuesdaeVehicle.preset(
                    type: VehicleType.regular,
                    config: VehicleConfig(
                            primaryColor: Color(0xFF3B82F6),
                            size: 50,
                    ),
                  ),
                  const Color(0xFF3B82F6),
                ),
                _buildModernVehicleCard(
                  '🚑 Ambulance',
                  'Emergency response vehicle',
                  const TuesdaeVehicle.ambulance(
                    config: VehicleConfig(
                      primaryColor: Colors.white,
                            size: 50,
                      isFlashing: true,
                    ),
                  ),
                  const Color(0xFFEF4444),
                ),
                _buildModernVehicleCard(
                  '🚓 Police Car',
                  'Law enforcement vehicle',
                  const TuesdaeVehicle.police(
                    config: VehicleConfig(
                      primaryColor: Color(0xFF1E3A8A),
                            size: 50,
                      isFlashing: true,
                    ),
                  ),
                  const Color(0xFF1E3A8A),
                ),
                _buildModernVehicleCard(
                  '🚜 Tractor',
                  'Farm vehicle with effects',
                  const TuesdaeVehicle.tractor(
                    config: VehicleConfig(
                      primaryColor: Color(0xFF16A34A),
                            size: 50,
                      showEffects: true,
                    ),
                  ),
                  const Color(0xFF16A34A),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildModernVehicleCard(
    String title,
    String description,
    Widget vehicle,
    Color accentColor,
  ) {
    return Container(
      decoration: BoxDecoration(
        color: const Color(0xFFF8FAFC),
        borderRadius: BorderRadius.circular(16),
        border: Border.all(
          color: const Color(0xFFE2E8F0),
          width: 1,
        ),
      ),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              title,
              style: const TextStyle(
                fontSize: 16,
                fontWeight: FontWeight.w700,
                color: Color(0xFF1F2937),
              ),
            ),
            const SizedBox(height: 4),
            Text(
              description,
              style: const TextStyle(
                fontSize: 12,
                color: Color(0xFF6B7280),
              ),
            ),
            const SizedBox(height: 8),
            Expanded(
              child: Center(
                child: Container(
                  padding: const EdgeInsets.all(4),
                  decoration: BoxDecoration(
                    color: accentColor.withValues(alpha: 0.1),
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: vehicle,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildModernInteractiveDemo() {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(24),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.1),
            blurRadius: 30,
            offset: const Offset(0, 15),
          ),
        ],
      ),
      child: Padding(
        padding: const EdgeInsets.all(28),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    gradient: const LinearGradient(
                      colors: [Color(0xFF06B6D4), Color(0xFF0891B2)],
                    ),
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: const Icon(
                    Icons.tune,
                    color: Colors.white,
                    size: 24,
                  ),
                ),
                const SizedBox(width: 16),
                const Text(
                  'Live Customization',
                  style: TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.w800,
                    color: Color(0xFF1F2937),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 24),
            Row(
              children: [
                Expanded(
                  flex: 2,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      _buildModernToggle('Emergency Lights', _emergencyMode, (value) {
                        setState(() => _emergencyMode = value);
                        HapticFeedback.lightImpact();
                      }),
                      const SizedBox(height: 20),
                      const Text(
                        'Direction',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.w700,
                          color: Color(0xFF1F2937),
                        ),
                      ),
                      const SizedBox(height: 8),
                      Wrap(
                        spacing: 8,
                        children: VehicleDirection.values.map((dir) {
                          return _buildDirectionChip(dir);
                        }).toList(),
                      ),
                      const SizedBox(height: 20),
                      Text(
                        'Size: ${_size.round()}px',
                        style: const TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.w700,
                          color: Color(0xFF1F2937),
                        ),
                      ),
                      const SizedBox(height: 8),
                      SliderTheme(
                        data: SliderTheme.of(context).copyWith(
                          activeTrackColor: const Color(0xFF06B6D4),
                          thumbColor: const Color(0xFF06B6D4),
                          overlayColor: const Color(0xFF06B6D4).withValues(alpha: 0.2),
                        ),
                        child: Slider(
                          value: _size,
                          min: 20,
                          max: 60,
                          divisions: 8,
                          onChanged: (value) {
                            setState(() => _size = value);
                            HapticFeedback.selectionClick();
                          },
                        ),
                      ),
                      const SizedBox(height: 20),
                      const Text(
                        'Color Theme',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.w700,
                          color: Color(0xFF1F2937),
                        ),
                      ),
                      const SizedBox(height: 8),
                      Wrap(
                        spacing: 12,
                        children: [
                          const Color(0xFF6366F1),
                          const Color(0xFFEF4444),
                          const Color(0xFF10B981),
                          const Color(0xFFF59E0B),
                          const Color(0xFF8B5CF6),
                          const Color(0xFF06B6D4),
                        ].map((color) => _buildColorOption(color)).toList(),
                      ),
                    ],
                  ),
                ),
                const SizedBox(width: 32),
                Expanded(
                  child: Container(
                    height: 160,
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topLeft,
                        end: Alignment.bottomRight,
                        colors: [
                          _carColor.withValues(alpha: 0.1),
                          _carColor.withValues(alpha: 0.05),
                        ],
                      ),
                      borderRadius: BorderRadius.circular(20),
                      border: Border.all(
                        color: _carColor.withValues(alpha: 0.3),
                        width: 2,
                      ),
                    ),
                    child: Center(
                      child: GestureDetector(
                        onTap: () {
                          HapticFeedback.mediumImpact();
                          ScaffoldMessenger.of(context).showSnackBar(
                            SnackBar(
                              content: const Text(
                                '🚗 Vehicle tapped! Ready to integrate?',
                                style: TextStyle(fontWeight: FontWeight.w600),
                              ),
                              backgroundColor: _carColor,
                              behavior: SnackBarBehavior.floating,
                              shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(12),
                              ),
                            ),
                          );
                        },
                        child: TuesdaeVehicle(
                          type: VehicleType.ambulance,
                          config: VehicleConfig(
                            primaryColor: _carColor,
                            size: _size,
                            direction: _direction,
                            isFlashing: _emergencyMode,
                            showEffects: true,
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildModernToggle(String label, bool value, ValueChanged<bool> onChanged) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Text(
          label,
          style: const TextStyle(
            fontSize: 16,
            fontWeight: FontWeight.w700,
            color: Color(0xFF1F2937),
          ),
        ),
        Switch(
          value: value,
          onChanged: onChanged,
          activeColor: const Color(0xFF06B6D4),
          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
        ),
      ],
    );
  }

  Widget _buildDirectionChip(VehicleDirection dir) {
    final isSelected = _direction == dir;
    return GestureDetector(
      onTap: () {
        setState(() => _direction = dir);
        HapticFeedback.selectionClick();
      },
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
        decoration: BoxDecoration(
          color: isSelected ? const Color(0xFF06B6D4) : const Color(0xFFF1F5F9),
          borderRadius: BorderRadius.circular(8),
          border: Border.all(
            color: isSelected ? const Color(0xFF06B6D4) : const Color(0xFFE2E8F0),
          ),
        ),
        child: Text(
          dir.name.toUpperCase(),
          style: TextStyle(
            color: isSelected ? Colors.white : const Color(0xFF64748B),
            fontSize: 12,
            fontWeight: FontWeight.w600,
          ),
        ),
      ),
    );
  }

  Widget _buildColorOption(Color color) {
    final isSelected = _carColor == color;
    return GestureDetector(
      onTap: () {
        setState(() => _carColor = color);
        HapticFeedback.lightImpact();
      },
      child: Container(
        width: 36,
        height: 36,
        decoration: BoxDecoration(
          color: color,
          shape: BoxShape.circle,
          border: Border.all(
            color: isSelected ? color : Colors.transparent,
            width: 3,
          ),
          boxShadow: [
            if (isSelected)
              BoxShadow(
                color: color.withValues(alpha: 0.4),
                blurRadius: 8,
                offset: const Offset(0, 2),
              ),
          ],
        ),
        child: isSelected
            ? const Icon(
                Icons.check,
                color: Colors.white,
                size: 20,
              )
            : null,
      ),
    );
  }

  Widget _buildModernTrafficDemo() {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(24),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.1),
            blurRadius: 30,
            offset: const Offset(0, 15),
          ),
        ],
      ),
      child: Padding(
        padding: const EdgeInsets.all(28),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    gradient: const LinearGradient(
                      colors: [Color(0xFFF59E0B), Color(0xFFD97706)],
                    ),
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: const Icon(
                    Icons.traffic,
                    color: Colors.white,
                    size: 24,
                  ),
                ),
                const SizedBox(width: 16),
                const Text(
                  'Traffic Simulation',
                  style: TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.w800,
                    color: Color(0xFF1F2937),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 24),
            Container(
              height: 280,
              decoration: BoxDecoration(
                gradient: const LinearGradient(
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                  colors: [
                    Color(0xFF1E293B),
                    Color(0xFF334155),
                    Color(0xFF475569),
                  ],
                ),
                borderRadius: BorderRadius.circular(20),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withValues(alpha: 0.2),
                    blurRadius: 20,
                    offset: const Offset(0, 10),
                  ),
                ],
              ),
              child: Stack(
                children: [
                  // Clean city background
                  Positioned.fill(
                    child: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(20),
                        gradient: const RadialGradient(
                          center: Alignment.center,
                          radius: 1.2,
                          colors: [
                            Color(0xFF374151),
                            Color(0xFF1F2937),
                          ],
                        ),
                      ),
                    ),
                  ),
                  
                  // Modern road layout
                  Positioned.fill(child: CustomPaint(painter: CleanRoadPainter())),
                  
                  // Vehicles positioned more naturally
                  const Positioned(
                    top: 60,
                    left: 200,
                    child: TuesdaeVehicle(
                      type: VehicleType.regular,
                      config: VehicleConfig(
                        primaryColor: Color(0xFF3B82F6),
                        size: 32,
                        direction: VehicleDirection.south,
                      ),
                    ),
                  ),
                  
                  const Positioned(
                    top: 120,
                    left: 80,
                    child: TuesdaeVehicle.ambulance(
                      config: VehicleConfig(
                        primaryColor: Colors.white,
                        size: 34,
                        direction: VehicleDirection.east,
                        isFlashing: true,
                      ),
                    ),
                  ),
                  
                  const Positioned(
                    top: 200,
                    left: 200,
                    child: TuesdaeVehicle.schoolBus(
                      config: VehicleConfig(
                        primaryColor: Color(0xFFFBBF24),
                        size: 38,
                        direction: VehicleDirection.north,
                        showEffects: true,
                      ),
                    ),
                  ),
                  
                  const Positioned(
                    top: 120,
                    right: 80,
                    child: TuesdaeVehicle.police(
                      config: VehicleConfig(
                        primaryColor: Color(0xFF1E3A8A),
                        size: 34,
                        direction: VehicleDirection.west,
                        isFlashing: true,
                      ),
                    ),
                  ),
                  
                  const Positioned(
                    top: 40,
                    left: 125,
                    child: TuesdaeVehicle.tractor(
                      config: VehicleConfig(
                        primaryColor: Color(0xFF16A34A),
                        size: 30,
                        direction: VehicleDirection.south,
                        showEffects: true,
                      ),
                    ),
                  ),
                  
                  // City elements for context
                  Positioned(
                    top: 20,
                    left: 20,
                    child: _buildCityBuilding(30, const Color(0xFF4B5563)),
                  ),
                  Positioned(
                    top: 20,
                    right: 20,
                    child: _buildCityBuilding(40, const Color(0xFF6B7280)),
                  ),
                  Positioned(
                    bottom: 20,
                    left: 30,
                    child: _buildCityBuilding(35, const Color(0xFF374151)),
                  ),
                  Positioned(
                    bottom: 20,
                    right: 30,
                    child: _buildCityBuilding(45, const Color(0xFF4B5563)),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 16),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: const Color(0xFFF0FDF4),
                borderRadius: BorderRadius.circular(12),
                border: Border.all(
                  color: const Color(0xFF16A34A).withValues(alpha: 0.2),
                ),
              ),
              child: const Row(
                children: [
                  Icon(
                    Icons.lightbulb_outline,
                    color: Color(0xFF16A34A),
                    size: 20,
                  ),
                  SizedBox(width: 12),
                  Expanded(
                    child: Text(
                      'Perfect for traffic games, city simulations, educational apps, and emergency response training!',
                      style: TextStyle(
                        color: Color(0xFF166534),
                        fontWeight: FontWeight.w600,
                        fontSize: 14,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildCityBuilding(double height, Color color) {
    return Container(
      width: 20,
      height: height,
      decoration: BoxDecoration(
        color: color,
        borderRadius: const BorderRadius.only(
          topLeft: Radius.circular(4),
          topRight: Radius.circular(4),
        ),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.3),
            blurRadius: 4,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      child: Column(
        children: [
          const SizedBox(height: 4),
          // Building windows
          for (int i = 0; i < (height / 12).floor(); i++)
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 3, vertical: 1),
              child: Container(
                height: 6,
                decoration: BoxDecoration(
                  color: Colors.yellow.withValues(alpha: 0.7),
                  borderRadius: BorderRadius.circular(1),
                ),
              ),
            ),
        ],
      ),
    );
  }

}

class RoadPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final roadPaint = Paint()..color = const Color(0xFF34495E);
    final linePaint =
        Paint()
          ..color = Colors.yellow
          ..strokeWidth = 2;

    // Horizontal road
    canvas.drawRect(
      Rect.fromLTWH(0, size.height / 2 - 20, size.width, 40),
      roadPaint,
    );

    // Vertical road
    canvas.drawRect(
      Rect.fromLTWH(size.width / 2 - 20, 0, 40, size.height),
      roadPaint,
    );

    // Center lines
    for (double x = 0; x < size.width; x += 30) {
      if (x < size.width / 2 - 30 || x > size.width / 2 + 30) {
        canvas.drawLine(
          Offset(x, size.height / 2),
          Offset(x + 15, size.height / 2),
          linePaint,
        );
      }
    }

    for (double y = 0; y < size.height; y += 30) {
      if (y < size.height / 2 - 30 || y > size.height / 2 + 30) {
        canvas.drawLine(
          Offset(size.width / 2, y),
          Offset(size.width / 2, y + 15),
          linePaint,
        );
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

class ModernRoadPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // Main road surface
    final roadPaint = Paint()
      ..shader = const LinearGradient(
        begin: Alignment.topLeft,
        end: Alignment.bottomRight,
        colors: [
          Color(0xFF2D3748),
          Color(0xFF1A202C),
          Color(0xFF2D3748),
        ],
        stops: [0.0, 0.5, 1.0],
      ).createShader(Rect.fromLTWH(0, 0, size.width, size.height));

    // Road line paint
    final linePaint = Paint()
      ..color = const Color(0xFFFBBF24)
      ..strokeWidth = 3
      ..strokeCap = StrokeCap.round;

    final dashedLinePaint = Paint()
      ..color = const Color(0xFFFBBF24)
      ..strokeWidth = 2
      ..strokeCap = StrokeCap.round;

    // Intersection background
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromCenter(
          center: Offset(size.width / 2, size.height / 2),
          width: size.width,
          height: size.height,
        ),
        const Radius.circular(12),
      ),
      roadPaint,
    );

    // Horizontal road
    final horizontalRoad = RRect.fromRectAndRadius(
      Rect.fromLTWH(0, size.height / 2 - 30, size.width, 60),
      const Radius.circular(4),
    );
    canvas.drawRRect(horizontalRoad, roadPaint);

    // Vertical road
    final verticalRoad = RRect.fromRectAndRadius(
      Rect.fromLTWH(size.width / 2 - 30, 0, 60, size.height),
      const Radius.circular(4),
    );
    canvas.drawRRect(verticalRoad, roadPaint);

    // Road borders
    final borderPaint = Paint()
      ..color = const Color(0xFFFBBF24)
      ..strokeWidth = 2
      ..style = PaintingStyle.stroke;

    canvas.drawRRect(horizontalRoad, borderPaint);
    canvas.drawRRect(verticalRoad, borderPaint);

    // Center dashed lines - Horizontal
    for (double x = 0; x < size.width; x += 20) {
      if (x < size.width / 2 - 40 || x > size.width / 2 + 40) {
        canvas.drawLine(
          Offset(x, size.height / 2),
          Offset(x + 10, size.height / 2),
          dashedLinePaint,
        );
      }
    }

    // Center dashed lines - Vertical
    for (double y = 0; y < size.height; y += 20) {
      if (y < size.height / 2 - 40 || y > size.height / 2 + 40) {
        canvas.drawLine(
          Offset(size.width / 2, y),
          Offset(size.width / 2, y + 10),
          dashedLinePaint,
        );
      }
    }

    // Lane dividers
    canvas.drawLine(
      Offset(20, size.height / 2 - 15),
      Offset(size.width - 20, size.height / 2 - 15),
      linePaint,
    );
    canvas.drawLine(
      Offset(20, size.height / 2 + 15),
      Offset(size.width - 20, size.height / 2 + 15),
      linePaint,
    );
    canvas.drawLine(
      Offset(size.width / 2 - 15, 20),
      Offset(size.width / 2 - 15, size.height - 20),
      linePaint,
    );
    canvas.drawLine(
      Offset(size.width / 2 + 15, 20),
      Offset(size.width / 2 + 15, size.height - 20),
      linePaint,
    );

    // Crosswalk stripes
    final crosswalkPaint = Paint()
      ..color = Colors.white.withValues(alpha: 0.8)
      ..strokeWidth = 4;

    for (int i = 0; i < 8; i++) {
      double x = size.width / 2 - 40 + (i * 10);
      canvas.drawLine(
        Offset(x, size.height / 2 - 30),
        Offset(x, size.height / 2 + 30),
        crosswalkPaint,
      );
    }

    // Stop lines
    final stopLinePaint = Paint()
      ..color = Colors.white
      ..strokeWidth = 4;

    // Horizontal stop lines
    canvas.drawLine(
      Offset(size.width / 2 - 40, size.height / 2 - 30),
      Offset(size.width / 2 - 40, size.height / 2 + 30),
      stopLinePaint,
    );
    canvas.drawLine(
      Offset(size.width / 2 + 40, size.height / 2 - 30),
      Offset(size.width / 2 + 40, size.height / 2 + 30),
      stopLinePaint,
    );

    // Vertical stop lines
    canvas.drawLine(
      Offset(size.width / 2 - 30, size.height / 2 - 40),
      Offset(size.width / 2 + 30, size.height / 2 - 40),
      stopLinePaint,
    );
    canvas.drawLine(
      Offset(size.width / 2 - 30, size.height / 2 + 40),
      Offset(size.width / 2 + 30, size.height / 2 + 40),
      stopLinePaint,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

class CleanRoadPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // Clean modern road surface with subtle gradient
    final roadPaint = Paint()
      ..color = const Color(0xFF2C3E50);

    final centerLinePaint = Paint()
      ..color = const Color(0xFFF39C12)
      ..strokeWidth = 2
      ..strokeCap = StrokeCap.round;

    final lanePaint = Paint()
      ..color = const Color(0xFFF39C12)
      ..strokeWidth = 1.5
      ..strokeCap = StrokeCap.round;

    // Main intersection area
    final roadRect = RRect.fromRectAndRadius(
      Rect.fromLTWH(0, 0, size.width, size.height),
      const Radius.circular(16),
    );
    canvas.drawRRect(roadRect, roadPaint);

    // Horizontal road
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromLTWH(0, size.height / 2 - 35, size.width, 70),
        const Radius.circular(8),
      ),
      roadPaint,
    );

    // Vertical road
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromLTWH(size.width / 2 - 35, 0, 70, size.height),
        const Radius.circular(8),
      ),
      roadPaint,
    );

    // Simple center lines - horizontal
    canvas.drawLine(
      Offset(30, size.height / 2),
      Offset(size.width / 2 - 40, size.height / 2),
      centerLinePaint,
    );
    canvas.drawLine(
      Offset(size.width / 2 + 40, size.height / 2),
      Offset(size.width - 30, size.height / 2),
      centerLinePaint,
    );

    // Simple center lines - vertical
    canvas.drawLine(
      Offset(size.width / 2, 30),
      Offset(size.width / 2, size.height / 2 - 40),
      centerLinePaint,
    );
    canvas.drawLine(
      Offset(size.width / 2, size.height / 2 + 40),
      Offset(size.width / 2, size.height - 30),
      centerLinePaint,
    );

    // Lane markers
    canvas.drawLine(
      Offset(30, size.height / 2 - 17),
      Offset(size.width - 30, size.height / 2 - 17),
      lanePaint,
    );
    canvas.drawLine(
      Offset(30, size.height / 2 + 17),
      Offset(size.width - 30, size.height / 2 + 17),
      lanePaint,
    );
    canvas.drawLine(
      Offset(size.width / 2 - 17, 30),
      Offset(size.width / 2 - 17, size.height - 30),
      lanePaint,
    );
    canvas.drawLine(
      Offset(size.width / 2 + 17, 30),
      Offset(size.width / 2 + 17, size.height - 30),
      lanePaint,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
2
likes
160
points
16
downloads

Documentation

API reference

Publisher

verified publishertuesdae.games

Weekly Downloads

Animated vehicle widgets for Flutter with clear visuals and predictable animations. Perfect for traffic games, simulations, and educational apps.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on tuesdae_assets