Dana Vrajitoru
B583/C490/I400 Game Programming and Design

B583/C490/I400 Lab 3

Due Date: Wednesday, September 14, 2022.

In this lab we will start writing a slot machine simulation game. Here is a working example. Here is a snapshot of the game:

We will use some Unity objects to create the functionality of a button.

Project

Create a new Unity 2D project called Slots. Download the following archive of images to a local folder and extract the files:
lab3assets.zip
You will find a folder called lab3assets in the zip file.

In Unity, create the usual folders in the Assets: Art, Scenes, and Scripts. From the file explorer, drag all the image and audio files into the Art folder in Unity. Save the scene as slots in the Scenes folder you created.

Click on the Game tab, then on the Free Aspect above the blue area and select 16:9. This ensures that your game will look the same no matter how the window is resized.

Drag the machine image to the scene and scale it holding the shift so that it covers most but not all of the window. Set its Position Z coordinate to 0.1.

Button

Use the + menu below the Hierarchy to create a "Capsule" 2D object and resize to look like a button and to fit in the area to the right of the word "Jackpot". Set its color to a dark blue and its name as rollButton. Then add a component to it, from Physics 2D -> Polygon Collider 2D. You should see a green shape that fits the object pretty well. You probably don't need to edit it.

Create an empty object and add a Text Mesh Pro component to it, containing the test "Roll" in a white color, with the name rollTxt. Adjust its size and make it fit over the button, and then make it a child of the button. Set its Position Z coordinate to -0.1.

Add a new script component to the button and call it ButtonManager. Move the script to the Scripts folder and then open it. Just like the last week, at the top of the class add the attribute

public bool mouseIsOver;

This will be set to true when the mouse is over the button, and false when it exits. This way, when a mouse click happens, we will know if we clicked on this button or not. In the function Start, set it to false.

Add the following functions inside the class:

void OnMouseOver()
{
    mouseIsOver = true;
}
void OnMouseExit()
{
    mouseIsOver = false;
}

Declare the following public attributes in the class:

public Color colorIdle, colorHover, colorClick;

Save the script and come back to Unity. Click on the pick button next to Color Idle and use the color picker to select the same color as the capsule object. Then repeat the procedure with Color Hover, but this time after picking the same color, move the color point towards a lighter shade. Then set an even lighter color to Color Click.

Now we can activate the colors for when the mouse moves over the object. First, since we'll be using the sprite renderer component a lot, declare the following attribute:

SpriteRenderer renderer;

Then in the function Start, cache the component into it by doing

renderer = GetComponent <SpriteRenderer>();

Now, in OnMouseOver, add the following line:

renderer.color = colorHover;

Then in OnMouseExit, reset the color to idle. If your button turns transparent in either case, check the Alpha value of the color and make sure it's not set to 0.

Now to click the button, we need to add functionality to on mouse down and on mouse up. On mouse down, we'll set the color of the button to clicked. On mouse up, we'll set the color back to idle. Add the following to the function Update:

if (mouseIsOver)
    if (Input.GetMouseButtonDown (0)) 
    {
        renderer.color = colorClick;
    }
    else if (Input.GetMouseButtonUp(0))
    {
        renderer.color = colorIdle;
    }

We'll add more functionality to these later. Go back and test this. Nothing much seems to be happening. This is because the mouse over keeps being detected, which resets the color to Hover.

To fix this, we need to add another boolean attribute, clicked. Initialize this in the function Start as false. Then when the mouse button is down, set it to true. Then in OnMouseOver, add a test if clicked is false before setting the color (but leave the assignment to mouseIsOver out of it). Finally, in OnMouseExit, set it back to false. Test this to make sure it works. This is now ready to go.

We can do one more thing with the button, which is adding a clicking sound. In Unity, add a component to the button: from Audio - Audio Source. Drag the sound called press from the Sounds in Assets folder on the Audio Clip attribute of the Audio Source component. Make sure that none of the flags of this component are checked, such as Play On Awake. Then in Visual Studio, add the following line inside the block for when the button is down in the function Update:

GetComponent<AudioSource>().Play();

Run the game to check if the sound is played when we click the button.

Reel Objects

Zoom in on the 3 white squares. The scroll button zooms in and out. The right mouse button can be used to move the whole scene around.

Drag 3 of the square sprites and place them over them. You will probably need to scale them down. Scale the first of them manually, then look in the Inspector at the values of the Scale in the Transform. Round those to 2 or 3 digits, then set the same value to the Scale over X and Y for all 3 sprites. This should set them with the same size and perfectly square.

Then set the Y coordinate in the Position area of the Transform with the same value for all 3 of them. This way they are aligned with each other. For example, for my settings 0.82 for the scale and 2.15 for the Y position worked well. Your values could be different depending on how you scaled the machine sprite.

In Inspector, name the three square sprites reelL, reelM, and reelR. These objects will hold the random images resulting from rolling the reels. Some randomizing will happen to them and the sprite they display will also change. Zoom out to see the whole area again.

Add an Audio Source component to each of these objects. Then set the audio clip for the left object as the lost clip, the middle one as the tap clip, and the right one as the win clip. This way, we can play all of the clips from the script.

Let's make the reels spin when we click on the button. But first, we need to add some references to these objects in the class.

Add the following attribute to the class ButtonManager:

public GameObject[] reels;

Then set its size in Unity to 3 and drag the 3 reel objects (not the images) onto its elements from left to right. Before we can spin the images, we need access to all the sprites that we can display on these reels.

Create an array of Sprite type called sprites. In Unity, set its size to 5 and drag all the sprites to its elements. Spinning these reels will be done through the function Update. Since this function is called once per frame of the game, we need a function to initialize the spinning when the mouse button is up, and another one to continue spinning for a while, and eventually stop. We will use a countdown for the number of times each reel will spin.

Add the following class attributes:

int[] countDown;
bool spinning;

Then in the function Start, add the following lines:

countDown = new int[reels.Length];
spinning = false;

The starting function will initialize each countdown with a different value.

Add the following function to the class:

void StartSpin()
{
    for (int i = 0; i < reels.Length; i++)
        countDown[i] = 10*(i+1);
    spinning = true;
}

Call this function inside the function Update, when the mouse button is up, after changing the sprite of the button. Then the function that actually spins the reels has to be called from the function Update every time the variable spinning is true. For each spin, the function will choose a random sprite and assign it to the reel object.

Add the following function to the class

void SpinReels()
{
    spinning = false;
    for (int i = 0; i < reels.Length; i++)
    {
        if (countDown[i] > 0)
        {
            spinning = true;
            countDown[i]--;
            int j = Random.Range(0, sprites.Length);
            reels[i].GetComponent<SpriteRenderer>().sprite = sprites[j];
            if (countDown[i] == 0)
                reels[1].GetComponent<AudioSource>().Play();
        }
    }
}

Then call this function inside the function Update within a test for spinning being true. We still need to store the values of the reels when we stop so that we can decide if the player has won or lost.

Add as class attribute an integer array called reelVal and initialize it the same way as the countDown in the function Start. Then inside the function SpinReels, assign to the element i of this array the random value j.

Then add a function called CheckWin that checks if the values of the 3 reels are the same, and if they are, play the sound from reels[1], otherwise play the one of index 2. Then go back to the function SpinReels and at the end, after the loop, check if the value of spinning is false (we've stopped spinning) and call the function CheckWin if that is the case.

The game will be continued in the homework.