The last day of my externship has come to a close. However, my work is not over. I was given the opportunity to jump start a project I plan to work on for months to come. Here's the progress I have made this month:
Overall, a lot of progress has been made in the last 19 days. I am currently still in the process of balancing and fleshing out a level in preparation for exhibition. Looking forward past high school I know I want to major in computer science. The feeling of solving a programming puzzle is incredibly satisfying, and I would love to be paid to do it. I appreciate everything externship has allowed me to do. My special thanks goes to Pat and Sheri Bonner for supporting me during this time, and Mitchell Lising for keeping me company! Qualcomm represents my own future working in a tech company
0 Comments
I have been working hard over the last few days (and plan on working more tomorrow) polishing up and creating the upgrades for the towers, as well as fixing small issues I have found sporadically throughout the game. In addition, the game now has a victory screen that appears when the user destroys the very last enemy on the very last wave. Over the course of Externship, I measured my personal success of the work I accomplished based primarily on the amount of focus and time I put into the game, regardless of how much it appears that I accomplished. This is because every aspect of game development is incredibly time consuming. I have been working on the tower defense game every day, almost non stop, for the last four weeks. When I spend several hours, or even several days polishing and accommodating a feature that I previously added, the end result appears almost the same. However, that almost is a large part of software development. Abolishing the bugs, the problems, and the "it kinda works" feel to a feature is what makes it feel complete.
Developing the game allowed me to make a meaningful contribution to myself. I have never focused so intently on one project for so long before. My time during externship proved that it isn't only possible for me to do so, It's also enjoyable. The project was good for my education, as it solidifies my choice of majoring in computer science at Cal Poly San Luis Obispo. On top of that, my work here is significant past externship because it is a project I know I want to continue developing, and eventually sell. I learned that having a designated time to show up and leave helps keep me motivated to work through that time. Today I continued polishing the current features of the game. I fixed some more bugs created by the range indicators. I then created both a pause menu and a game over menu. After that, I created an indicator on the top right that displays what wave the player is currently on. These menus allow the players to properly navigate around scenes in the game, and make exhibition of the game possible. Tomorrow I am going to develop the tower upgrades for the rest of the towers, and continue work on game balance and playability. About my coworkersOur mentor wasn't here today. So instead here is information about our fellow lab ops workers. Daniel graduated from Devry University in Program Management and got his job at Qualcomm through the navy. Sean is a grizzled veteran of the US Army Infantry. After he got tired of being awesome, he settled down, got married, and joined Qualcomm's lab ops team.
As the five days of externship looms, I've transitioned to filling in all the lose ends. The potholes I need to fill before the game is in a basic, yet playable state that I can properly present during my presentation of learning. This means fixing all of the mechanics I've broken with the addition of new ones. It means utilizing the wave manager I created to create comprehensive levels using the maps I made. It means adding basic menus to navigate through the game: A pause menu that allows the user to return to the main menu, for example, is missing. Most importantly, the most difficult task is assigning the stats of the towers and enemies to make the game balanced. This means a lot of experimenting, and a lot of play testing.
Today I made placing towers a much better experience. The clunky drag and drop system has been replaced by simply clicking on the tower button then clicking where the user wants the tower to go, this ended up being very difficult, and it took the entire morning. Towers now have range indicators, so the user can see how far they shoot. The tower placement indicator now also turns red when it is in a position where it can not be placed. The end result is that placing towers is much more fluid. There is still some work to be done. The prices, for example, are not shown. There is no way of knowing if the user can afford to place or upgrade a tower or not. I also started into balancing the game. Currently, I am up to five waves. To that point, the prices, health, damage, speed, and rewards feel solid. On Tuesday I'm going to continue balancing, and create upgrade chains for the other towers. At this stage they will probably only be stat modifiers that don't require significant coding. Took a day off from working on my game to eat tacos and canoe at Crown Point, Mission Bay, San Diego! Today was a team builder, so everyone took off work to come here instead.
Main Menu:
I decided I was taking too much time from the main game to create the main menu, so I've decided to put it on hold for now. Notice the smooth transition to the level selection screen I was working on earlier. Going to the level selection screen shows only one map: the one I made during internship. However, the box has custom scaling. It can support as many levels as I can add, also allowing you to scroll up and down within the menu. Creating intuitive UI like this came very much in handy for other elements of the game. The options button doesn't currently do anything. It's a feature I will add on another date.
Concept Brainstorming
I started writing out ideas for tower upgrades and ways to make the game more unique.
Overhauled Tower Selection UI:
I took the knowledge I learned making the scrolling level selection screen and applied it to the tower selection panel within the main game. Selecting and placing a tower is now a nicer experience, with (placeholder) pictures and bold text!
Dynamic Upgrading System:
Accomplishing this system is something I am very proud of. I completely rewrote the upgrade system for towers, and created an upgrade path for the missile towers. Towers were previously hard coded to only allow one upgrade. This was boring, and didn't allow me to create branching upgrade paths to add variety. I tried hard-coding support for a second upgrade, however, the bloat it was causing to my code coupled with the total lack of flexibility made me attempt one more time.
Towers can now have as many upgrades as I want. Whenever the player clicks on a tower, it generates a new button for every upgrade the tower has. The process of creating a dynamic, scroll-able list where each button does something different (being able to differentiate between different upgrades) allowed me to put a large variety of skills and techniques together. Ranging from arrays of serialized classes to Unity's dynamic UI resizer. While it doesn't look like much for the end user (it just works!), creating it and the ease of use it allows me is very gratifying.
Throughout the course of the Externship, I haven't had an in-person resource to help me through the the problems i've faced. However, that issue has not prevented me from eliminating roadblocks and moving forward. My externship is not only teaching me computer programming and game design. Externship is also teaching me how to research and find the information I need to solve specific problems, as well as significant utilisation of trial and error creation. I learned that the number one key is patience. Frustration can cause me to get sloppy, but with enough time and effort there has yet to be a problem I couldn't eventually push through.
For Example: Today I continued work on the main menu and level selection screen (video preview tomorrow). I shifted gears from a simple text overlay to having the main menu be an active scene. In order to traverse the main menu, I wanted the camera to move smoothly between preset positions. This is achieved through a repeatedly run function that interpolates between two numbers and updates that value. That value is then substituted for the camera's position and rotation, allowing smooth transitions. The problem was the method I implemented (found widespread on the internet) was not truly linear. The transition speed would change, but most importantly, the camera would never fully reach the end position. It would end up in a slightly different position every time. It turns out, despite taking precautions not to, the method was dependent on frame rate. I searched the web, and came across THIS blog post. The post contained an a detailed explanation of the problem and the solution. However, the example script didn't fit directly into my code, and only worked for translations. I learned from its implementation, however, and created my own that also had support for rotation and going to predefined points (and not just forward). I can now transition between two points in the main menu screen smoothly and with perfect accuracy! Tomorrow I will finish up the main menu screen. I will also post a video showcasing it. Laser turrets, as they are so aptly named, shoot lasers! Unlike bullets, they apply constant damage over time. They also slow the target upon hit. I also took the time to learn Unity's built in particle effect system, to make some neat impact effects and smoke trails. No video today, as recording isn't supported on my laptop. I took a good portion of the weekend working on it, and despite using a model I didn't make, the results are quite clean. The laser turrets work by rendering a line between the tip of the barrel and the center of the target, updating every frame to maintain accuracy. The actual damage and slowing of the enemy is done directly through the tower. I made a modified override of the default "Shoot(Enemy enemy)" function of the tower. Instead of instantiating a bullet, it deals damage directly and modifies the speed. I also began work on a main menu screen. It is very basic currently, but I would like the scene to be animated. I also want to create a level selection screen, and create an options menu for the graphics and controls. Not to mention the fact that I need to think of a name for the game! Tomorrow, I will continue working on the main menu. If I have extra time, I plan on making a pause menu while in game, that can be opened by pressing escape.
Today, I implemented both the code and the user interface to change the enemies that towers target. Originally, all towers would simply shoot at the enemy closest to them. Now, the user can choose to make a tower target the strongest enemy in range (the enemy with the highest health), or target the enemy furthest along the path. This is an addition to the original method in place before.
Notice how, after I change the targeting method on each tower, the tower on the right hand side focuses on the grey tank (the one with the highest health), while the tower on the left aims for the tank furthest along the path. Further into the video, the tower targeting enemies with the highest health will switch targets on the fly as tanks get damaged. This is especially useful if the user who possesses a high damage, slow firing tower wants to make use of each shot most effectively. The target finding code works by accomplishing these three things every frame (between 60 and 100+ times a second): First, before the tower compares the values of the enemies, the tower defines a new Enemy called the "targetEnemy." This enemy doesn't exist until I assign the target later in the program. Thus, I start by setting it to "null." Then, the tower sets a "base" comparison value. This is what the tower references later when it begins to compare enemies. They are set as low as possible.
I then run a "foreach" loop. A foreach loop will execute a block of code for every single item contained in a list or array. In my case, I iterate through every enemy in the global "Enemies" list that changes whenever an enemy is created or destroyed.
The first thing I do within the foreach loop is get information from the specific enemy that the loop is running on. For my three different targeting methods, I find three snippets of information: The distance the enemy is from the tower, the "path node" the enemy is moving to (the higher this is, the further the enemy is), and the health of the enemy.
Then comes the tricky part: I start comparing values. The base values I declared before are compared to the values of the first enemy in the list. Since the first enemy is guaranteed to have values higher than the base values I set before (even a mosquito should have higher than -1 health in a video game!), I change the base values to that of the enemy, and the enemy becomes the target. But wait, how could that enemy be the target? What if it's the weakest enemy? It's important to remember that before the frame is over, this comparison happens with every single enemy.
For Example: Lets say four different enemies enter the range of a tower at the same time, and the tower is set to target the strongest enemy. Lets say these are the health values for each enemy:
Enemy 1: 20 health Enemy 2: 15 health Enemy 3: 50 health Enemy 4: 45 health The tower first evaluates Enemy 1. Even though Enemy 1 only has 20 health compared to Enemy 3's 50, the tower does not know that yet. It only knows that Enemy 1's 20 health is larger then the "base value" of -1 set previously. This tower is now the target, and the base value is changed to that of Enemy 1. But wait, the frame isn't over yet! Then, the tower looks at Enemy 2. Enemy 2 has less health then the new base value defined by Enemy 1. The values aren't updated, and Enemy 1 remains the target. After that, the tower looks at Enemy 3. Enemy 3 has more health than Enemy 1. Thus, the tower re updates the target and base values to that of Enemy 3. Finally, the tower looks at Enemy 4. Since Enemy 4 has less health then Enemy 3, Enemy 3 remains the target. Since Enemy 4 is the last enemy in the list, the tower is done finding targets. The tower shoots at Enemy 3.
The frame is over. Next frame, the process runs again. The base values are reset, and the enemyTarget becomes null once more. This assures that now matter what, the tower is always shooting at the most ideal target according to the user's set targeting method!
Overall, today was a very productive day. On top of what I listed above, I also fixed the remaining problems with the enemy health bars (they would show up when the camera was looking directly in the opposite direction), and refactoring the current active group of enemies from a (static, unchangeable) Array to a (dynamic) List, meaning a new Array doesn't need to be generated every time an enemy is created or destroyed, saving performance. Next Monday, my goal is to add laser turrets!
Here are some pictures of my workspace: Qualcomm Building Q
Today, I added health bars that hover above enemies:
The method was less straightforward then I originally thought. While it appears that the health bar hovers above the enemy in the world space, it is actually being drawn flat on the UI (user interface), along with other elements such as the tower selection and money displays. It then draws itself offset from the enemy itself by a certain amount, and updates its location every frame. This comes with an two added benefits: health bars will remain the same size now matter how zoomed in or out the player is, and the method is much more optimized.
I also refactored the way enemy health works, adding support for an armor statistic that reduces incoming damage from towers by a modifiable percentage, and allowing for the proper scaling of enemy health bars no matter how much health they start with.
I also created a very simple UI popup that displays the statistics of an enemy when you click on them. While it doesn't look very good yet, the framework and code is in place to allow me to expand it when necessary.
Today was another progressive step towards baseline! Tomorrow I plan on revisiting some of my old code again and changing the way towers find enemies to be more optimized. I would also like the user to be able to choose who the tower targets, with settings ranging from first, closest, strongest, and last.
|
|