Question: using Flutter I have created a treasure hunt app. It's such that when a user taps on a treasure to find it displays either found

using Flutter I have created a treasure hunt app. It's such that when a user taps on a treasure to find it displays either found or too far. I would like to make the user experience much better by displaying to the user the distance between them and the treasure. So when they start moving it should display how far they are and if they are still far away, the distance should be in red, if they are almost there it should be yellow and if they are within the 20m radius which I stated in this treasure hunt code, the distance should be in green which will then make the user know that they can tap on the treasure to find it. it saves them the stress of having to just keep tapping on the found treasure button without any clue on if they are close to the treasure or not. Please can anyone implement these features to my code? Please don't show an example code instead implement it into mine as it makes it easier for me to understand and learn my concept rather than a new concept. i have a treasure hunt distance view code that implements this logic but I'm struggling to integrate it or call it into my treasure hunt view where the user has to tap to find the treasures. and use it so the user can actually see their distance from a treasure.

 

 Below is a treasurehunt distance view  code.


import 'package:flutter/material.dart';
import 'package:hunt/hunt_views/treasure_view.dart';
import 'package:haversine_distance/haversine_distance.dart' as hd;
import 'package:location/location.dart' as lc;

class TreasureDistanceView extends StatefulWidget {
  final Treasure treasure;
  final lc.LocationData userLocation;

  TreasureDistanceView({required this.treasure, required this.userLocation});

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

class _TreasureDistanceViewState extends State {
  final hd.HaversineDistance haversineDistance = hd.HaversineDistance();

  @override
  Widget build(BuildContext context) {
   double? userLatitude = widget.userLocation.latitude;
double? userLongitude = widget.userLocation.longitude;
double distance = 0.0;
if (userLatitude != null && userLongitude != null) {
  distance = haversineDistance.haversine(
    hd.Location(userLatitude, userLongitude),
    hd.Location(widget.treasure.latitude, widget.treasure.longitude),
    hd.Unit.METER,
  );
}
Color distanceColor;
String distanceText;
if (distance <= 20) {
  distanceText = "You found the treasure!";
  distanceColor = Colors.green;
} else if (distance <= 50) {
  distanceText = "You're getting close! Distance: ${distance.toStringAsFixed(1)}m";
  distanceColor = Colors.yellow;
} else {
  distanceText = "Distance: ${distance.toStringAsFixed(1)}m";
  distanceColor = Colors.red;
}


    return Text(
      distanceText,
      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: distanceColor),
    );
  }
}
 

Below is the treasurehunt view where the logic takes place

import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:haversine_distance/haversine_distance.dart' as hd;
import 'package:location/location.dart' as lc;
import 'package:share_plus/share_plus.dart';
class Treasure {
  double latitude;
  double longitude;
  String name;
  bool found = false;

  Treasure(
      {required this.latitude, required this.longitude, required this.name});

  factory Treasure.fromSnapshot(DocumentSnapshot snapshot) {
    return Treasure(
      latitude: (snapshot.data() as Map)['lat number'],
      longitude: (snapshot.data() as Map)['long number'],
      name: (snapshot.data() as Map)['hint name'],
    );
  }
}

class TreasureHuntView extends StatefulWidget {
  final String collectionName;
  final List treasures;

 

  TreasureHuntView({required this.collectionName, required this.treasures,});

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

class _TreasureHuntViewState extends State {
  int foundTreasures = 0;
  lc.LocationData? userLocation;
  final lc.Location location = lc.Location();
  final hd.HaversineDistance haversineDistance = hd.HaversineDistance();
  Duration timeLeft = Duration(minutes: 1);
  Timer? timer;
 

  @override
  void initState() {
    super.initState();
    location.getLocation().then((locationData) {
      setState(() {
        userLocation = locationData;
        timer = Timer.periodic(Duration(seconds: 1), (Timer t) {
          setState(() {
            print(locationData);
            timeLeft = timeLeft - Duration(seconds: 1);
            if (timeLeft.inSeconds <= 0) {
              t.cancel();
              showDialog(
                context: context,
                builder: (BuildContext context) {
                  return AlertDialog(
                    title: const Text("Time is up!"),
                    content: const Text("You didn't find all the treasures in time."),
                    actions: [
                      ElevatedButton(
                        child: const Text("OK"),
                        onPressed: () {
                          Navigator.of(context).pop();
                        },
                      ),
                      ElevatedButton(
                        child: const Text("Reset"),
                        onPressed: () {
                          Navigator.of(context).pop();
                          setState(() {
                            timeLeft = Duration(minutes: 10);
                            foundTreasures = 0;
                            widget.treasures.forEach((treasure) {
                              treasure.found = false;
                            });
                          });
                        },
                      ),
                    ],
                  );
                },
              );
            }
          });
        });
      });
    }).catchError((e) {
      // Handle the error here
      print(e);
    });
  }

  @override
  void dispose() {
    timer?.cancel();
    super.dispose();
  }


  void _onTreasureTapped(int index) {
    double distance = haversineDistance.haversine(
        hd.Location(userLocation?.latitude ?? 0, userLocation?.longitude ?? 0),
        hd.Location(widget.treasures[index].latitude,
            widget.treasures[index].longitude),
        hd.Unit.METER);
    if (distance <= 20) {
      setState(() {
        widget.treasures[index].found = true;
        foundTreasures++;
      });
      if (foundTreasures == widget.treasures.length) {
          // Store user's details in the leaderboard collection
  FirebaseFirestore.instance.collection('leaderboard').add({
   
    'score': widget.treasures.length,
    'time': DateTime.now(),
    'treasurehunt': widget.collectionName,
  });
  // Show congratulatory dialog

        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: const Text("Congratulations!"),
              content: const Text("You have found all the treasures!"),
              actions: [
                ElevatedButton(
                  child: const Text("OK"),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
                ElevatedButton(
                  child: const Text("Reset"),
                  onPressed: () {
                    Navigator.of(context).pop();
                    setState(() {
                      foundTreasures = 0;
                      widget.treasures.forEach((treasure) {
                        treasure.found = false;
                      });
                    });
                  },
                ),
              ],
            );
          },
         
        );
      } else {
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: const Text("Congratulations!"),
              content: const Text("You have found a treasure! Keep searching."),
              actions: [
                ElevatedButton(
                  child: const Text("OK"),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
      }
    } else {
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text("Too far"),
            content: const Text("You are too far from the treasure"),
            actions: [
              ElevatedButton(
                child: const Text("OK"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }
}



 
  @override
  Widget build(BuildContext context) {
 
    return Scaffold(
      appBar: AppBar(
        title:
            Text(widget.collectionName, style: TextStyle(color: Colors.white)),
        backgroundColor: Color.fromARGB(255, 255, 0, 255),
        elevation: 0,
        actions: [
          IconButton(
            icon: Icon(Icons.share),
            onPressed: () {
              Share.share(
                'Check out my score in this awesome treasure hunt game!',
                subject: 'Treasure Hunt Game',
              );
            },
          )
        ],
      ),
      body: Column(

        mainAxisAlignment: MainAxisAlignment.center,
        children: [

         const  SizedBox(height: 10,),

           Text('Time left: ${timeLeft.inMinutes}:${timeLeft.inSeconds.remainder(60)}'),
           
          Container(
           

            padding: EdgeInsets.all(16),
            child: Text(
                "Found ${foundTreasures} of ${widget.treasures.length} treasures"),
          ),
       
          Expanded(
            child: GridView.builder(
              itemCount: widget.treasures.length,
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  mainAxisSpacing: 10.0,
                  crossAxisSpacing: 10.0,
                  childAspectRatio: 1.0),
              itemBuilder: (BuildContext context, int index) {
                return Card(
                  elevation: 5.0,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10.0)),
                  child: Column(
                    children: [
                      const SizedBox(height: 10.0),
                      Text(
                        widget.treasures[index].name,
                        style: TextStyle(
                            fontSize: 18.0, fontWeight: FontWeight.bold),
                      ),
                      const SizedBox(height: 10.0),
                      widget.treasures[index].found
                          ? Icon(
                              Icons.check,
                              color: Colors.green,
                            )
                          : SizedBox(),
                      SizedBox(height: 10.0),
                      InkWell(
                        onTap: () => _onTreasureTapped(index),
                        child: Container(
                          width: double.infinity,
                          decoration: BoxDecoration(
                              color: Colors.blue,
                              borderRadius: BorderRadius.circular(10.0)),
                          child: const Center(
                            child: Text(
                              "Find Treasure",
                              style: TextStyle(
                                  color: Colors.white,
                                  fontWeight: FontWeight.bold),
                            ),
                          ),
                        ),
                      )
                    ],
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
 

below is the home page where the user selects what treasure hunt they want to play and when they select it then it takes them to the treasure hunt list which is the code above with the different treasures find. If you need any more information please do not hesitate to ask thanks

 

mport 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart' hide NavigationDrawer;
import 'package:google_nav_bar/google_nav_bar.dart';
import 'package:hunt/hunt_views/main_view.dart';
import 'package:hunt/hunt_views/map_view.dart';
import 'package:hunt/hunt_views/profile_view.dart';
import 'package:hunt/hunt_views/settings_view.dart';
import 'package:hunt/hunt_views/treasure_view.dart';

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

  @override
  State createState() => _HomeViewState();
}

class _HomeViewState extends State {



  final user = FirebaseAuth.instance.currentUser!;
  final CollectionReference completedTreasureHuntCollection =
      FirebaseFirestore.instance.collection(
    'completed_treasure_hunts',
  );
  List treasureHuntOneLocations = [];
  List treasureHuntTwoLocations = [];
  List treasureHuntThreeLocations = [];
  List> completedTreasureHunts = [];

  @override
  void initState() {
    super.initState();

    // Retrieve locations for treasurehunt one
    final CollectionReference treasureHuntOneCollection = FirebaseFirestore
        .instance
        .collection('treasurehunt')
        .doc('treasurehuntone')
        .collection("locations");
    treasureHuntOneCollection.get().then((querySnapshot) {
      querySnapshot.docs.forEach((doc) {
        Treasure treasure = Treasure.fromSnapshot(doc);
        treasureHuntOneLocations.add(treasure);
      });
    }).catchError((e) {
      // Handle the error here
      print(e);
    });

    // Retrieve locations for treasurehunt two
    final CollectionReference treasureHuntTwoCollection = FirebaseFirestore
        .instance
        .collection('treasurehunt')
        .doc('treasurehunttwo')
        .collection("locations");
    treasureHuntTwoCollection.get().then((querySnapshot) {
      querySnapshot.docs.forEach((doc) {
        Treasure treasure = Treasure.fromSnapshot(doc);
        treasureHuntTwoLocations.add(treasure);
      });
    }).catchError((e) {
      // Handle the error here
      print(e);
    });

    // Retrieve locations for treasurehunt three
    final CollectionReference treasureHuntThreeCollection = FirebaseFirestore
        .instance
        .collection('treasurehunt')
        .doc('treasurehuntthree')
        .collection("locations");
    treasureHuntThreeCollection.get().then((querySnapshot) {
      querySnapshot.docs.forEach((doc) {
        Treasure treasure = Treasure.fromSnapshot(doc);
        treasureHuntThreeLocations.add(treasure);
      });
    }).catchError((e) {
      // Handle the error here
      print(e);
    });

    // Retrieve completed treasure hunts of the user
    completedTreasureHuntCollection
        .where('email', isEqualTo: user.email)
        .get()
        .then((querySnapshot) {
      querySnapshot.docs.forEach((doc) {
        completedTreasureHunts.add(doc.data() as Map);
      });
    }).catchError((e) {
      print("Error retrieving completed treasure hunts: $e");
    });
  }



  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text("Select Treasure Hunt"),
        backgroundColor:  Color.fromARGB(255, 0, 0, 0),
        elevation: 0,
      ),
      drawer: const NavigationDrawer(),
     
     
      body: Column(
        children: [
          const SizedBox(
            height: 20,
          ),
          Container(
            padding: EdgeInsets.all(10),
            alignment: Alignment.centerLeft,
            decoration: BoxDecoration(
                color: Color.fromARGB(255, 0, 0, 0),
                borderRadius: BorderRadius.only(
                    topRight: Radius.circular(20),
                    bottomRight: Radius.circular(20))),
            child: Text(
              "Welcome " + user.email!,
              style: TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 18.0,
                  color: Colors.white),
              textAlign: TextAlign.left,
            ),
          ),
          const SizedBox(
            height: 20,
          ),
          Expanded(
            child: ListView(
              children: [
                Container(
                  decoration: BoxDecoration(
                      border: Border(
                          bottom: BorderSide(
                              color: Colors.grey[300]!.withOpacity(1),
                              width: 1.0))),
                  child: ListTile(
                    leading: Icon(
                      Icons.location_on,
                      color: Colors.green,
                    ),
                    title: Text(
                      "Treasure Hunt One",
                      style: TextStyle(
                          fontWeight: FontWeight.bold, fontSize: 18.0),
                    ),
                    onTap: () {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (context) => TreasureHuntView(
                                collectionName: "TreasureHunt One",
                                treasures: treasureHuntOneLocations)),
                      );
                    },
                  ),
                ),
                Container(
                  decoration: BoxDecoration(
                      border: Border(
                          bottom: BorderSide(
                              color: Colors.grey[300]!.withOpacity(1),
                              width: 1.0))),
                  child: ListTile(
                    leading: Icon(
                      Icons.location_on,
                      color: Colors.green,
                    ),
                    title: Text(
                      "Treasure Hunt Two",
                      style: TextStyle(
                          fontWeight: FontWeight.bold, fontSize: 18.0),
                    ),
                    onTap: () {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (context) => TreasureHuntView(
                                collectionName: "TreasureHunt Two",
                                treasures: treasureHuntTwoLocations)),
                      );
                    },
                  ),
                ),
                Container(
                  decoration: BoxDecoration(
                      border: Border(
                          bottom: BorderSide(
                              color: Colors.grey[300]!.withOpacity(1),
                              width: 1.0))),
                  child: ListTile(
                    leading: Icon(
                      Icons.location_on,
                      color: Colors.green,
                    ),
                    title: Text(
                      "Treasure Hunt Three",
                      style: TextStyle(
                          fontWeight: FontWeight.bold, fontSize: 18.0),
                    ),
                    onTap: () {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (context) => TreasureHuntView(
                                collectionName: "TreasureHunt Three",
                                treasures: treasureHuntThreeLocations)),
                      );
                    },
                  ),
                ),
              ],
            ),
          ),
        ],
       
      ),
     
    );
   
  }
}

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock

To integrate the treasure hunt distance view logic into your existing treasure hunt app you can fo... View full answer

blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Programming Questions!