Hello Kitty’s Adventure: The Car Dodging Challenge
I chose this project because for my midterm, I created an experience and for my final, I aimed to challenge myself by creating a game. Additionally, having received my license two months ago, it seemed like the perfect opportunity to develop a game involving cars.
This game, titled “Hello Kitty’s Adventure: The Car Dodging Challenge” lets you control a character resembling Hello Kitty, guiding her left and right to avoid colliding with cars. As you skillfully maneuver past every four cars, the game progresses to a new level, increasing in speed. Your score accumulates with each second you survive. This fun and engaging game is inspired by my long-time fondness for a character similar to Hello Kitty, which has been a favorite of mine since childhood.
P5 Structure : IMG_5852
How the Game Works : IMG_5846
prototype + Schematic (ultrasonic distance sensor, two LEDs) :


Exhibition
The Im showcase on Friday 15th was a blast! It was my first time being part of an exhibition and making a game, which turned out to be super fun. I really enjoyed it, especially chatting with people there. I got loads of compliments and comments on my project, like “Your project was the best,” “Did you make this? It’s amazing,” and “This game is addicting.” It feels great to see my hard work pay off. The course was fun and I’ve been proud of everything i achieved during the course. My friends showed up to support me, and seeing people smile while playing my game was the best part. Zion and Fausto even set the highest score at 77! Here are some pictures and videos from the showcase.

rose playing –> My friend Rose Playing my game
Structure + Challenges
The structure of the project is crafted using recycled cardboard and cork that I found at home, a gesture to honor COP28 held in the UAE. Unfortunately, I couldn’t access the resources and equipment in the IM lab, as I wasn’t available during the weekend. Nevertheless, I am proud of how the prototype turned out. It has a homemade aesthetic that truly showcases the effort and creativity I invested in it. *Update: I drew road markings on the pink paper, to easily direct left right and middle*
The challenges I encountered primarily involved reacquainting myself with p5. After a break spent focusing on Arduino, I felt a bit out of touch with p5 and needed to catch up on some of its features. However, I am pleased with the final result, particularly the pink color scheme I chose, which I feel represents me well. Another significant challenge was working with Arduino. I frequently faced connectivity issues with my laptop, requiring multiple restarts whenever it failed to upload. Additionally, getting the ultrasonic sensor to accurately measure distances was tricky, but after consulting numerous videos, I managed to overcome this obstacle. Despite these challenges, I am proud of what I accomplished. *Update: the issue of the arduino lagging was fixed by Muhammad Khan who was kind enough to fix the code for me, now Id say it works perfectly with no lag*
let car, helloKitty; // images for car and Hello Kitty character
let phase = "startScreen"; // current phase of the game: startScreen, game, endScreen, instructions
let speedCount = 0; // counter to track speed and timing of game elements
let speed = 1; // initial speed of moving cars
let cars = []; // array to hold car objects for collision detection and rendering
let gameOverImg; // image to be displayed when the game is over
let arduinoData = 0; // data received from Arduino for control
let useArduinoControl = true; // flag to enable or disable Arduino control
let rVal = 0;
// -------------------------------------------------------------------------------------
// preloads game assets (images, fonts, sounds)
// before starting the game
function preload() {
car = loadImage("pink1.png");
helloKitty = loadImage("hellokitty.png");
StartUp = loadImage("workpls.png")
customfontkitty = loadFont('kittyfont2.ttf');
customfontsan = loadFont('san.ttf');
gameOverSound = loadSound("ouch.mp3");
introSound = loadSound("introsong.mp3");
leftBorder = loadImage("leftBorder.png");
rightBorder = loadImage("rightBorder.png");
instructionImg = loadImage("instructions8.png");
}
// ----------------------------------------------------------------------------
// sets up the initial state of the game canvas and variables
function setup() {
createCanvas(400, 600);
rectMode(CENTER);
imageMode(CENTER);
kittyX = 115; // initial X position for Hello Kitty
kittyY = 550; // initial Y position for Hello Kitty
score = 0; // initialize score
level = 1; // initialize game level
}
// ----------------------------------------------------------------------------
// The main game loop, executed continuously to render the game
function draw() {
background(50, 140, 80); // set the background color
if (phase == "game") {
fill(255,204,220);
noStroke();
// fisplay the left and right border images on the screen
image(leftBorder, 20,height/2,leftBorder.width*0.55,leftBorder.height*0.55);
image(rightBorder, 380,height/2,rightBorder.width*0.55,rightBorder.height*0.55);
// draw the central playing area
rect(width / 2, height / 2, 320, height);
fill(255);
// creates the road markings
for (let i = 0; i < 4; i++) {
for (let j = -1; j < 10; j++) {
rect(75 + i * 80, (speedCount % 60) + 30 + 60 * j, 6, 50);
}
}
// increment speedCount to control the moving speed of road markings
speedCount += speed;
// arduino Control: Move Hello Kitty based on Arduino input
if (useArduinoControl && arduinoData !== null) {
if (arduinoData < 10) { // move left
kittyX = 115;
} else if (arduinoData >= 10 && arduinoData < 20) { // Move center
kittyX = 195;
} else if (arduinoData >= 20) { // Move right
kittyX = 275;
}
}
// returns the hello kitty to current position
image(helloKitty, kittyX, kittyY, 70, 100);
// on every 50th speed count a car will come down
if (speedCount % 200 == 0) {
cars.push({
x: random([115, 115 + 80, 115 + 160]), // Random lane
y: -40, // Start above the screen
});
}
// move each car
for (let i = 0; i < cars.length; i++) {
image(car, cars[i].x, cars[i].y, 70, 100);
// checks for collision with Hello Kitty
if (dist(cars[i].x, cars[i].y, kittyX, kittyY) < 60) {
phase = "gameOver";
gameOverImg = get(0, 0, width, height);
gameOverSound.play();
introSound.stop();
}
// update car position
cars[i].y += speed * 2;
}
// display score and level
textSize(16);
stroke(255);
strokeWeight(2);
fill("#9B858D");
text("SCORE : " + score, 20, 30);
text("LEVEL : " + level, 320, 30);
// increment score over time
if (frameCount % 60 == 0) {
score++;
}
// increase speed and level after certain intervals
if (speedCount % 1000 == 0) {
speed += 1;
level += 1;
}
}
// ----------------------------------------------------------------------------
// display the game over screen and show score and level reached
if (phase == "gameOver") {
image(gameOverImg,width/2,height/2);
textSize(16);
strokeWeight(2);
stroke(0);
fill(0, 100);
rect(width / 2, height / 2, 240, 150);
fill(255);
stroke(255);
strokeWeight(1);
text("Level " + level + " Reached", 145, 250);
textSize(14);
text(" You Scored " + score, 145, 360);
text(" press Enter to Restart", 135, 330);
fill(255);
textSize(32);
text(" GAME OVER", 105, 300);
}
// checks if the current game phase is the start screen
if (phase == "startScreen") {
if(!introSound.isPlaying()){
introSound.loop();
}
// ----------------------------------------------------------------------------
// start up image and text
background("#9B858D");
fill(255,192,203,0.60);
image(StartUp, width/2, height/2, StartUp.width*0.7, StartUp.height*0.7);
rect(width / 2, height / 2, 380, 580);
stroke(255);
fill(255);
strokeWeight(6);
stroke(255, 192, 230);
fill(255, 105, 180);
textFont(customfontkitty);
textSize(86);
text("hello kitty", 20, 120);
fill(255, 105, 180)
textSize(60);
strokeWeight(2)
stroke(255);
textFont(customfontkitty);
text("adventure", 70, 175);
fill(171,209,158);
rect(width / 2, 480, 200, 80, 50);
fill(255);
textFont(customfontkitty);
text("start", 140, 500);
stroke(171,209,158);
strokeWeight(2)
fill(255);
textSize(28);
text(" Press Enter for Instructions",10,570)
// check if the mouse position is within a specified rectangular area
if (
mouseX > width / 2 - 100 &&
mouseX < width / 2 + 100 &&
mouseY > 460 &&
mouseY < 540
) {
// If the mouse is within the specified area it changes to game phase
if (mouseIsPressed) {
mouseIsPressed = false;
phase = "game";
}
}
}
// -------------------------------------------------------------------------------------
// intruction page
if (phase == "instruction"){
image(instructionImg,200,300,400,600); // display the instruction image
strokeWeight(2);
stroke(0);
textSize(60);
textFont(customfontkitty);
fill(0);
text("How To Play",40,120);
textFont();
textFont(customfontsan);
strokeWeight(1);
textSize(20);
text(" \n 1) move your hands left \n and right to move \n hello kitty \n 2) try to avoid the cars \n 3) BE SAFE!",60,330);
textSize(20);
text(" press enter to go back \n and start! ",70,500)
}
}
// function to handle keyboard inputs
function keyPressed() {
// game control using arrow keys during the 'game' phase
if (phase == "game") {
switch (key) {
case "ArrowLeft":
if (kittyX > 115) {
kittyX -= 80;
}
break;
case "ArrowRight":
if (kittyX < 260) {
kittyX += 80;
}
break;
default:
break;
}
}
// restart the game when 'Enter' is pressed in the 'gameOver' phase
if (phase == "gameOver") {
if (key == "Enter") {
score = 0;
level = 1;
speedCount = 0;
speed = 0;
cars = [];
phase = "startScreen";
kittyX = 75;
kittyY = 550;
key="";
}
}
// handle key presses for navigating between instruction and start screen
if(phase=="instruction"){
if(key== "Enter"){
phase = "startScreen";
key="";
}
}
if(phase=="startScreen"){
if(key== "Enter"){
phase = "instruction";
key="";
}
}
// setup serial communication when spacebar is pressed
if (key == " ")
{
setUpSerial();
}
}
// -------------------------------------------------------------------------------------
// arduino
function mouseIsPressed()
{
readSerial();
}
// This function will be called by the web-serial library
// with each new line of data. The serial library reads
// the data until the newline and then gives it to us through
// this callback function
let lastDataReceivedTime = 0;
function readSerial(data) {
if (data != null) {
arduinoData = parseInt(data);
lastDataReceivedTime = millis();
useArduinoControl = true;
} else if (millis() - lastDataReceivedTime > 2000) { // 2 seconds timeout
useArduinoControl = false;
}
let sendToArduino = 0;
switch (phase) {
case 'game':
sendToArduino = 1;
break;
case 'instruction':
case 'startScreen':
sendToArduino = 2;
break;
case 'gameOver':
sendToArduino = 3;
break;
}
writeSerial(sendToArduino + "\n");
}
const int trigPin = 9; // Pin number for the ultrasonic sensor's trigger pin
const int echoPin = 10; // Pin number for the ultrasonic sensor's echo pin
const int ledgreen = 4; // Pin number for the green LED
const int ledred = 7; // Pin number for the red LED
long duration; // Variable to store the duration of the echo pulse
float distance; // Variable to store the calculated distance
void setup()
{
pinMode(trigPin, OUTPUT); // Set the trigPin as an output
pinMode(echoPin, INPUT); // Set the echoPin as an input
Serial.begin(9600); // Start serial communication at 9600
pinMode(ledgreen, OUTPUT); // Set the green LED pin as an output
pinMode(ledred, OUTPUT); // Set the red LED pin as an output
}
unsigned long ultrasonic_clock = 0;
unsigned long led_clock = 0;
float sum = 0;
int iterator = 0;
void loop()
{
if (millis() - ultrasonic_clock >= 5) // Take reading every 5 ms
{
ultrasonic_clock = millis();
digitalWrite(trigPin, LOW); // Clear the trigPin
delayMicroseconds(2);
digitalWrite(trigPin, HIGH); // Set the trigPin to HIGH state for 10 microseconds
delayMicroseconds(10);
digitalWrite(trigPin, LOW); // Set the trigPin to LOW state
duration = pulseIn(echoPin, HIGH); // Read the echoPin, returns the sound wave travel time in microseconds
distance = duration * 0.034 / 2; // Calculate the distance
sum += distance;
iterator++;
if (iterator == 5) // Average the last 5 readings
{
Serial.println(int(sum / 5));
iterator = 0;
sum = 0;
}
}
if (millis() - led_clock >= 10) // Take reading every 10 ms
{
led_clock = millis(); //record the time this code ran
// reading brightness level from serial
// int brightness = Serial.parseInt();
if(Serial.read() == '\n'){
// controlling LED based on brightness level
if(brightness == 1){
digitalWrite(ledgreen, HIGH);
digitalWrite(ledred, LOW);
}
else if(brightness == 2){
digitalWrite(ledgreen, LOW);
digitalWrite(ledred, LOW);
}
else if(brightness == 3){
digitalWrite(ledred, HIGH);
digitalWrite(ledgreen, LOW);
}
}
}
}
Improvements
For future improvements, I aim to rely less on external help, as I did encounter significant struggles. I plan to apply the skills acquired from tool training to craft an even better prototype using materials like wood and acrylic. Additionally, I’ll consider utilizing various components to enhance the game or possibly explore a different direction and different sensors for this project. Starting earlier will also be a priority, allowing ample time for revisions, enhancements, and potentially incorporating more features. Overall, I am proud of my work and have gained a deep appreciation for the effort, thought, and creativity required by those who do this professionally. Creating a project that not only reflects my aesthetic but also functions effectively has been a rewarding experience. I am extremely pleased with the outcome and feel a sense of accomplishment for what I have achieved.
Sources –
Song : https://www.youtube.com/watch?v=DTU2VpTJ0So
Ouch : https://www.youtube.com/watch?v=J6l4TVqTRpU
Hello Kitty : https://www.pinterest.com/pin/500884789807456421/
Instruction Background : https://www.pinterest.com/pin/2111131070738280/
Instruction Frame : https://www.pinterest.com/pin/4292562138085566/
Help –
https://www.youtube.com/watch?v=0Lhgd8PQmn0
https://www.youtube.com/watch?v=6F1B_N6LuKw
https://editor.p5js.org/azimovbob/sketches/LkvG5pT5g
https://editor.p5js.org/kellycarvalho2024/sketches/tDFpv6VLi
https://github.com/mzohaibnaz/CarRacing-p5
https://medium.com/@yyyyyyyuan/tutorial-serial-communication-with-arduino-and-p5-js-cd39b3ac10ce
https://www.youtube.com/watch?v=feL_-clJQMs
https://labor.99grad.de/typo3-docs/nnarduino/sensors/80_utrasonic/index.html









