LogoDart Beginner Tutorials

Time Management Async Await Future and More ifelse

This part adds asynchronous functionality to simulate time passage impacting hunger and happiness levels and refines ifelse usage.

Welcome to Part 4! In the previous recipe, we built the core functionality for feeding and playing with our digital pet. Now, let's add a crucial element of realism: the passage of time. This will dynamically change our pet's hunger and happiness levels, making the game more engaging. To accomplish this, we'll introduce asynchronous programming in Dart using async, await, and Future.

Understanding Asynchronous Programming

Asynchronous programming allows your program to perform multiple tasks concurrently without blocking the main execution thread. This is especially important when dealing with time-consuming operations, like waiting for a certain amount of time to pass (as in our case). In Dart, we achieve this using async, await, and Future.

  • Future: A Future represents a value that might not be available immediately. It will eventually resolve to a value (or an error).
  • async: The async keyword marks a function as asynchronous, allowing the use of await .
  • await: The await keyword pauses execution within an async function until a Future completes.

Step 1: Introducing the timePasses() Function

Let's create a new function, timePasses(), in our DigitalPet class. This function will simulate the passage of time, increasing hunger and decreasing happiness. We'll use Future.delayed() to introduce a pause before updating the values.

  Future<void> timePasses() async {
    print('Time passes...');
    await Future.delayed(Duration(seconds: 1));
    hunger++;
    happiness--;
  }

Future.delayed() creates a Future that completes after the specified Duration. The await keyword pauses the execution of timePasses() until this Future completes (after one second).

Step 2: Adding Clamping to Prevent Overflow

We need to ensure that our hunger and happiness values remain within the range of 0 to 10. We can do this using the .clamp() method. This method takes a minimum and maximum value as arguments.

    hunger = hunger.clamp(0, 10);
    happiness = happiness.clamp(0, 10);

Step 3: Refining if/else for Feedback

Now, let's add more sophisticated feedback using if/else statements to check the hunger and happiness levels after time passes.

    if (hunger >= 10) {
      print("${name} is very hungry!");
    }
    if (happiness <= 0) {
      print("${name} is very sad!");
    }

Step 4: Integrating timePasses() into main

Finally, let's integrate the timePasses() function into our main function. We'll call it periodically to simulate time.

  // ... existing code ...

  // Add this line to call timePasses after other actions
  await myPet.timePasses();

  // ... existing code ...

Now, each time you feed or play with your pet, the timePasses() function will be called. You will see the effects of time on hunger and happiness.

That's it for Part 4! We've successfully implemented asynchronous programming to make our simulation more dynamic. We’ve also refined our use of if/else statements for better control flow and added clamping to prevent out-of-bounds values. In Part 5, we'll add more advanced controls using switch statements and while loops, further improving your interaction with the game. We will also introduce encapsulation.