Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

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

Step: 1

To integrate the treasure hunt distance view logic into your existing treasure hunt app you can fo... blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

International Marketing And Export Management

Authors: Gerald Albaum , Alexander Josiassen , Edwin Duerr

8th Edition

1292016922, 978-1292016924

More Books

Students also viewed these Programming questions

Question

Where are the iPhone's components produced and purchased?

Answered: 1 week ago

Question

What are the primary reasons for holding inventory?

Answered: 1 week ago