import 'dart:async'; import 'dart:math' as math; import 'dart:ui' as ui; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:aesthetica_wallpaper/models/drag_puzzle_game.dart'; class DragPuzzleProvider extends ChangeNotifier { DragPuzzleGame? _currentGame; Timer? _timer; DragPuzzleGame? get currentGame => _currentGame; /// 创建拖拽式拼图游戏 Future createDragPuzzle({ required String imagePath, required DragPuzzleDifficulty difficulty, }) async { // 停止之前的计时器 _timer?.cancel(); // 分割图片 final pieces = await _splitImageForDrag( imagePath, difficulty.rows, difficulty.cols, ); // 打乱拼图块顺序 pieces.shuffle(); // 创建游戏 _currentGame = DragPuzzleGame( pieces: pieces, gridRows: difficulty.rows, gridCols: difficulty.cols, imagePath: imagePath, ); // 开始计时 _startTimer(); notifyListeners(); } /// 分割图片为拖拽式拼图块 Future> _splitImageForDrag( String imagePath, int rows, int cols, ) async { final pieces = []; // 加载图片 final ByteData data = await rootBundle.load(imagePath); final codec = await ui.instantiateImageCodec(data.buffer.asUint8List()); final frame = await codec.getNextFrame(); final image = frame.image; final pieceWidth = image.width ~/ cols; final pieceHeight = image.height ~/ rows; // 分割图片 for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { final id = row * cols + col; // 创建图片块 final recorder = ui.PictureRecorder(); final canvas = Canvas(recorder); canvas.drawImageRect( image, Rect.fromLTWH( col * pieceWidth.toDouble(), row * pieceHeight.toDouble(), pieceWidth.toDouble(), pieceHeight.toDouble(), ), Rect.fromLTWH(0, 0, pieceWidth.toDouble(), pieceHeight.toDouble()), Paint(), ); final picture = recorder.endRecording(); final pieceImage = await picture.toImage(pieceWidth, pieceHeight); // 将图片转换为字节数据 final byteData = await pieceImage.toByteData( format: ui.ImageByteFormat.png, ); final uint8List = byteData!.buffer.asUint8List(); pieces.add( DragPuzzlePiece( id: id, correctRow: row, correctCol: col, image: MemoryImage(uint8List), ), ); } } return pieces; } /// 将拼图块放置到指定位置 void placePiece(int pieceId, int targetRow, int targetCol) { if (_currentGame == null || _currentGame!.isComplete) return; final pieces = List.from(_currentGame!.pieces); final pieceIndex = pieces.indexWhere((p) => p.id == pieceId); if (pieceIndex == -1) return; final piece = pieces[pieceIndex]; // 检查目标位置是否已被占用 final existingPiece = _currentGame!.getPieceAt(targetRow, targetCol); if (existingPiece != null) { // 如果目标位置有其他块,将其移回底部 final existingIndex = pieces.indexWhere((p) => p.id == existingPiece.id); pieces[existingIndex] = existingPiece.copyWith( isPlaced: false, currentRow: null, currentCol: null, ); } // 放置当前块 pieces[pieceIndex] = piece.copyWith( isPlaced: true, currentRow: targetRow, currentCol: targetCol, ); // 增加移动次数 final newMoves = _currentGame!.moves + 1; // 更新游戏状态 _currentGame = _currentGame!.copyWith(pieces: pieces, moves: newMoves); // 检查是否完成 if (_currentGame!.checkComplete()) { _completeGame(); } notifyListeners(); } /// 将拼图块移回底部 void removePiece(int pieceId) { if (_currentGame == null || _currentGame!.isComplete) return; final pieces = List.from(_currentGame!.pieces); final pieceIndex = pieces.indexWhere((p) => p.id == pieceId); if (pieceIndex == -1) return; final piece = pieces[pieceIndex]; // 只有已放置的块才能移除 if (!piece.isPlaced) return; pieces[pieceIndex] = piece.copyWith( isPlaced: false, currentRow: null, currentCol: null, ); _currentGame = _currentGame!.copyWith( pieces: pieces, moves: _currentGame!.moves + 1, ); notifyListeners(); } /// 开始计时 void _startTimer() { _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (_currentGame != null && !_currentGame!.isComplete) { _currentGame = _currentGame!.copyWith( elapsedTime: _currentGame!.elapsedTime + const Duration(seconds: 1), ); notifyListeners(); } }); } /// 完成游戏 void _completeGame() { _timer?.cancel(); _currentGame = _currentGame!.copyWith(isComplete: true); } /// 重新开始游戏 void restartGame() { if (_currentGame == null) return; _timer?.cancel(); // 重置所有拼图块 final pieces = _currentGame!.pieces .map( (piece) => piece.copyWith( isPlaced: false, currentRow: null, currentCol: null, ), ) .toList(); // 重新打乱 pieces.shuffle(); _currentGame = _currentGame!.copyWith( pieces: pieces, elapsedTime: Duration.zero, moves: 0, isComplete: false, ); _startTimer(); notifyListeners(); } /// 提示功能 void showHint() { if (_currentGame == null || _currentGame!.isComplete) return; // 找到第一个未正确放置的块 final unplacedPieces = _currentGame!.unplacedPieces; if (unplacedPieces.isNotEmpty) { final hintPiece = unplacedPieces.first; print( '提示:将块 ${hintPiece.id} 放到位置 (${hintPiece.correctRow}, ${hintPiece.correctCol})', ); } } @override void dispose() { _timer?.cancel(); super.dispose(); } }