How to Create an Engaging Scavenger Hunt with Twilio

July 01, 2022
Written by
Twilion
Reviewed by
Twilion

header - How to Create an Engaging Scavenger Hunt with Twilio

As kids are finishing up school and the days are becoming warmer, consider getting everyone active by sending them on a scavenger hunt around the neighborhood. To make the day more exciting, utilize some Twilio magic by having the participants use their phones to complete puzzles to determine the winner of the scavenger hunt.

This tutorial is intended to present an idea that can be appended to the end of the scavenger hunt game, sort of like an alternate reality game (ARG) that utilizes both the real world and technology.

The flow of the game goes as follows:

  • The user will text the Twilio number to retrieve the URL to play a minigame.
  • The user will play a click-based game that will trigger an SMS to be sent to the host of the scavenger hunt, likely yourself, signifying that someone has completed the scavenger hunt.

In this article, you will learn how to implement a game workflow in the Java Spring Boot Controller and build a mini clicker game that sends an SMS with Twilio.

Tutorial requirements

Add the Thymeleaf and Twilio dependencies

Navigate to the pom.xml file to add the following dependencies between the <dependencies></dependencies> tags:

                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </dependency>
                <dependency>
                        <groupId>com.twilio.sdk</groupId>
                        <artifactId>twilio</artifactId>
                        <version>7.54.2</version>
                </dependency>

The Spring Boot Starter Thymeleaf is required to build web applications that serve HTML. This is essential for creating the web-based clicker game.

This dependency allows the Twilio Java Helper Library to be used and executed in this Maven project. This is essential for the controller class that will be created later on to handle the TwiML messages of this SMS project.  

Save the file.

Look at the top-right corner of the IntelliJ IDEA and find the little icon with an "M" shape. Click it to load Maven changes.

An icon with an "M" shape with a tooltip "Load Maven Changes"

Customize the web controller

After you’ve set up your application, navigate back to the WebController.java file that was created during the setup prerequisites, and replace the contents with the following code:

package com.example.scavengerhunt;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.stereotype.Controller;

@Controller
public class WebController {
    @GetMapping("/game")
    public String helloGame() {
        return "game";
    }
}

Remember that the package in the first line will vary depending on the name of your Java project. The project is named "scavengerhunt" in this tutorial.

The WebController has a helloGame() method that returns a string referencing the path name for the HTML template page that will be rendered.

Build the click-based minigame with Twilio SMS

There are multiple parts to this project. The webpage portion of the project is the click-based minigame that will trigger an SMS to be sent to the host of the scavenger hunt, likely yourself, signifying that the player has completed the scavenger hunt.

Create the HTML page

The objective of this clicker game is to make a POST request whenever the user clicks on a moving picture. Once the image is clicked, an SMS is sent to the game host to inform them that someone has reached the end of the scavenger hunt. At the same time, an alert is made to let the player know that the host was informed.

Go ahead and place a picture that you would like to see in the minigame in the src/main/resources/static subfolder. The /static subfolder is a location for all static assets to be used and referenced throughout this project.

Find the src/main/resources/templates subfolder and create a new file named game.html. This file will be rendered from the helloGame() method in the web controller.

Copy and paste the following code to the game.html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>The Final Stage</title>
</head>
<body>
    <h1>Click on Rilakkuma quickly!</h1>
    <br><img id = "banana" src="/<FILE_NAME_FOR_IMAGE>" alt="description for image here">

    <script>
        var banana = document.getElementById("banana");
        banana.onclick = function(e) {
            alert("Informing the host that you are the winner!");
            fetch("/sendSMS", {method:"POST"})
                .then(response => response.text())
                .then(data => console.log(data));
        }
    </script>
</body>
</html>

Be sure to replace <FILE_NAME_FOR_IMAGE> with the name for the image you uploaded in the src/main/resources/static subfolder. You can also replace the variable and img id names to match your project.

The image is given an id so that it can be retrieved from the Document Object Model (DOM). In the example for this article, a pixelated image of Rilakkuma inside a banana is used, so the variable and id names will be related to the banana. This banana image is retrieved from the document in the JavaScript portion so that an onclick event function can be attached to the image.

The following logic is defined inside the function:

  • Once the image is clicked on, an alert shows up to the player to let them know the host has been alerted.
  • A fetch request is made to the /sendSMS route.

Here's an example of the expected HTML page at the end of the article:

Webpage prompting user to click image of Rilakkuma, alerting the host

Add some animation to the minigame

This will be a fun section for those who enjoy using CSS and JavaScript to make their websites interactive. This clicker game will offer some challenging elements with the help of CSS to make the image move across the screen. This is intended to be a little challenge, just for fun.

Copy and paste the following code in between the <head></head> tags in the game.html file:

    <style>
        @keyframes bounce {
            0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
            40% {transform: translateY(-30px);}
            60% {transform: translateY(100px);}
            0% {
                opacity: 0;
                transform: translateX(2000px);
            }
            60% {
                opacity: 1;
                transform: translateX(-30px);
            }
            80% {
                transform: translateX(10px);
            }
            100% {
                transform: translateX(0);
            }
        }
        #banana {
            width: 200px;
            height: 100px;
            position: center;
            animation: bounce 2s ease alternate infinite;
        }
    </style>

The banana image is altered with the CSS id selector. With the help of @keyframes, a bounce animation is created for the image to bounce across the screen. Clicking the image is the small challenge within the minigame on the webpage.  

Feel free to alter the CSS as you wish or add more properties and functions to make it more fun.

Configure the environment variables

It is best practice to protect your Twilio account credentials by setting environment variables.

You can find your account credentials on the Twilio Console.

Twilio Account Credentials showing hidden account SID and authentication token

Refer to this article to set up and hide variables in the IntelliJ IDEA environment.

Not only is it mandatory to set the Twilio credentials as environment variables, it is also suggested that you store both your Twilio phone number and personal phone number as environmental variables. This would be helpful in the case that the code is shared on a public repository so that the phone numbers are not exposed.

Go ahead and follow the same instructions to store YOUR_PHONE_NUMBER and TWILIO_PHONE in the IntelliJ IDEA environment. The Twilio phone number and personal number must be stored in E.164 format such as "+19140201400".

Build the REST controller

Recall that the Twilio number will send a text twice within the scope of this project.

  • When the player texts the phone number to retrieve the game link.
  • When the player wins the game and triggers an SMS to be sent on their behalf.

A few HTTP requests are necessary for the flow of this clicker game. The REST controller file is essential for serving data and REST endpoints.

Create a file named GameRestController.java within the same subfolder and paste the following code:

package com.example.scavengerhunt;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Message;

@RestController
public class GameRestController {
    @PostMapping(value="/sms", produces = "application/xml")
    public ResponseEntity<String> sendTwiML(@RequestParam(value = "From", required = false) String incomingCallerNumber) {
        Twilio.init(System.getenv("TWILIO_ACCOUNT_SID"), System.getenv("TWILIO_AUTH_TOKEN"));
        String TWILIO_PHONE = System.getenv("TWILIO_PHONE");
        String gameSite = "https://XXXXXXXX.ngrok.io/game";
        String RECIPIENT_NUM = incomingCallerNumber;
        Message message = Message.creator(
                        new com.twilio.type.PhoneNumber(RECIPIENT_NUM),
                        new com.twilio.type.PhoneNumber(TWILIO_PHONE),
                        gameSite)
                .create();
        return new ResponseEntity<String>("Message sent successfully", HttpStatus.OK);
    }
}

Remember that the package in the first line will vary depending on the name of your Java project.

The @RestController annotation marks the request handler required to build and provide the RESTful web service during runtime.

Begin by defining the first route the player hits. This /sms route uses the environment variables set in the previous section to make a connection to the Twilio services. In addition, the system retrieves the phone numbers that were set in the IDE as well.

Another String variable named "gameSite" is created to store the custom URL for the minigame link.

One of the paid features of ngrok is that it allows creating custom domains instead of the "XXXXXXXX" placeholder as seen in the code. Thus, it is important to change this URL so that it applies to your case.

For the purposes of this article, a randomly generated URL will be sufficient as you are the only one who needs to know the URL path to the /game page. When you are ready to share this live, it would be convenient to have a static URL hardcoded so that it's ready to be texted whenever this program is run.

Send an SMS in Spring Boot

Now the magical part – writing the code that sends the SMS to you, the game host, once the image is clicked.

Copy and paste the following code inside the GameRestController class so that it is aligned with the other @PostMapping route:

    @PostMapping(value = "/sendSMS")
    public ResponseEntity<String> sendSMS() {
        Twilio.init(System.getenv("TWILIO_ACCOUNT_SID"), System.getenv("TWILIO_AUTH_TOKEN"));
        String TWILIO_PHONE = System.getenv("TWILIO_PHONE");
        String YOUR_PHONE_NUMBER = System.getenv("YOUR_PHONE_NUMBER");
        Message.creator(
                new com.twilio.type.PhoneNumber(YOUR_PHONE_NUMBER),
                new com.twilio.type.PhoneNumber(TWILIO_PHONE),
                "We have a winner!").create();
        return new ResponseEntity<String>("Message sent successfully", HttpStatus.OK);
    }

Similarly, a connection to the Twilio services is made, in addition to retrieving YOUR_PHONE_NUMBER since Twilio will be sending an SMS to your personal device.

We create a new message instance of the Message resource as provided by the Twilio REST API in order to send an SMS to your personal phone number from your Twilio phone number. The SMS will inform the host that a winner has been identified, along with a success message after firing the SMS.

Play the clicker game

It's time to test out the game flow! Here is the GitHub repository in case you need to check the code.

You are encouraged to test the game out on two different SMS enabled devices. Go ahead and use the second phone whose number is not an environment variable, and text a message such as "hi" to the Twilio number to receive the game link.

The user texts a Twilio phone number, and the phone number replies with a link to a game

The following gif shows the demonstration of the gameplay for the given URL:

A player clicks on a moving image as a game. Clicking the image reveals a prompt that the player won

Check your personal device for the last SMS as seen here:

Push notification from a Twilio phone number that reads: We have a winner!

Nice! The group scavenger hunt can end and the winner can be awarded a prize.

What's next for building Java minigames?

Congratulations on building a clicker game that utilizes the real world as a platform as well as technology!

As you can see, there are plenty of ways you can be creative and introduce some Twilio magic to your physical, real-world activities.

While you send groups of friends and family onto their own scavenger hunt challenges, why not spend the time challenging yourself to expand on this project? Look into how you can build a more creative game flow for an ARG or make more minigames.

Explore some other neat Java Spring Boot projects.

Let me know what games you're building by reaching out to me over email.

Diane Phan is a software developer on the Developer Voices team. She loves to help beginner programmers get started on creative projects that involve fun pop culture references. She can be reached at dphan [at] twilio.com or LinkedIn.