Sunday, November 19, 2023

CAGD 377 Sprint 6

At the start of Sprint 6, I made a list of the three most important tasks that needed to be done for the game to be ready: getting the aspect ratio nailed down, getting items implemented, and getting the art assets in the game.

So my first exploit was getting the UI scaling to work. The task was pretty easy, but required a search for what to do. I set Unity to the Samsung phone simulator and reorganized the UI, scaling everything appropriately and making room for the art assets to be included. After some tinkering with the camera, I got the scale to change properly, and did some testing.


With the UI scaling locked in, I moved to finishing up items. While I had done some work with items in the main scene, and our lead had done some work with items in the inventory scene, we were yet to tie the two together.

First, that required some bug fixing. I added a quick fix to ensure that save data was retained on scene transfer, and a hooking function to the scam button to make sure it can always attach to the PlayerManager after the scene has been unloaded and loaded again.

Now that we had a library of our items, I gave the GeneratorManager a reference to it so it knows what the items are. That way, after it activates discovering an item, it can decide what the item will be. Based on the generator type, it will pull one from one of four pools of four items each.

One major challenge is that the item discovery and the item management happen in different scenes, which makes it difficult for the scripts to communicate with each other. To solve this problem, and solve the other question of how to save the game, both scripts write to and read from the save file. So, the GeneratorManager checks if there’s space to add another item to the storage in the save data, and in the inventory scene, the ItemManager checks what items are in the save data and loads them up. 

One other addition I made to the code was a variable that factors into the player’s income that can be affected by items. The main challenge with this is that the UI has a copy of the calculations for UI display purposes, so for optimization and organization, I merged them into one float-returning function that other scripts can use to get a value for the income per second.

Besides those important tasks, we also realized an issue with the gameplay: after the first few minutes, there’s no reason for the player to interact with the scam button. To fix this, my last task was to add three new upgrades to the game that increase the amount of money earned when the player clicks the scam button.

Each upgrade makes the money earned get increased by 1%, 2%, then 3% of the player’s income. This makes it somewhat effective at all stages of the game, and increases how effective it is by the number of upgrades the player has. These upgrades also don’t have any exterior thresholds, which means they’re always there as a goal for the player to get. The only requirement is owning one building, which seems like a good time for upgrades to be introduced to the player.

Since this was a new upgrade type, I had to make a new function to handle it, but it was as simple as giving the PlayerManager a new variable that factors into the “money earned on click” function.


Sunday, November 5, 2023

CAGD 377 Sprint 5

To start off Sprint 5, I made some backend math functions that our lead asked for–eventually we’ll be able to implement them into upgrades, and the item math might need to use them. One finds the player’s lifetime money, and another finds the player’s raw income unmodified by upgrades.

Next, I added a set of 7 new upgrades that increase the item discovery chance of the respective generators. I added a simple flag on the upgrade class that tells it to increase the item discovery chance instead of the multiplier, and then got to calculating the prices and putting in the data.

In doing so, I also split the item discovery stat into four different ones for the four different item types. While this was done for flexibility, ultimately it never gets fully utilized since each generator only finds one item type. So I think it could be better optimized by putting them back to a single stat, and just having the item discovery go off of which generator found it.

That was all for Sprint 5–quite honestly, I know I could have done more this sprint, I think that as a group we were just at a point in the middle of the semester where we both were missing a little direction, and waiting on all our pieces to be complete so they can be put together.

So, here’s our direction! Going forward into Sprint 6, here’s the three biggest priorities: the item system, getting the art assets in the game, and making sure the UI looks good on mobile.

The item system is our plus one feature, so it’s vital that it makes it into the game on release. Getting it completed mostly requires hooking it up to the existing systems. For Sprint 6, one of my jobs will be to make sure the item discovery system’s activation is hooked up to the item spawner. Additionally, I’ll be looking at the save data to make sure the items can be saved.

Our artists have made some wonderful models for the game, but we haven’t tested putting them in unity yet. This is also vital to the game’s success and to make sure that our artists’ work gets appreciated. This sprint, we’ve gotta get the models in unity so we know that everything’s configured correctly on release.

Lastly, the UI works on PC while we’re developing it, but it still looks off on mobile. This will be another one of my jobs, making sure it scales properly on a mobile device and that there’s room for the models to be on the main screen.



Here’s an oversimplified mockup I made during our team’s discussion, showing how everything should be organized so the art can fit in.


Additionally, I have a few stretch goals for myself if I can complete everything else with time to spare. I’d also like to implement a few more upgrades for the SCAM button, increasing the money generated when the player clicks it. Our lead has this idea in the backlog, but it’ll only get added if we have time, so I’d like to make sure I have time because it’d be a piece of cake for me to implement, and increase the number of things the player can do.

Looking further ahead with the plan, I’d also like to see if we have time to implement the prestige system in Sprint 7. That’s something that would probably only get added further down the line, but coding-wise I don’t think it’s too complicated, and it would make a fun addition to the game.


Monday, October 23, 2023

CAGD 377 Sprint 4

One of the main challenges of Sprint 4 for me was that I didn’t have an overall theme this time, and instead was just doing some miscellaneous tasks. With the major systems complete and waiting on the lead for items to be ready for me to work on, there wasn’t a major milestone this time. 

First, I optimized the upgrade system. Following the ideas I had in the last sprint, I got the system optimized so it works smoother. 

Since items were our next big-ticket item I got the framework set up for item discovery. You can see the code here, it was pretty straightforward, and just triggers a debug message where adding the item would go. This was as far as I could get for now, but it was good to know it was working.

Next, I thought it would be interesting to see how the game plays–and discovered there was a slight balancing issue. Since our plan was to go for additive multipliers, but we implemented multiplicative multipliers since those worked better, the income multipliers the player could get were higher than they should be, and made upgrades have too overpowering of an impact on the game. I brought this up to our lead, and got a new task to rebalance the multipliers so they would be equivalent to what the additive system would’ve been. 

For example, adding a x2 multiplier, then a x6 multiplier would result in a x8 multiplier overall. I would take something like this and convert it to multiplying a x2 multiplier by a x4 multiplier to get the same x8 overall. Making these small adjustments to every set of upgrades left the game in a much more balanced state. This was a simple task, but one that’s worth some explanation.

Lastly I tackled the advanced upgrades. This included an upgrade for Spambots that increase their multiplier for every other building owned, and a set of upgrades for every other generator that increase their income based on the number of ChopDocs owned. Since the upgrade system wasn’t built to do this, it required a little finesse–just a checker for the ids of these unique upgrades to redirect to their unique code. Not super elegant, but functional for now, though worth optimizing if the game ever gets bigger; though this will probably be the extent of the scope. The only other upgrades after this will be related to item discovery, and then they’ll be done.

Anyways, as shown in this gif, I got them working. It took me about a day’s work to iron out the kinks, but otherwise it didn’t give me too much trouble. I will say that they do serve an important role to bridge the gap between the 50 generator upgrade and the 100 generator upgrade. 

That might sound like a bit of work, and it was, but I definitely had more room to improve during this sprint. I could’ve done some more work on the game, I think we were just in an awkward place where there wasn’t more programming needed at the moment. Which is fine–it shows that we’re well on track to completing the project.

In conclusion, I’m excited to tackle items in the upcoming sprint. Since they’re the main +1 feature, I’ve been eager to get started working on them, and now that everything in the base game is functional, we’re finally ready. I think the game will really start looking complete once we get the art imported onto the menu.


Sunday, October 8, 2023

CAGD 377 Sprint 3

During the third sprint I had less time to work than I would’ve liked, so I focused on getting the most important tasks done: finishing up the upgrade system. I decided that this would be the best thing to focus on first since it’ll be the most relevant to players in the next playtest. In an idle game, upgrades keep the game from slowing to a grinding halt and give players more goals to work towards. They’re a bit like footholds on a rock wall, giving something for the players to reach to and giving them a boost to reach the next goal.


First off was optimization. Like I mentioned in the last blog post, using “upgradeSets” instead of prerequisites was a misstep, so I corrected it, rewriting the code to remove upgrade sets and having my future code use prerequisites instead. It wasn’t too difficult a switch because the verifier hadn’t been implemented yet.


Sprint 2 for me was all about the back-end for upgrades, so all that was left for me to add was the front-end for the player. Basically, getting the GUI ready. I did this with two main scripts. First, I made a generic upgradeButton prefab that instantiates a button with a certain upgrade, displays the appropriate upgrade name and price on the button, and tries to purchase the upgrade when clicked. Next, I made a buttonManager script that checks if the requirements for an upgrade are met whenever the player buys a generator or upgrade (since those are the only things that could cause it to update) and instantiates a button prefab.


Here it is working!


The only trick was making sure upgrades display on the correct spot on the screen. To do this, when the buttons are instantiated they get added to a list, and all elements in the list get lined up on the screen based on their spot in the list. When a button is clicked and the purchase is successful, it gets deleted and removed from the list, which lets all upgrades ahead of it slide back into place nicely.


The only thing left before I could get it working was to input the rest of the data from our spreadsheet into the upgrade library in the game. It was a little tedious, but didn’t take more than half an hour and it got all 21 of our upgrades in the game. The one issue I ran into is that the most expensive upgrade is $9 billion dollars, but for some reason the unity interface wouldn’t let me input more than 8.999999999, which is weird since that isn’t any kind of integer limit. For now, players will probably never be able to tell the difference, and balance wise, 9 billion is basically no different than 8.999999999 billion, but we may want to look into this in the future.



But with that, all 21 base upgrades are in the game! We may want to look into some more later, which would require an expansion of the system, but for now, I’m very happy with it and proud of my work. With this, two of our core features, generators and upgrades, are fully implemented. Now, all that’s left before our game is ready is items.


Upgrades weren’t too much trouble for me since I had a plan, but I don’t have one yet for items and I’ll be working with other people’s code, so it may prove more challenging. It’ll also require more steps and interconnectedness than the previous tasks. However, I’m still confident that we’ll be able to do it.


Saturday, September 23, 2023

CAGD 377 Sprint 2

The first challenge this sprint was one of communication: I needed to make a guide for my teammates on how to implement the rest of the generators using the tools I created. Since the hard part was mainly connecting objects together in the Unity editor, I figured communication would be the most straightforward with a video tutorial, lasting only 9 minutes. With this, my teammates could finish the rest of the generators so I could focus on other features.


And for this sprint, that was the upgrades. I programmed the framework for basically the entire upgrade system. Previously my main two ideas were an array of id values to store the data of which upgrades were owned, and a set of upgrade ScriptableObjects that contain all the relevant information for the upgrade objects.

Ultimately I realized that the best solution was to marry these ideas together: the saveData stores an array of integers that are 1 or 0 to mark if an upgrade is owned or unowned, and each upgrade is a scriptable object with one of its datum being an id number that tells the upgradeManager which int in the array corresponds to it. So basically, the upgradeManager reads the saveData, if there’s a 1 at a certain array index, it checks the upgrades for the one with that id number, and turns it on.

One other challenge to note was whether to make the upgrades additive or multiplicative: ie, should a 2x multiplier and then 4x result in 6x, or 8x? With my current system, multiplicative was far easier, so that’s what we decided to go with (also because it gives more power to the player). 


Definitely my biggest misstep with this system was organizing upgrades into “upgrade sets”, since some upgrades come in a linear progression: ie, Tier 1, Tier 2, Tier 3 of a certain upgrade. Doing this ensures that players can’t get the tier 2 upgrade before tier 1, but adds a lot of complexity and noise to the code, since now we’re sorting through an array of arrays.

A better way to have achieved the same goal–which I’ll probably switch to as soon as I can–is for each upgrade to have a “prerequisite id” integer that points to the upgrade that is required as a prerequisite, if one exists.



Making this system was the majority of my work for the sprint, but it’s a super important system, and with it working, that’s two of our big three features done (generators, upgrades, and items). My next challenge is getting the UI for upgrades working, since I’ll need a queue of upgrades available for purchase on the left side of the screen.

I haven’t worked with UI elements as much so this will be more of a challenge for me, but I don’t think it should be too hard, since we’d just need a list of upgrades available for purchase, and once one has its requirements met, it should be added to the list and go to the front of the queue. 

One other change I discussed with the lead was whether we’re sticking with 2D UI or if we want to make 3D buttons. If we eventually go for 3D, that may substantially change how this system would work, so maybe the next step is testing out clickable 3D buttons.

As I see it, the biggest challenge is going to be a concise and readable way for players to see upgrade descriptions–adding a string for them to the upgrade data is easy, but finding a spot for it to display in the ui could be challenging. We can cross that bridge when we get to it though.


Overall working with data engineering (is that an appropriate term? For finding the most efficient way to store and retrieve data) has been a satisfying experience for me.


Sunday, September 10, 2023

CAGD 377 Sprint 1

 I was out of town for the weekend, and with our delayed start for Sprint 1, I really had to hit the ground running. Despite this, I still pulled through and completed all my tasks for the sprint.

As the main programmer, most of what I did during the sprint was setting up the foundations for how the code will look going forwards. I discussed with our lead and decided that the best way forward would be to split up the main sections of the game into three main scripts: the PlayerManager, the ShopManger, and the GeneratorManager. 

The PlayerManager stores all of the player’s data in one script, so it’s easy to grab it and save it to a scriptable object. The ShopManager deals with purchasing new generators—checking the player has enough money, updating costs, and completing purchases. The GeneratorManager does all the calculations for money generated per second. I figured things could get laggy if this wasn’t standardized, so I made sure to keep it all in one place in a few functions to keep it under control.


To demonstrate their functionality, I got everything set up with the first generator in the game—the Spambots—and hooked it up to the appropriate scripts. As of the first sprint, the Spambots in their base form are already fully functional, and all it takes for the rest of the buildings to be in the game is a few copy+pastes. The basic data for the generators is stored in scriptable objects that get read by the shop and generator managers, so once that data is put in place and the UI is set up, we can already have all the generators in the game.


In my last game development project, I was a lead, so I had to think about how we were going to organize the production of all of the game’s features. This time I’m a programmer, so I’m given the features to create, and instead have to figure out the best way to organize the technical functionality of those features. 

One challenge for me is that most of my programming assignments up to this point were solo, so I could just code and organize it in a way that made sense to me. Of course, having good organization would be helpful and commenting my code to explain it to the graders was relevant, but I was still mostly held to the standard of “does it work?” This time though, I have to worry about my code and organization structure being understandable to the other members of my team. This is especially difficult since we’re making an idle game that’s mostly just a bunch of math—since my last project was a 3D platformer, it was easier to communicate what we were going for with the design. Now we’ve got spreadsheets.


Coming up next is going to be working on upgrades and items, and while I had a good idea of how to easily implement the generators, this might be a bit more of a challenge. I may have to do some research about good ways to implement upgrade and item systems, however I already have some ideas.

For the amount of generators owned, I made an array that abstracts all that data so it can be easily stored in a save file, and then I have a function in the player manager that knows how to read it. I figure that for upgrades I can do something similar, once I know how many should be in the game I can just make an array with a 1 or a 0 in each spot to mark if that upgrade is owned, and then number each upgrade with which spot it is in the list. While it’s an abstract system, it’s not very data intensive, and it can be explained to the other coders with comments.

On the other hand, the reading function for this may be more complicated since it’ll have to check every single number in the array. However, that may just be a product of there being a lot of upgrades—the only other way to do that would probably be a list of what upgrades are owned, and that would require a new scriptable object. However, if a made a scriptableObject “Upgrade” with a name, reference to what it should add to, and a multiplier, that could be more efficient in a list and easier for programmers to read and edit.


Saturday, May 13, 2023

CAGD 370 Postmortem

 Now that the fifth sprint is done and we have a finished build of our game, Figure Skating Flying Squirrel, it’s time to do a postmortem of the whole development process. First, I’ll talk about some challenges we faced during the development process, and then I’ll talk about how the final project turned out (it went great).

One challenge we faced during the start of development was breaking up tasks into sufficiently small pieces. For example, developing a level is a long process. Eventually I decided that the best way to do it would be to make separate cards for two drafts of the annotated map, a level blockout, a first draft, and final draft of each level. Throughout the development process we had some similar issues, but I definitely think this is just something that gets ironed out with experience, since we figured out what the expected steps are for certain tasks.

Another challenge I ran into during the fourth sprint was getting stuck on a card I couldn’t get to work. I looked through the unity scripting API and online for solutions, and nothing seemed to work. Eventually I figured out it was a conflict with someone else’s script—I assumed he would’ve told me if there was a conflict, and he assumed that I would’ve checked for any conflicts. In the end it was a funny misunderstanding, but I think going forward I learned that I should ask for help when I get stuck, and check with my team members if there could be a script conflict.

In the final sprint we realized we probably wouldn’t have time to include a final level, and had to decide to cut it. Throughout the development process, as the lead, I would have to make the call on whether or not to cut certain features. While this is just something that has to happen in every project, since at some point it has to be finished, I didn’t want to dismiss other people’s ideas. I solved this problem by trying to find ways to incorporate other people’s ideas by modifying them—for example, somebody suggested being able to upgrade the player with new abilities. I didn’t think this would work great for the design of the game, so I suggested keeping the idea of new abilities, but putting them in temporary power-ups instead of permanent upgrades. 

An early success of the project was getting the movement and physics working early. I really have to thank my programmer for this; but getting that working early on meant we could work on the levels and game interactions with much more confidence.

A later success was the design of our level objects. I wanted to add some intractable objects to the levels that made things more interesting. The design I’m most proud of are the bumpers—I realized that the biggest challenge to the player is the large turn radius and slow turn speed. I figured that bumpers that instantly cause the player to bounce one-hundred-eighty degrees would therefore be a meaningful addition that players want to go for. 

Another game object that had some thoughtful design was the branch wall. The player can smash through branch walls if they’re going fast enough. I wanted the players to be able to pick up on this, so first I made a model for them that communicates that they can be broken. I made them look really brittle, but I also gave them large gaps that the player can see through. If the player can see that there’s an area behind the wall, they’re more likely to realize that they have to break the wall to get in. For the implementation, I put a section in the tutorial level where the player starts going really fast, and put a branch wall at the end of it. I correctly reasoned that players would likely lose control and hit the wall, then realizing that they can smash right through.

One of the biggest successes of the project was the switch to ProBuilder for our level building. For our game especially, we needed a lot of slopes, ramps, and curves, which weren’t feasible with the unity primitives. Using the ProBuilder plugin, we were able to make levels that both played and looked way better.

What would I do differently on my next project? While we knew we wanted powerups and level objects, I think getting design documents for those sooner would’ve been beneficial. Additionally, I think more of a design document for how levels should be designed would be good—while we got things worked out, I think it was hard for me to communicate my vision for the level design until I made the tutorial level; making a design document with some general guidelines would’ve made that easier. I also would’ve liked to get the third level in if we had more time.

Overall, I’m really happy with how the project turned out. I think our strong core mechanics greatly contributed to a game that’s cohesively fun, and the powerups and level objects provide nice spins on the gameplay. The high score time and acorns give players some great incentives to go for, and playing it, it really feels fun to try to speed through the levels as fast as possible. The moveset combined with the varied levels means there’s a lot of tricks the player can pull off, and it makes the gameplay feel fun, rewarding, and flexible. 


Featured Post

Aftershock Simulator Sprint 3

This is th e tutorial video I made for my team demonstrating how to use the objective system I designed this sprint. I’m really happy with h...