Dream Build Play – Mines and Slot Machine

I’m now wrapping up the implementation of the gameplay elements in the Turn Back the Clocks 4 game for Dream Build Play.  The two features that I had envisioned adding were mines and a slot machine.

The mines just act as a hazard, which destroy your ball on contact.  Programmatically, this was relatively simple to implement.  The mine is just a GameObject with a sphere collider.  When a ball collides with it, the ball is destroyed.  I do a check in the ball’s on collision method to verify that the object that it has collided with has a Mine component (in other words, has been assigned the Mine script).  I have found that this is a better way to determine an object’s type than using the Unity tagging system.  I don’t know if there are any performance differences, but tagging seems really redundant when the object already has a type from the script that has been assigned to it.  Plus, a GameObject can have multiple scripts assigned, but it can only have one tag.

From doing game jams over the five years, I have really learned a lot tricks.  Others may call this “tools in my toolbox”.  I’ve tried to use an array of the tricks that I’ve learned in this game.  One of those is the Blender Cell Fracture add-on.  This Blender feature will take an object, and break it into multiple pieces based on the parameters that you set.  Then you can apply Blender physics to the broken pieces, which will make the object explode over a period of time, which is saved as an animation.  So I took my ball model (another good reason to use a modeled ball in Blender instead of the default Unity 3D sphere) and applied the cell fracture.  I saved this now model and animation as a ball explosion.  This way, when the ball hits the mine, I can destroy the original ball, and instantiate the ball explosion.  This makes things a lot simpler, keeping the ball and it’s logic separate from the explosion.  The only catch is that you’ve got to pass the ball’s material to the ball explosion, otherwise the explosion will just look like a gray ball breaking apart.  I created a method in the ball explosion, which takes the material of the ball as a parameter.  The other issue is that the ball explosion actually has two materials that are generated by the Cell Fracture plugin.  I know I’ve tried setting the array of materials on an object before, but it never seemed to work.  After some research, I found that GetComponent<Renderer>().materials actually returns a copy of the materials on the object.  So to assign new materials, you have to set the Material array back to the materials property and it will work.  Now when a ball explodes, it is the same color (blue, red, or yellow) of the ball that hit the mine.

The other feature that I wanted to have in the game was a slot machine.  I got this idea from watching Pachinko videos online.  In Pachinko, if a ball goes into the target slot, a slot machine will appear on the video screen.  If all three numbers match, then you get more balls.  I liked the concept of getting more balls from the slot machine.  However, I didn’t like the concept of just matching three numbers.  It just felt too random, and the numbers really didn’t have any significance.  Therefore, I decided to have the prizes on the slot reel, which were the balls which could be won.  Then I had the idea of having a multiplier reel, which increased the number of balls that you would win.  The only thing was, I wasn’t sure how this would work with three reels.  Finally, I just decided to have only two reels, which made things simpler and much easier to under stand.  The first reel is the ball type (blue, red, or yellow) and the second reel is the multipler (x1, x2, or x5).  I wanted the better prizes to be more difficult to win, so each reel has five of the low prizes (blue and x1), two of the middle prizes (red and x2), and only one of the best prizes (yellow and x5).  That makes eight total items on each reel.  The chance of getting the best prize on both reels (yellow ball x5) is 1/8 times 1/8, or a one in sixty-four chance.  That seemed about right to me.  I wanted the best prize to be rare, but not so rare that it will never occur.

I created a SlotMachine script, which controls both of the reels.  I decided against have scripts for each specific reel, although that would be helpful if I had a unknown number of reels.  The SlotMachine script has float variables which store the rotation of each reel.  Each reel is set to a random position, and rotates for a random period of time.  It took me a little while to determine which prize was selected when the reel stopped.  I converted the rotation to an index by dividing by 45 (360 degrees divided by 8 prizes) and rounding to the nearest integer (modulo 8 to take care of the case when the rotation is greater than 315 and it rounds up).  I also have to a 90 to the rotation to get the correct index.  This took me a while to track down, and I can only explain it as being an issue when moving from the Z up coordinate system (in Blender) to the Y up coordinate system (in Unity).  Frequently, when a Blender model is imported into Unity, -90 degrees on the X rotation is automatically applied in the transformation.  However, when you’re handling the rotation yourself, you have to add that 90 degree back to get the correct index.  Texture mapping the reels was not too difficult, but I had to make sure that each of the panels in the UV map lined up exactly over the appropriate square in the texture that I created in Gimp.  I made the reel texture 2048×2048, and each of the panels are 512×512.  I wrote down the sequence of prizes in a text editor, and placed them appropriately on the reel.

I also created a slot entry object, which is just a simple little container mesh with three sides.  The container has a mesh collider on the outside, and a trigger box collider on the inside.  If a ball touches the trigger, then a new SlotMachine object is instantiated.  After both reels on the slot machine stop, then the appropriate number of balls are added to the player’s ball queue.  Another problem arose when a new ball touches the slot trigger, when a SlotMachine is already active, which causes multiple SlotMachines to appear on the screen at the same time.  To fix this, I just simply check to see if a SlotMachine already exists using GameObject.FindComponentOfType<SlotMachine>() before creating a new one.  This is a little unfair, because the player will lose a ball when they should get another turn at the slot machine, so that is something that could be improved by adding something like a lid on the slot entry that closes when a SlotMachine is active.

I think I’ve finished with all of the gameplay elements on this game for now, and I will focus on adding more levels, touching some things up, and make leaderboards work for each level.  Also, I’ve got to submit the game to the Windows Store before the end of the calendar year for the Dream Build Play 2017 competition.

Dream Build Play – Multiple Levels, Stuck Balls

Earlier today, I did some game development off stream.  I was working on the colors for the background.  In previous games like Note Chomper, I have synchronized the hue with the music volume by calculating the RMS value of the AudioSource on the game object playing the music.  It is a nice effect, but sometime appears flickery.  I tried it for this game, and it just didn’t look great.  I tried modifying my code so that it uses frequency instead using the AudioSource GetSpectrumData method, but it still didn’t look right to me.  I also tried setting the hue to the sound of the cannon being shot, but I didn’t like it because it would be one hue (red) at the beginning while the balls were being shot, but then another value (blue) for the rest of the time.  I ended up settling on tying the hue to the current combo value.  I clamped the range from 0 to 50 combo value, which I converted to a 0f to 1f value.  I passed that value to my script which handles setting the background material color, which then sets a target hue.  The hue can be converted to a color using Color.HSVtoRGB, passing the hue as the first parameter and 1f for the second and third parameters.  I then converted my 0f to 1f value to a value in the range of 0.5f (180 degree hue which is cyan) to 0f (0 degree hue which is red).  So as the combo increases, the target hue value moves backwards from cyan to red on the ROYGBIV scale.  I also have value specified for speed of transitioning, so that it is a smooth change in color and it doesn’t jump directly from one hue to another.

I also updated the cannon model.  It didn’t look right before, because it was too small for the balls that it was shooting.  I added a cylinder at the bottom, for where the balls should come out.  I used the boolean modifier to “drill” another smaller cylinder hole in the middle.  I had to ensure that the hole was big enough to give the appearance that the balls were coming out of it.  I also had to significantly increase the size of the model, so much that the top is no longer visible on the screen, but I think that’s not really a problem.

It still really didn’t look like the balls were coming out of the cannon, so I created a particle effect that looks like a puff of smoke.  when the ball is shot, the smoke particle effect is instantiated.  I made it a separate GameObject prefab, which has  a custom script attached that destroys it after a few seconds.  One neat effect that I added is setting the color of the particle effect to that color of the ball that is being shot.  I just pass in the ball score to the SetScoreColor of the particle effect, and it uses the Ball color constants that I defined last time to set the smoke color.  I was really happy with how the effect turned out.

Finally, I added multiple levels to the game.  To do this, I created text files which contain the layout of the clocks on the levels.  I just used an ‘O’ to represent each clock.  I may end up using other letters for future objects to be added to the game.  I put these text files in the Resources folder under Assets in my project, which allows me to assign them to a TextAsset List that I defined in my LevelManager.  I added new parsing code which loops over each line in the text file (rows) and each character in every line (columns).  Based on the row and column position, the clock is Instantiated in the appropriate location.  It’s always important to subtract the row from total rows in the files, otherwise the level layout will be upside down.

Adding a Next Level button was a trivial change.  I added a new function in my Level Manager to handle incrementing the level number, which loops back to zero if it is equal to or greater than the level List size.  I also added a function which deletes all of the objects that are children of the Room object, which is the parent of all of the objects that are Instantiated for a specific instance of a level (the clocks, the cannon, etc).

Another problem that arose from the new level layouts is that sometimes the balls would get stuck between two clocks.  I added code which compared the velocity of the RigidBody of the ball to Vector3.zero (not moving), and destroyed the ball if those are equal.  That worked at first, but I found that when the level restarted, all of the balls were being destroyed.  Apparently on the first Update, the ball’s velocity was getting returned as zero.  To solve this, I added a countdown, which added Time.deltaTime for every frame that the velocity is zero.  Otherwise, it would set the coutdown back to zero (the ball is moving).  Once the countdown reaches a defined value (I used 1f, which is one second) then the ball is destroyed.  I need to go back and add a puff of smoke (probably the same one that I used for the cannon) when the ball is destroyed, so that it doesn’t look like the ball magically disappears.

Dream Build Play – Graphical Updates

There’s only a little more than two weeks left in the Dream Build Play 2017 competition.  I’ve been really busy between work, the Ludum Dare 40 competition, hosting and editing the Knoxville Game Design podcast, and visiting fellow game developers in Lexington, Kentucky.  However, I did manage to find some time tonight to spend working on my Dream Build Play entry called Turn Back the Clocks 4.

I really didn’t update any of the gameplay tonight, and I solely focused on making the graphical user interface stand out.  The first thing on the laundry list in my head was to display the individual points scored for each clock hit.  This is the ball score (5 points for blue, 10 points for red, and 25 points for yellow) multiplied by the current combo.  I really need to add a screen which explains the points system.  Now whenever a clock is hit, the associated score is displayed below the total score and scrolls downward and fades out.  The score text is also the same color as the ball which hit it, so the player can see the score made from one of the bonus (red or yellow) balls.

One problem that I noticed was that the blue text was too difficult to read.  I ended up picking a lighter shade of blue on the Shades of Blue Wikipedia page called Crayon blue, which is #1F75FE in hex or (31, 117, 254) in RGB.  The Unity color selector for the Text component accepted the hex value, but I had to remember to divide those three values by 255 to set the light color in code in Unity, because the Color object expects the RGB values to be floats in the range of 0f to 1f.  I also updated the blue in the clock texture to match accordingly.  I made constant Color variables in my Ball class to hold the red, blue, and yellow ball colors.  This way if I ever need to change the color again, I’m only need to update the color in the Ball constant.

Another change was making the board color lighter.  This made the balls and activated clocks stand out better, but I also had to darken the color of the inactive clocks which were already light gray.  Since the board used the same material as the title text, I duplicated that material.  I haven’t found a way to duplicate materials in the Unity editor, so I just have to select the material and display in explorer, and then copy and paste the material.  Now the title screen has a copy of the material, which I made a golden color.  I disabled the material normal map for the title text, because it looked too gritty.  I also updated the title mesh in Blender, and lined up the Y coordinates of the front vertices of the mesh.  I could see artifacts of the triangles in the light which looked bad.  Lining up the vertices can be done in Blender by scaling by zero on the Y axis.  It still really didn’t look the way I wanted, so I selected the front faces and turned off smooth shading, which fixed the problem.

Going back to the graphical user interface, I thought that the “PERFECT” display looked really plain.  I ended up writing a simple script which scaled the text in and out on the X axis.  I set variables to track if the scale is expanding or contracting along with the rate, minimum, and maximum scale values.  Once the scale value hits one of those boundaries, I flip the sign of the rate value which is multiplied by Time.deltaTime.  I also made the perfect text green, so it stands out from everything else on the screen.  When all of the clocks are enabled, I also added a 20000 score display in green to the the scrolling score values.  There is a slight problem in that the 20000 score displays at the same time as the score of the last clock hit, so it overlaps it.  However, I think that is fine as long as the 20000 score is on top, which is more significant.

The last interface change I made was to the combo display.  I broke the word “Combo” and the multiplier display into two separate text objects.  That way I could keep the size of the “Combo” text the same and scale the size of the multiplier text.  Using some math, I made it so that when the combo value is displayed or incremented, it is twice the regular size, and scales down to normal size during the combo period.  I thought that this emphasized the point that the combo expired over time.

There are a few more changes that I want to make before the competition is over.  I want to add different configurations of the clocks.  I’m not sure if I’m going to do that programmatically or define the layouts in a data file.  I may just have the player play through each of the levels sequentially, but it would be nice if I had a level select screen, with target scores for each of the levels.  If I did that, then I would need to update my leaderboard PHP code and MySQL database to accept scores for different levels on a game.  It wouldn’t be that difficult of a change to make, and it would definitely be useful for leaderboards in my other games.  Games with just one leaderboard could just set the level number to a default value like 0 and just ignore it.

I would also like to include a few more mini-game bonuses like a slots that are enabled if you meet certain conditions.  I’m not sure if that would be when a ball falls in a certain area (like in pachinko) or if it’s enabled when all of the clocks are activated.  I think the extras would all be based on luck, such as spinning a wheel for a bonus.  It would just be something a little different to break up shooting and watching the bouncing balls.