Final Project | Dungeon Escapist

Game Description

Dungeon Escapist is a single-player game where players take control of an adventurer and delve through a dungeon. By using a physical controller that reacts with tilting, players can move their character, collect coins, and reach the exit before the time runs out!

Check out DUNGEON ESCAPIST Here!

Project Inspiration

Dungeon Escapist is a game heavily inspired by older titles such as Adventure (1980), with interactive elements from The Legend of Zelda: Breath of the Wild (2017). This game is also a direct sequel to my previous IM game: Pyro Dancer.

Escapist (adjective)

relating to avoiding an unpleasant or boring life by thinking, reading, etc. –Cambridge Dictionary

Unlike the previous game, however, Dungeon Escapist focuses more on problem-solving rather than player reaction. The main character, an adventurer, wishes to gain riches! He began to look around the Adventurer’s Guild to see if there were commissions. Noticing the dungeon-clearing request, our protagonist sets off to explore the uncharted areas in hopes of bathing in fame and fortune.

Gameplay Images

Main Menu Screen

Game Screen with different maps

Gameplay Videos

How the Game Works

The game is built using the p5 Play library. The dungeon (or maze) is an array of sprites. The library can then construct these using their built-in sprite and tiling system. Because of this, the game is able to have three distinct maps easily.

// Print the sensor data to the serial monitor
//currentDirection, X, Y, Z
Serial.print(currentDirection);
Serial.print(",");
Serial.print("X:");
Serial.print(x);
Serial.print(",");
Serial.print("Y:");
Serial.print(y);
Serial.print(",");
Serial.print("Z:");
Serial.println(z);

Arduino sends out a message consisting of a number, the controllerDirection, alongside XYZ information to the Serial Output. The number listed in controllerDirection is read by p5 and moves are made based on that.

//Serial Library function
function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////

  if (data != null) {
    //Only run when there is a Serial message
    let fromArduino = split(trim(data), ",");
    if (fromArduino.length == 4) {
      controllerDirection = int(fromArduino[0]);
    }
  }
}

// Then....

//UP
    if (
      controllerDirection == 12 &&
      isOpen(avatar.x, avatar.y - 1, currentMap) &&
      gameState == 1
    )

Then, inside the game, a function called isOpen() checks whether the space in the array next to the player is free. If it is and the controllerDirection is specific to that direction, the character will move infinitely towards that direction until it hits a wall. This simplicity of the character movement is something I am proud of.

function isOpen(x, y, mapName) {
  //Function to check whether the tile is empty to allow moving
  let i = floor(x);
  let j = floor(y);
  let tile = mapName[j][i];
  if (tile == "." || tile == "x" || tile == "h") {
    return true;
  } else {
    return false;
  }
}

Two major issues that I found to be painful while developing the game are figuring out the scoring system and gameState. It took me a few hours to solve why using multiple game states would crash the game. Ultimately, it all comes down to checking the game state before changing to another one.

The scoring system depends on the game time and coins picked. I wanted to make it such that the longer the player spends solving the dungeon, the less score they get, whereas the coins, act as a score multiplier. I found out that instead of immediately running the timer, I can make it run after the player has collected at least one coin.

User Testing & Feedback

During the production phase (2 & 4 May 2024), the game was tested by several users (thank you). Here are some of the issues that the game encountered:

The first thing I noticed was how players were confused about what to do with the physical controller. To combat this confusion, I decided to add a tutorial screen after the title screen. It also specifically mentions to “tilt” the physical controller for more legibility.

Notable things that I observed were in particular how long it took for players to solve the maze. Originally, I thought it would take <1 minute.

Initial User Testing.

However. given the time it takes for the player to figure out the control scheme, solve the maze, and discover things, the time averages around 4 minutes. The scoring system, which is dependent on the time and coins, has then been adjusted to give leniency to the players.

Another notable issue was player sprite color. Because it looks very similar to the walls, the color has been adjusted for better visibility as well.

I also found out that people kept referring to this game to how similar it is to a mobile game called Tomb of the Mask, a hit mobile game, due to their style.

Production Images

From prototypes to actual product

Future Improvements
  • I originally wanted to make the physical controller pretty. However, by the time I finished the whole game, another project was waiting for me. I will try to see what I can do before the IM Show just to make things a bit more pretty.
  • Scoreboards. I wanted to implement scoreboards so players could compare their scores. However, this was quite difficult to implement. So I’ll try to see what I can do in the meantime.
I.M. Show Reaction!

Many thanks to everyone who played Dungeon Escapist and managed to finish the level! Here are some thoughts, reactions, and comments about the game:

“I was confused with the controls in the beginning … It is quite difficult!” -A professor

“Pretty cool.” -I.M Senior

“It’s difficult to control in the beginning. But once you get the hang of it, it gets easier.” -A lost engineer

“Cool game. The UI/UX can be improved though” -An I.M Professor

I am glad that Dungeon Escapist captured the attention of many. I noticed that the game is ‘easier’ to grasp for younger audiences, whereas the controls and movement of the game are a barricade for adult audiences. By observing the human-machine interaction, I gathered so many insights on how to improve the game. While the difficulty might need to be adjusted, specifically in the map design, I believe the skill ceiling from mastering the physical controller of Dungeon Escapist makes it enjoyable and rewarding.

Resources Used

Assets

Home · Kenney

Royalty Free 8-Bit Background Music Downloads | FStudios (fesliyanstudios.com)

Artstation

Tutorials

How to Use Gyroscopes on the Arduino – Ultimate Guide to the Arduino #43 (youtube.com)

Yes, you can make a Gyroscope using #arduino (youtube.com)

Coding Challenge #66: JavaScript Countdown Timer (youtube.com)

p5play: Using tiles, tilesets, and making pixelated background images with Photoshop (youtube.com)

Final Project Update: Interactive Mood Lamp

Concept

For my final project, I made an interactive mood lamp with five push-buttons corresponding to five moods: Day, Calm, Study, Energetic, and Night. Each mood lights up with a matching color on the arduino and p5, as well as background music from p5.

Implementation

I used a total of 5 push-buttons (3 from the Arduino kit and 2 I had at home), each for one of the moods. I also used a potentiometer to control the light brightness, an RGB LED for the light itself, and some 220ohm resistors I had at home (because I lost the ones from the kit), as well as the breadboard and jumper wires.

Each button is connected to one of the arduino’s digital ports; I used the internal pullup resistors for them to reduce the amount of components needed and to make the circuit simpler. The RGB LED is connected through resistors to PWM ports to have control over the brightness. The potentiometer is connected to an analog input.

When the arduino starts, the light is set to orange as a starting color, with a matching screen on p5 prompting the user to select a mood. Whenever any of the five buttons are pressed, the light switches to that mood’s color, as well as the p5 screen, and matching music is played. Light brightness can be controlled continuously through the potentiometer.

User Testing

I gave each of my sisters my project to try.

My first sister managed to figure it out without any instructions from me, surprisingly even knew which COM port to select. She did not figure out that brightness can be controlled by the potentiometer though.

IMG_7816

My other (younger) sister managed the same, but did not know which what to do when the COM port prompt came up. She also did not realize that brightness can be controlled.

IMG_7817

Areas for Improvement

I should add instructions for the brightness within the program, so that people are aware it can be adjusted.

I also have yet to make a casing for my project, which I hope to finish soon.

Final Project – User Testing

Strengths of the Project

Users understood the relationship between their actions and the game responses well. This was particularly true for tasks involving direct interactions like pressing buttons.

  • Engagement with Tasks: The distance sensing tasks were well-received, as participants found them to be intuitive and fun.
  • Sensor Integration: The integration of the potentiometer within the game mechanics worked smoothly, providing a satisfying challenge to the players.

Areas for Improvement

  • Animation Speed: There was a noticeable slowdown in animation frames as the game progressed, which affected the overall experience. This issue needs to be addressed to ensure smooth gameplay.
  • Keypad Usage: Although the Adafruit Trellis keypad was a central component of the game, many users needed additional instructions to use it effectively.

Enhancements and Future Steps

To make the game more user-friendly and engaging, here are some steps I plan to take based on the feedback:

  • Clarify Sensor Usage: Simplify the riddles associated with sensors or provide clearer, step-by-step tutorials that guide the users on how to interact with the game.
  • Improve Animations: Optimize the code to ensure that animation frames run smoothly throughout the game, enhancing the visual feedback that is crucial for interactive gameplay.

Video for 1st user test/feedback

Video for 2nd user test/feedback

Final Project User Testing – Pi

For my project, I did 9 user test in total, with the people who did not know about my game at all. The procedure is such that I invite them, I start the p5js sketch, set up the camera and let them work out without saying anything.

Gladly, out of 9 subjects, only 2 needed instructions from me, and others at one point were able to figure out the entire experience withotu instruction. The average play time/ or time needed for them to enjoy the experience without needing instructions is 3 minutes. Below are 3 sessions of the user testing.

The only parts where I needed to explain for the 2 users are (1) the user did not read the instructions on the screen and did not know they have to touch the castle and (2) The user did not connect to the right serial port.

In general, this is the feedbacks I get for improvement suggestion.

  1. Cover the breadboard of the castle with a ladder texture to make the design more consistent and hide the electronics.
  2. I need to be more specific in telling which serial port to choose (now I only say usbmodem).
  3. Take out all the debugging functionalities I made for myself in the actual game.
  4. Tell the people to stand up and play (It is more comfortable than sitting down).
  5. Sometimes the bullet hit the enemy, but the enemy  did not die (I need to adjust the collider radius).
  6. Some users did not get the full background story, so probably have a mini comic printed out so that whoever interested can read.

Special Thanks

Special Thanks to Guglielmo Fonda, Aditya Pandhare, Aneeka Paul, Megan Marzolf, Salma Mansour, Sashank Neupane, Lingfen Ren, Lexie and Nastassja for testing my project.

Final Project User Testing – Jihad Jammal

The journey of transforming a concept into a tangible, functional reality is an exhilarating experience, with challenges and discoveries at every turn. The most enjoyable part of this adventure for me was definitely the user-testing phase of my final project. It’s one thing to nurture an idea in your mind or sketch it on paper, but watching real people interact with your creation adds a layer of excitement and invaluable insights.

A significant hurdle I faced was with the servos intended to be a key component of the project. Despite my efforts, I struggled immensely with integrating and programming them. The complexity proved to be beyond the scope of what could be managed within the time and resource constraints of the project I had to make the difficult decision to pivot and remove the servos entirely from the project. This decision, though tough, was necessary to maintain the project’s viability and ensure a smoother user experience.

Pivoting away from using servos forced me to rethink and simplify the design, focusing on what was most essential and functional. This redesign, though less complex, brought its own set of challenges and learning opportunities.

The insights gained from user-testing were invaluable. Observing how users interacted with the revised version of the project without the servos helped me understand the practicality and user-friendliness of my design. The feedback was instrumental in shaping the final tweaks:

Timer needs to be bigger: Users found the timer too small, highlighting the need for a more visible and accessible design. (Alongside that I believe I will increase the size of all text)
Add instructions page: User suggested that there be an instructions page to clarify the objective
Fix dog barking glitch: Dog barking would play over itself causing an awkward sound (potential solution is to increase the delay time between sounds

Week 12: Serial Communication (Aneeka + Amiteash)

Serial Exercise 1

For the first exercise, we used the flex sensor in a voltage divider circuit as the analog input on pin A0 to control the x-axis motion of an ellipse on a screen. The more a flex sensor is bent, the higher the resistance of the flex sensor.

Schematic:

p5 Sketch:

Serial Exercise 2

For the second exercise, we represented the movement of an ellipse along the x-axis, as controlled by mouseX, as the brightness of 2 LEDs, on pins 9 and 11. The green LED increases in brightness as the ellipse moves to the right while the red LED increases in brightness as the ellipse moves to the left.

Schematic:

p5 Sketch:

Serial Exercise 3

Here we edited Prof. Aaron Sherwood’s GravityWind example in p5 to connect to Arduino through Serial Communication. This allows the potentiometer on pin A0 to control wind speed and direction depending on turning of the potentiometer (0 to 1023 mapped to -5 to 5) and for the LEDs on pins 9 and 11 to blink alternately when the ball crosses the bottom end of the screen.

Schematic:

p5 sketch:

Code (for all three)

From the Arduino side, we used a common code, mainly to prevent errors from continuously updating the code. The setup() function set up serial communication and the behavior while a connection was yet to be established. The loop() function was as follows:

void loop() {
  // wait for data from p5 before doing something
  while (Serial.available()) {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
    int left = Serial.parseInt();
    int right = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(leftLedPin, left);
      digitalWrite(rightLedPin, right);
      int sensor = analogRead(potPin);
      delay(5);
      Serial.println(sensor);
    }
  }
  digitalWrite(LED_BUILTIN, LOW);
}

From the p5 side, our code didn’t differ greatly from the Serial Communication template. Where our code differed was mainly in mapping analog inputs to fit the range of values of the sketch width/maximum viable wind speed (for exercises 1 and 3 respectively), while variables called ‘left’ and ‘right’ were assigned to track changes to the LED state due to changes in the sketch.

One code we were particularly proud of in Exercise 3 was how we alternated the blinking of the LEDs depending on the number of times the ball bounced.

if (position.y > height - mass / 2) {
  velocity.y *= -0.9; // A little dampening when hitting the bottom
  position.y = height - mass / 2;
  left = (left + 1) % 2;
  if (left == 0) {
    right = 1;
  } else {
    right = 0;
  }
}

The code for assigning the values to the right LED may look needlessly complicated, and it seems that both could use the (x + 1) % 2 for both LEDs, only assigning one as 0 and the other as 1 at start. However, this method allowed for both LEDs to be dark before the first bounce of each ball (which can be seen in the demo if slowed), which we felt was key to the prompt.

Demo (for all three)

Final Project User Testing – Khalifa Alshamsi

Through user testing, I improved the look of the device itself by covering the wire with insulated heat-shrinkable tubes so that it doesn’t get caught up by anything over the user’s hand. Also, an issue that was resolved after more testing was that, for some odd reason, the code kept looping over the positioning of the UFO, making it glitch after a while of playing the game.

Video of the problem:

After the improvements:

After playing once or twice, people can understand the concept, which made me realize that I needed to create an info tab to finalize the project.

Week 12: Serial Communication (Amiteash + Aneeka)

Serial Exercise 1

For the first exercise, we used the flex sensor in a voltage divider circuit as the analog input on pin A0 to control the x-axis motion of an ellipse on a screen. When the flex sensor is fully bent, The more a flex sensor is bent, the higher the resistance of the flex sensor.

Schematic:

p5 Sketch:

Serial Exercise 2

For the second exercise, we represented the movement of an ellipse along the x-axis, as controlled by mouseX, as the brightness of 2 LEDs, on pins 9 and 11. The green LED increases in brightness as the ellipse moves to the right while the red LED increases in brightness as the ellipse moves to the left.

Schematic:

p5 Sketch:

Serial Exercise 3

Here we edited Prof. Aaron Sherwood’s GravityWind example in p5 to connect to Arduino through Serial Communication. This allows the potentiometer on pin A0 to control wind speed and direction depending on turning of the potentiometer (0 to 1023 mapped to -5 to 5) and for the LEDs on pins 9 and 11 to blink alternately when the ball crosses the bottom end of the screen.

Schematic:

p5 sketch:

Code (for all three)

From the Arduino side, we used a common code, mainly to prevent errors from continuously updating the code. The setup() function set up serial communication and the behavior while a connection was yet to be established. The loop() function was as follows:

void loop() {
  // wait for data from p5 before doing something
  while (Serial.available()) {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
    int left = Serial.parseInt();
    int right = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(leftLedPin, left);
      digitalWrite(rightLedPin, right);
      int sensor = analogRead(potPin);
      delay(5);
      Serial.println(sensor);
    }
  }
  digitalWrite(LED_BUILTIN, LOW);
}

From the p5 side, our code didn’t differ greatly from the Serial Communication template. Where our code differed was mainly in mapping analog inputs to fit the range of values of the sketch width/maximum viable wind speed (for exercises 1 and 3 respectively), while variables called ‘left’ and ‘right’ were assigned to track changes to the LED state due to changes in the sketch.

One code we were particularly proud of in Exercise 3 was how we alternated the blinking of the LEDs depending on the number of times the ball bounced.

if (position.y > height - mass / 2) {
  velocity.y *= -0.9; // A little dampening when hitting the bottom
  position.y = height - mass / 2;
  left = (left + 1) % 2;
  if (left == 0) {
    right = 1;
  } else {
    right = 0;
  }
}

The code for assigning the values to the right LED may look needlessly complicated, and it seems that both could use the (x + 1) % 2 for both LEDs, only assigning one as 0 and the other as 1 at start. However, this method allowed for both LEDs to be dark before the first bounce of each ball (which can be seen in the demo if slowed), which we felt was key to the prompt.

Demo (for all three)

Final Project User Testing

For the user testing, I asked two of my coursemates and asked for their feedback. There were several aspects in the game that they and I had differing opinions but there were also several agreements in terms of improvement of the game. Initially, I had the game with the objective of collecting 10 treasures on both level 1 and level 2, but due to the map size, it seems just 3 to 5 treasures is enough as it would take too much time and might bore the players. Another advice they gave me was to decrease the range of the radar, which actually surprised me, as I thought that the range was too small. Furthermore, we thought it would also be good idea to make the pulsing effect much more slower and inline with the cooldown effect, so that the users will know the cooldown of the radar. I found their opinions in this regard to be most useful and seeing as I also had to explain to them certain instructions and game mechanics.

IMG_4595

Week 12 Reading Reflection

This week’s reading challenged the conventional notion that the primary function of disability aid is utilitarian, which has transformative potential of design within the disability sector. The juxtaposition of functionality with aesthetic appeal, as exemplified by the historical transformation of eyewear from a medical necessity to a fashion accessory, invites us to reconsider the role of design in disability aids. This comparison particularly resonated with me, who has to use glasses every day, prompting a reflection on how cultural and aesthetic elements can significantly alter the perception and functionality of disability aids. I still find it difficult to understand the lack for innovations in eyewear for people who need it for medical reason. You can easily order a meta AI glass from online shops; however, I still can’t find a sunglass with prescription power in most shops.

One passage that stood out to me involves Charles and Ray Eames’s work with plywood leg splints. This example beautifully illustrates how design constraints, rather than stifling creativity, can indeed spur innovation that transcends its original intent. The Eames’s approach to the splints not only fulfilled a medical need but also laid a foundation for design principles that they carried into their later iconic furniture pieces. This prompts me to question whether current design practices within the disability sector might be too constrained by traditional norms that prioritize invisibility and functionality over aesthetic expression.

However, the text also raises critical questions about the balance between form and function. While it advocates for the integration of design and cultural significance into disability aids, it also prompts me to reflect on how such integration should not compromise the practical and accessible nature of these aids. How can designers ensure that the push for aesthetic innovation does not overshadow the essential functionality of disability aids?

The reading has significantly shaped my perception of disability and design. They challenge the ingrained assumption that design for disability must focus solely on functionality and encourage a reevaluation of what constitutes effective design. Moving forward, I am keen to see how these principles can be applied in real-world design projects, ensuring that disability aids not only meet practical needs but also enhance the personal identity and cultural inclusion of their users.