Asteroids Clone

About Asteroids

Asteroids was the first project I created in my personal engine, and my first real project using C++. In the context of my coursework at guildhall, it served as a great way to explore new technologies and carve out the basic framework of my engine in a few short weeks. But my biggest takeaway for asteroids is the importance of juice, and a passion for the work that you're doing.

During the time that we were developing asteroids in-class, I enjoyed exploring ways to make the game feel unique even though we were limited to untextured lines for drawing. Even though it's a simple game to implement, I had so much fun creating asteroids that I chose to go back and continue polishing it much later, with some of the new features I had added to my engine.

Specs

  • Engine: Personal Engine
  • Language: C++, OpenGL

Features




Game Features


Starfield

void Game::AddStars()
{
    //if long enough since last star spawn & not at max stars
    if ((m_stars.size() <= MAX_STARS) && (m_gameTime > m_lastSpawnedStar + 0.3f)){
        //check every "tile" on the screen for perlin noise value. 
        //This determines chance for star spawn, and star size/opacity
        AABB2 tileArea;
        float step = SCREEN_MAX * (1.f / GRID_SIZE);
        for (int x = 0; x < GRID_SIZE; x++){
            for (int y = 0; y < GRID_SIZE; y++){
                float xPos = x * step;
                float yPos = y * step;
                tileArea = AABB2(xPos, yPos, xPos + step, yPos + step);
                float zOnTime =  m_gameTime* SCREEN_MAX * .1f;
                //perlin noise waves cale should be about half the screen size
                float perlinVal = Compute3dPerlinNoise(xPos, yPos, zOnTime, SCREEN_MAX * .5f);      
                if (perlinVal > -0.5f){
                    //fast range map for known range [-.5,1.5] to [0,1]
                    float chanceForStars = (perlinVal + 1 ) * .66667f;   

                    //check square of range-mapped perlin val to get much more spawning in high value areas, 
                    //but at least some spawns in most areas
                    if (CheckRandomChance(chanceForStars * chanceForStars)){
                        AddNewStar(tileArea, chanceForStars * chanceForStars * chanceForStars);
                        m_lastSpawnedStar = m_gameTime;
                    }
                }
            }
        }
    }
    
}

After my first semester at Guildhall, I decided to go back to asteroids, and improve it using everything I had learned. Though my engine had gained many rendering features, I wanted to stick to the untextured line aesthetic from the original asteroids. I chose to create a dynamic galaxy-like background, composed of hundreds of polygonal stars. The effect drastically improves the overall look of asteroids, and was a good investigation of how I can use perlin noise in a variety of different ways.

The starfield is generated by first establishing a grid for the entire screen. These coordinates for these tiles are used to calculate perlin noise for that reason. I used 3D perlin noise for this, with x and y being the respective coordinates of the tile, and z being gametime to get a moving galaxy effect. If the perlin noise value for the tile is high enough, that tile has a chance to spawn a star that frame.

In order to cluster stars in higher noise-value tiles, I squared the 0-to-1 mapped perlin noise value as the random chance that was being checked. This makes it much less likely, but still possible, to spawn stars in areas that barely make the perlin noise threshold, but far more likely in the peak of the noise range. When a star is spawned, it's size, shape, rotation, and color are all randomly selected. I decided to drive the random selection of size and opacity with the same range-mapped perlin noise value that determines the chance to spawn. This led to larger stars appearing in the high-noise areas, while the low-noise areas were mostly small specks.

I also decided to tint the background using time-based perlin noise, to continue to explore that deep-space, galaxy-like aesthetic. In the end, I created random color functions to generate dark-blueish-green hues based on perlin noise values, which were driven by time. I then tinted 4 corners of a quad with these randomly generated colors, which led to a smooth shifting background color.


Back To Top

Faces


After finishing the base asteroids game, I chose to add some "juice" features, to make the game feel more unique to me. With the tools available to me in my brand new engine, I decided to put cute faces on the asteroids.

As asteroids get broken apart, they spawn smaller, more upset asteroids, until the player destroys them entirely. In the context of this game, this required three different faces to be drawn - happy, sad, and angry. In order to make the faces feel good, I wanted to experiment with time, and randomness. To get the glistening effect on the happy asteroid's eye, I chose a random size/translation for the eye highlight each frame. For the crying asteroid's tears, I used a simple sin-wave to construct a wavy mesh, and passed in time as the x coordinate. These are both simple mathematical problems, but the value that they added to the faces was incredible. These elements really made me appreciate the importance of simple, effective juice in games.


Back To Top