new targets
This commit is contained in:
@@ -26,6 +26,7 @@ class TargetViewScreen extends StatefulWidget {
|
||||
class _TargetViewScreenState extends State<TargetViewScreen> {
|
||||
int _currentIndex = 0;
|
||||
List<Offset> _bullets = [];
|
||||
List<Offset> _scaledBullets = []; // Bullets scaled to display target size
|
||||
int _totalScore = 0;
|
||||
Offset? _targetCenter;
|
||||
Uint8List? _targetImageBytes;
|
||||
@@ -35,7 +36,10 @@ class _TargetViewScreenState extends State<TargetViewScreen> {
|
||||
int? _pressedScoreGroup;
|
||||
late String _targetFilePath;
|
||||
late String targetAssetPath;
|
||||
late String _selectedTargetPath; // For display
|
||||
final double bulletSize = 19;
|
||||
double _scaleFactorX = 1.0; // Scale factor for X coordinate
|
||||
double _scaleFactorY = 1.0; // Scale factor for Y coordinate
|
||||
|
||||
Color _bulletColor = Colors.blue; // default/fallback bullet color
|
||||
String _selectedLanguage = 'English';
|
||||
@@ -72,7 +76,10 @@ class _TargetViewScreenState extends State<TargetViewScreen> {
|
||||
Future<void> _loadSelectedTarget() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final selectedTarget = prefs.getString('selectedTarget') ?? 'assets/target.png';
|
||||
targetAssetPath = selectedTarget;
|
||||
// Always use default target for bullet positioning
|
||||
targetAssetPath = 'assets/target.png';
|
||||
// Store selected target for display
|
||||
_selectedTargetPath = selectedTarget;
|
||||
_backgroundColor = _getBackgroundColorForTarget(selectedTarget);
|
||||
}
|
||||
|
||||
@@ -81,37 +88,54 @@ class _TargetViewScreenState extends State<TargetViewScreen> {
|
||||
switch (targetPath) {
|
||||
case 'assets/target.png':
|
||||
return const Color(0xFFFFFFFF); // White
|
||||
|
||||
case 'assets/targets/Target1.jpg':
|
||||
return const Color(0xFFE8ECD5); // Light beige
|
||||
|
||||
case 'assets/targets/Target2.jpg':
|
||||
return const Color(0xFFC1DF87); // Light green
|
||||
|
||||
case 'assets/targets/Target3.jpg':
|
||||
return const Color(0xFFFEFEFE); // Off-white
|
||||
|
||||
case 'assets/targets/Target4.jpg':
|
||||
return const Color(0xFFD42931); // Red
|
||||
|
||||
case 'assets/targets/Target5.jpg':
|
||||
return const Color(0xFF02050A); // Very dark blue/black
|
||||
|
||||
case 'assets/targets/Target6.jpg':
|
||||
return const Color(0xFF000000); // Black
|
||||
|
||||
return const Color(0xFFF3E7D1); // Light beige
|
||||
case 'assets/targets/Target7.jpg':
|
||||
return const Color(0xFFFFD454); // Bright yellow
|
||||
|
||||
case 'assets/targets/Target11.jpg':
|
||||
case 'assets/targets/Target8.jpg':
|
||||
return const Color(0xFF1E5E81); // Dark teal blue
|
||||
|
||||
case 'assets/targets/Target14.jpg':
|
||||
case 'assets/targets/Target9.jpg':
|
||||
return const Color(0xFFFEFEFC); // Off-white
|
||||
|
||||
case 'assets/targets/Target15.jpg':
|
||||
case 'assets/targets/Target10.jpg':
|
||||
return const Color(0xFF98926E); // Olive green
|
||||
|
||||
case 'assets/targets/Target11.jpg':
|
||||
return const Color(0xFF13132B); // Dark blue
|
||||
case 'assets/targets/Target12.jpg':
|
||||
return const Color(0xFFF5F4EF); // Off-white
|
||||
case 'assets/targets/Target13.jpg':
|
||||
return const Color(0xFF174AA5); // Blue
|
||||
case 'assets/targets/Target14.jpg':
|
||||
return const Color(0xFFFEE05E); // Light yellow
|
||||
case 'assets/targets/Target15.jpg':
|
||||
return const Color(0xFFFFFFFF); // White
|
||||
case 'assets/targets/Target16.jpg':
|
||||
return const Color(0xFF000000); // Black
|
||||
case 'assets/targets/Target17.jpg':
|
||||
return const Color(0xFF13132B); // Dark blue
|
||||
case 'assets/targets/Target18.jpg':
|
||||
return const Color(0xFF050608); // Very dark gray
|
||||
case 'assets/targets/Target19.jpg':
|
||||
return const Color(0xFFC32534); // Dark red
|
||||
case 'assets/targets/Target20.jpg':
|
||||
return const Color(0xFFFCF3EE); // Light beige
|
||||
case 'assets/targets/Target21.jpg':
|
||||
return const Color(0xFFDA6868); // Muted red
|
||||
case 'assets/targets/Target22.jpg':
|
||||
return const Color(0xFFFDFAF3); // Off-white
|
||||
case 'assets/targets/Target23.jpg':
|
||||
return const Color(0xFFFFFFFD); // White
|
||||
case 'assets/targets/Target24.jpg':
|
||||
return const Color(0xFFFFC4C6); // Light pink
|
||||
default:
|
||||
return Colors.white; // Fallback to white
|
||||
}
|
||||
@@ -167,20 +191,33 @@ class _TargetViewScreenState extends State<TargetViewScreen> {
|
||||
|
||||
Future<void> _loadJsonAndImage() async {
|
||||
try {
|
||||
final byteData = await rootBundle.load(targetAssetPath);
|
||||
final bytes = byteData.buffer.asUint8List();
|
||||
_targetImageDecoded = img.decodeImage(bytes);
|
||||
// Load default target for bullet positioning reference
|
||||
final defaultByteData = await rootBundle.load(targetAssetPath);
|
||||
final defaultBytes = defaultByteData.buffer.asUint8List();
|
||||
img.Image? defaultTargetDecoded = img.decodeImage(defaultBytes);
|
||||
|
||||
if (defaultTargetDecoded == null) {
|
||||
print("Failed to decode default target image.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate target center from default target (for bullet positioning)
|
||||
_targetCenter = Offset(
|
||||
defaultTargetDecoded.width / 2,
|
||||
defaultTargetDecoded.height / 2 - 1,
|
||||
);
|
||||
|
||||
// Load selected target for display
|
||||
final displayByteData = await rootBundle.load(_selectedTargetPath);
|
||||
final displayBytes = displayByteData.buffer.asUint8List();
|
||||
_targetImageDecoded = img.decodeImage(displayBytes);
|
||||
|
||||
if (_targetImageDecoded == null) {
|
||||
print("Failed to decode image.");
|
||||
print("Failed to decode display target image.");
|
||||
return;
|
||||
}
|
||||
|
||||
_targetImageBytes = Uint8List.fromList(img.encodePng(_targetImageDecoded!));
|
||||
_targetCenter = Offset(
|
||||
_targetImageDecoded!.width / 2,
|
||||
_targetImageDecoded!.height / 2 - 1,
|
||||
);
|
||||
|
||||
final currentFile = widget.jsonFiles[_currentIndex];
|
||||
final jsonString = await currentFile.readAsString();
|
||||
@@ -210,6 +247,18 @@ class _TargetViewScreenState extends State<TargetViewScreen> {
|
||||
|
||||
_targetFilePath = currentFile.path;
|
||||
|
||||
// Calculate scale factors based on image dimensions
|
||||
_scaleFactorX = _targetImageDecoded!.width / defaultTargetDecoded.width;
|
||||
_scaleFactorY = _targetImageDecoded!.height / defaultTargetDecoded.height;
|
||||
|
||||
// Scale bullets to match display target size
|
||||
_scaledBullets = _bullets.map((bullet) {
|
||||
return Offset(
|
||||
bullet.dx * _scaleFactorX,
|
||||
bullet.dy * _scaleFactorY,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
_totalScore = _bullets
|
||||
.map((b) => _scoreForBullet(b, _targetCenter!))
|
||||
.fold(0, (sum, score) => sum + score);
|
||||
@@ -386,12 +435,15 @@ class _TargetViewScreenState extends State<TargetViewScreen> {
|
||||
height: displayHeight,
|
||||
child: Image.memory(_targetImageBytes!, fit: BoxFit.fill),
|
||||
),
|
||||
..._bullets.asMap().entries.map((entry) {
|
||||
..._scaledBullets.asMap().entries.map((entry) {
|
||||
final i = entry.key;
|
||||
final bullet = entry.value;
|
||||
final dx = bullet.dx * scaleX + offsetX;
|
||||
final dy = bullet.dy * scaleY + offsetY;
|
||||
final score = _scoreForBullet(bullet, _targetCenter ?? Offset.zero);
|
||||
final scaledBullet = entry.value;
|
||||
// Scaled bullets are already scaled to display target dimensions
|
||||
final dx = scaledBullet.dx * scaleX + offsetX;
|
||||
final dy = scaledBullet.dy * scaleY + offsetY;
|
||||
// Score is calculated using original bullet position and default target center
|
||||
final originalBullet = _bullets[i];
|
||||
final score = _scoreForBullet(originalBullet, _targetCenter ?? Offset.zero);
|
||||
final isHighlighted = widget.isCombinedView
|
||||
? (_pressedScoreGroup == score)
|
||||
: (i == _highlightedBulletIndex);
|
||||
|
||||
Reference in New Issue
Block a user