JavaScript Text Adventure Game
Tags: javascript, beginners, programming, tutorial
Published: 2024-06-20 04:54:33

**Intro:** This is a small text adventure game created with JavaScript, HTML5, and CSS. 

**Demo link:** [https://youtube.com/shorts/F167r8qaQok?feature=share](https://youtube.com/shorts/F167r8qaQok?feature=share)

**Note:** This could have been done with fewer lines of code. Anyway you take it and do as you please

```html
<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0"> 
	<title>the Old Forest</title>
	<link rel="stylesheet" href="a_new_world.css">
</head>
<body>
	<div id="stage">
		<h1>the Old Forest</h1>
		<img src="" width="400" height="367">
		<p id="output"></p>
		<input id="input" type="text" placeholder="Enter your action...">
		<button>enter</button>
	</div>
	<script src="a_new_world.js"></script>
<body>
</html>
```

```css
*
{
  font-family: Merriweather;
  font-size: 15px;
  color: #000;  
  padding: 0px;
  margin: 0px;
}

@font-face 
{
  font-family: Merriweather;
  src: url("C:/Users/petix/AppData/Local/Microsoft/Windows/Fonts/Merriweather-Regular.ttf");
}

@font-face 
{
  font-family: Merriweather-Bold;
  src: url("C:/Users/petix/AppData/Local/Microsoft/Windows/Fonts//Merriweather-Bold.ttf");
}

@font-face 
{
  font-family: Ginga;
  src: url("C:/Users/petix/AppData/Local/Microsoft/Windows/Fonts//Ginga.ttf");
}

h1
{
  text-align: center;
  font-family: Ginga;
  font-size: 80px;
  padding-bottom: 10px;
  padding-top: 20px;
  font-weight: normal;
}
em
{
  font-size: 14px;
}
p
{
  width: 300px;
  margin: 0px auto;
}

img
{
  margin: 0px auto;
  display: block;
  margin-bottom: 20px;
}

input
{
  position: absolute;
  bottom: 30px;
  left: 135px;
  width: 160px;
  padding: 2px 2px 2px 5px;
  border: 1px solid black;
  background-color: rgba(255,255,255,0.3);
  -webkit-box-shadow: 5px 5px 3px rgba(0,0,0,0.5);
	-moz-box-shadow: 5px 5px 3px rgba(0,0,0,0.5);
	box-shadow: 3px 3px 5px rgba(0,0,0,0.4);
  margin-top: 20px;
  display: block;
  margin-left: auto;
  margin-right: auto;
}

button
{
  position: absolute;
  bottom: 30px;
  left: 310px;
  height: 25px;
  width: 50px;
  
  font-family: Merriweather;
	font-size: 14px;
	color: #000;
	border: 1px solid #000;
	
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;	
	
	background:-webkit-linear-gradient(top, rgba(255,255,255,0.6), rgba(0,0,0,0.2));
	background:-moz-linear-gradient(top, #a3a3a3, rgba(0,0,0,0.2));
	background: linear-gradient(top, #a3a3a3, rgba(0,0,0,0.2));
	
	-webkit-box-shadow: 5px 5px 3px rgba(0,0,0,0.5);
	-moz-box-shadow: 5px 5px 3px rgba(0,0,0,0.5);
	box-shadow: 3px 3px 5px rgba(0,0,0,0.4);
	
	-webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  display: block;
  margin: 10px auto 0 auto;
}

body{
	display: flex;
	justify-content: center;
	align-items: center;
	height: 100vh;
	margin: 0;
}


#stage
{
  width: 500px;
  height: 700px;
  background-color: gray;
  position: relative;
  background-image: url("C:/Users/petix/Downloads/page1.png");
  text-align: center;
  padding-bottom: 50px;
}
```

```javascript
// Create the map
var map = [];
map[0] = "An old stone keep.";
map[1] = "A deep well.";
map[2] = "A sunny glade.";
map[3] = "A sleeping dragon.";
map[4] = "A narrow pathway.";
map[5] = "A bridge.";
map[6] = "An ancient gate.";
map[7] = "The edge of a river.";
map[8] = "A lonely wooden bench.";
map[9] = "An isolated cottage. Faint music comes from inside.";

// Set the player's start location
var mapLocation = 4;

// Set the images
var images = [];
images[0] = "keep.jpg";
images[1] = "well.jpg";
images[2] = "glade.jpg";
images[3] = "dragon.jpeg";
images[4] = "path.jpg";
images[5] = "bridge.jpg";
images[6] = "gate.jpg";
images[7] = "river.jpg";
images[8] = "bench.jpg";
images[9] = "cottage.jpg";

// Set the new images for when riddles are solved
var solvedImages = [];
solvedImages[0] = "solved_bridge.png"; // Image after solving the first riddle
solvedImages[1] = "solved_river.png";  // Image after solving the second riddle
solvedImages[2] = "solved_dragon.jpeg"; // Image after solving the third riddle

// Set the blocked-path messages
var blockedPathMessages = [];
blockedPathMessages[0] = "The path is blocked by thick brambles.";
blockedPathMessages[1] = "A steep cliff prevents you from going east.";
blockedPathMessages[2] = "The path is flooded and impassable.";
blockedPathMessages[3] = "A large boulder blocks your way.";
blockedPathMessages[4] = "A landslide blocks the path.";
blockedPathMessages[5] = "The way is blocked by a raging fire.";
blockedPathMessages[6] = "The path is covered in ice.";
blockedPathMessages[7] = "A magical barrier blocks your way.";
blockedPathMessages[8] = "A fallen tree blocks the path.";

var riddleSolved = [false, false, false]; // Track which riddles have been solved
var riddleAttempts = [3, 3, 3]; // Track remaining attempts for each riddle

//sets the text that is displayed when the user is at the riddle location
var riddleLocationMessages = [];
riddleLocationMessages[0] = "A huge troll stands in the middle of the bridge blocking your way to the other side. He asks you a riddle.";
riddleLocationMessages[1] = "An eerie looking water nymph stands in the river and prevents you from moving with her magical powers.<br>She asks you a riddle.";
riddleLocationMessages[2] = "You are now in an old castle standing before a dragon sleeping on treasure. A sinister dwarf appears before you and asks you a riddle.";

// Set the positive fate Messages
var positiveFateMessages = [];
positiveFateMessages[0] = "<br>" + "The troll disappears. Now you can walk safely over the bridge.";
positiveFateMessages[1] = "<br>" + "The river nymph disappears.";
positiveFateMessages[2] = "You are suddenly transported back home safely standing in your backyard.";

//set the negative fate messages
var negativeFateMessages = [];
negativeFateMessages[0] = "The troll stomps on the bridge and the bridge broke sending you into the fast-flowing river.";
negativeFateMessages[1] = "The river nymph calls for her other friends and they drown you in the river.";
negativeFateMessages[2] = "The dwarf steals a golden goblet from the dragon and disappears. The dragon wakes up, sees you, and burns you to a crisp.";

// Create the riddles and set their locations
var riddles = [];
riddles[0] = "<em><br>Riddle: Walk right through me, never feel me. Always lurking, never seen. What am I?</em>";
riddles[1] = "<em>Riddle: What always runs but never walks,<br>has a bed but never sleeps?</em>";
riddles[2] = "<em>Riddle: I am always hungry, I must always be fed,<br>The finger I touch will soon turn red.</em>";
var riddleLocations = [5, 7, 3];


var gameLost = false;
var answeredRight = false;

// Create an array of correct answers for the riddles
var riddleAnswers = ["air", "river", "fire"];

// Initialize the player's input
var playersInput = "";

// Initialize the gameMessage
var gameMessage = "";

// Create an array of actions the game understands
// and a variable to store the current action
var actionsIKnow = ["north", "east", "south", "west"];
var action = "";

// An array of items the game understands
// and a variable to store the current item
var answer = "";

// The img element
var image = document.querySelector("img");

// The input and output fields
var output = document.querySelector("#output");
var input = document.querySelector("#input");

// The button
var button = document.querySelector("button");
button.style.cursor = "pointer";
button.addEventListener("click", clickHandler, false);

// Display the player's location
render();

//when the button is pressed this fucntion is called
function clickHandler() {
    playGame();
}

//create a function called playGame
function playGame() {
    // Get the player's input and convert it to lowercase
    playersInput = input.value.toLowerCase();
    
    // Reset these variables from the previous turn
    gameMessage = "";
    action = "";
    answer = "";
    
    // Figure out the player's action
    for (var i = 0; i < actionsIKnow.length; i++) {
        if (playersInput.indexOf(actionsIKnow[i]) !== -1) {
            action = actionsIKnow[i];
            break;
        }
    }

    // Figure if the player answered the riddle correctly
    for (var i = 0; i < riddleAnswers.length; i++) {
        if (playersInput.indexOf(riddleAnswers[i]) !== -1) {
			//if the user answers the riddle correctly then
			//the answer variable gets one of the riddle answers 
            answer = riddleAnswers[i];
        }
    }

    // if the player arrives at a riddle location and if it's not solved
    if (riddleLocations.includes(mapLocation) && !riddleSolved[riddleLocations.indexOf(mapLocation)]) {
		//get the index of the riddle location
        var riddleIndex = riddleLocations.indexOf(mapLocation);
		//if the player answered the riddle correctly
        if (answer === riddleAnswers[riddleIndex]) {
			//display a positive fate message
            gameMessage = positiveFateMessages[riddleIndex];
			//mark the riddle as solved
            riddleSolved[riddleIndex] = true;
            riddles[riddleIndex] = ""; // Remove the riddle
            riddleLocationMessages[riddleIndex] = ""; // Remove the riddle location message
            images[mapLocation] = solvedImages[riddleIndex]; // Change the image
            if (riddleIndex === 2) { // Check if the final riddle is solved
				//answeredRight gets true as its value
                answeredRight = true;
            }
        } else {
			//if the player gives a wrong answer attempt will be decreased by one
            riddleAttempts[riddleIndex]--;
			//if the player uses all their attempts
            if (riddleAttempts[riddleIndex] <= 0) {
				//if the riddle location is 5
                if (mapLocation === 5) {
					//display a negative message
                    gameMessage = negativeFateMessages[0] + "<br>" + " Game over!!";
					//set gameLost to true
                    gameLost = true;
				//if the riddle location is 7
                } else if (mapLocation === 7) {
					//display a negative message
                    gameMessage = negativeFateMessages[1] + "<br>" + " Game over!!";
					//set gameLost to true
                    gameLost = true;
				//if the riddle location is 3 
                } else if (mapLocation === 3) {
					//display a negative message 
                    gameMessage = negativeFateMessages[2] + "<br>" + " Game over!!";
					//set gameLost to true
                    gameLost = true;
                }
            } else {
                gameMessage = "Incorrect answer. You have " + riddleAttempts[riddleIndex] + " attempts left.";
            }
        }
    } else {
        // Determine the target location based on the action
        var targetLocation = mapLocation;
		//set the value of blockedPathMessage to an empty string
        var blockedPathMessage = "";
		
		//display block messages if the user wants to go outside the map area
        switch (action) {
            case "north":
			    //move the player up 
                if (mapLocation >= 3) {
					//
                    targetLocation -= 3;
                } else {
                    blockedPathMessage = blockedPathMessages[0];
                }
                break;
            case "east":
				//move the player right
                if (mapLocation % 3 != 2) {
                    targetLocation += 1;
                } else {
                    blockedPathMessage = blockedPathMessages[1];
                }
                break;
            case "south":
				//move the player down
                if (mapLocation < 6) {
                    targetLocation += 3;
                } else {
                    blockedPathMessage = blockedPathMessages[2];
                }
                break;
            case "west":
				//move the player left
                if (mapLocation % 3 != 0) {
                    targetLocation -= 1;
                } else {
                    blockedPathMessage = blockedPathMessages[3];
                }
                break;
        }

        //if the 
        if (targetLocation === mapLocation) {
            gameMessage = blockedPathMessage;
			// Ensure that the player can only access riddle locations sequentially
        } else if (targetLocation === riddleLocations[1] && !riddleSolved[0]) {
            gameMessage = "You must solve the first riddle before you can proceed.";
        } else if (targetLocation === riddleLocations[2] && !riddleSolved[1]) {
            gameMessage = "You must solve the second riddle before you can proceed.";
        } else {
            mapLocation = targetLocation; // Update the player's location
        }
    }

    // Reset the player's input field to an empty string
    input.value = "";

    // Disable input and button if game is lost or final riddle is solved
    if (gameLost || answeredRight) {
		output.innerHTML = "<br><em>" + gameMessage + "</em>";
        input.disabled = true;
        button.disabled = true;
    }

    // Render the game
    render();
}

function render() {
    // Render the location
    output.innerHTML = " Try any of these words: " + "<br>" + "north, east, south, west";
    image.src = "C:/Users/petix/OneDrive/Desktop/" + images[mapLocation];
    
    // Display an item if there's one in this location
    var riddleIndex = riddleLocations.indexOf(mapLocation);
    if (riddleIndex !== -1 && riddles[riddleIndex] !== "") {
        output.innerHTML = riddleLocationMessages[riddleIndex] + '<br>' + riddles[riddleIndex];
    }

    // Display the game message
    if (gameLost) {
        output.innerHTML = "<br><em>" + gameMessage + "</em>";
    }
	//if the gameMessage is still empty then display this
	else if(gameMessage) {
		output.innerHTML += "<br><em>" + gameMessage + "</em>";
	}
}

```