Midterm Project

Concept

Back in school, they wouldn’t give us the WiFi password, so whenever I opened a browser I got stuck on the “No internet” page with the little dinosaur. With nothing else to do, my classmates and I would end up playing the offline dino game, and it got really competitive as we tried to beat each other’s high scores. That memory is where Desert Runner started. I wanted to keep the same simple, addictive feeling of the dino game but make it my own by bringing my culture into it. Instead of a dinosaur jumping over cacti, the main character is an Emirati man in a kandura, ghutra and agal, and instead of cacti he has to get past animals from the UAE desert.

I also wanted the game to have a goal instead of running forever, so I gave it a story. The character is an NYUAD student who leaves campus on Saadiyat Island and gets lost in the desert. Every road takes him further away, first to Sweihan, then Al Ain, then all the way to Liwa, before he finally finds the long road back to Saadiyat. If you reach 2000 points, an NYU Abu Dhabi building appears, he runs up to the door and you win. If you crash, you’re “lost in the desert” and start again from Saadiyat.

How to Hack the Hidden Google Chrome Dinosaur Game

The NYU Abu Dhabi Campus - NYU Abu Dhabi

 

How it works and what I’m proud of

The game is plyed in the following. The player never actually moves forward. He stays in the same spot while the world scrolls toward him, the same trick the dino game uses. Every frame the game updates the speed, score, jumping and obstacles, checks for collisions, and then redraws everything. The jump uses simple gravity. When you press jump he gets an upward speed, and every frame gravity pulls a bit of it away, so the jump curves up and comes back down naturally. Instead of counting frames, the movement uses the time between frames, so the game runs at the same speed on fast and slow computers. The game also slowly speeds up, and the gap between animals grows with the speed, so there is always enough room to land and jump again.

The part I’m most proud of is that everything is drawn with code. There are no images at all. The Emirati man, the snake, oryx, camel and falcon are all built from ellipses, lines, triangles and custom shapes. Animation comes from a sine wave, which makes his arms and legs swing in opposite directions, his ghutra flap in the wind, the snake slither and the falcon flap its wings. Each location also has its own look. Saadiyat has the beach, the sea, dhows and the Louvre dome. Sweihan has camel farms and ghaf trees. Al Ain has Jebel Hafeet, an old fort with the UAE flag and date palms, and Liwa has a sunset over huge red dunes. The scenery is drawn in layers that move at different speeds, so far things move slowly and close things move fast, which gives the world depth. The places also follow the real route you would drive from Saadiyat, and a bar at the top shows how far along the journey you are.

I’m also proud of some game design decisions. The falcon flies at head height, so you have to duck instead of jump. If you try to jump, it swoops up after you, which makes sense for a hunting bird and makes ducking the clear choice. Collisions use invisible boxes that are slightly smaller than the drawings, so you only lose when you clearly hit something. The best score is saved in the browser so it stays when you retry, which brings back the competitive feeling from school, and it resets when you finally make it home so every journey starts fresh. The menu, tutorial and controls screens make it easy for someone new to understand the story and the animals before they play.

. Same speed on every computer. So the movement here is based on the time between frames, and not on counting frames.

// timeStep keeps the game the same speed on fast and slow computers
let timeStep = min(deltaTime / 16.667, 3);

 

. Jumping with gravity. Gravity takes away a little upward speed every frame, so the jump curves up and comes back down.

function updatePlayer(timeStep) {
  if (!player.onGround) {
    player.verticalSpeed -= GRAVITY * timeStep;
    player.height += player.verticalSpeed * timeStep;
    // Landed
    if (player.height <= 0) {
      player.height = 0;
      player.verticalSpeed = 0;
      player.onGround = true;
    }
  }
}

Areas for improvement and problems I ran into

I ran into several problems along the way. The first version of the falcon felt unfair, because it looked low enough to jump over but jumping always made you lose. I fixed this by raising it to head level and making it follow you up when you jump, so losing actually looks right. The music took two to three seconds to start and the crash sound was delayed, because the audio was being streamed like a video. Loading the sound files fully into memory at the start fixed both. My high score also showed 2316 out of 2000 because it had been saved back when the goal was 2500, so I changed how the score is saved and capped it at the goal.

There are still things I would like to improve. I’d like to add lives, so the player gets a few chances before the game ends instead of losing everything on the first hit. I’d also like to make the death scene more interactive, for example by showing an animation of the man falling or the animal reacting, instead of the game just stopping. I’d like to give each location its own animals too, like more camels in Sweihan or snakes in Liwa. Right now the high score only saves on your own computer, so a shared online leaderboard would bring back the real competition with friends. I’d also like to add a pause button and make the controls work better on phones.

References

.Inspiration, the Chrome offline dinosaur game.

.Reference images: Google Images searches for “UAE desert” and cartoon Emirati characters, used for inspiration on clothing, colors and scenery. The final character is my own original design.

.MDN Web Docs, Web Audio API; loading and playing sound files from memory.

.Music “Desert Caravan” by Walen, Free To Use (freetouse.com).

.Distances used to order the route: Bayut Sweihan guide, Wikipedia: Sweihan, Rome2rio Al Ain to Liwa and Rome2rio Liwa to Abu Dhabi.

.The Coding Train, Coding Challenge #147: Chrome Dinosaur Game; how to build the Chrome dino game in p5.js, with a jumping player and obstacles.

.Jumping and gravity: Programming a Retro-Style video game in P5.js, Part 3: simulating gravity and Lesson 2: Simulating Gravity with JavaScript and P5JS: how speed and gravity change the character’s position every frame so he falls back down after jumping.

.Changing scenes: Changing scenes P5 JS: switching between the menu, tutorial, game over and win screens using a game state variable.

.Collision detection: The Coding Train, 8.4 Class and Objects: Collision Detection: checking when the player’s hitbox touches an animal.

.Animation with sine waves: The Coding Train, 3.5 Simple Harmonic Motion (Nature of Code): using sin() to make the arms and legs swing, the falcon’s wings flap and the snake slither.

.Sand dunes and mountains: The Coding Train, I.2: Perlin Noise and p5.js: using noise() for the smooth shapes of the dunes and Jebel Hafeet.

.Saving the high score: Local Storage in JavaScript with p5.js: saving the best score in the browser so it stays after you close the page.

AI  helped me make the Tutorial screen feel more alive. At first I thought of the Tutorial as a page of instructions, but I wanted players to actually see the animals they’d face, not just read about them. Claude explained that each animal’s drawing function takes an animation number, and that number decides where the legs are in their step, how the snake’s body is curved and where the falcon’s wings are. During the game this number goes up as the animal moves. On the Tutorial screen it uses p5.js’s built-in framecount instead, which goes up by 1 every frame. Because the number keeps changing, the snake slithers, the oryx and camel walk in place, and the falcon flaps its wings, all without moving across the screen. This showed me how one variable can bring a still image to life, and that I can reuse the same drawing functions on different screens just by changing the number I give them.

Leave a Reply