TT9: Saved games from GDEX

When I demoed the game at GDex, at the end of every play session, I saved the current game to disk. I skipped out on saving the data for the people in the game, so those are all missing, so all that remains of the towers is the terrain and rooms. There were a few other bugs that resulted from that.

Every game started with a square of empty floor, an entrance, construction room, and an elevator in place, and a vast majority of the players built within that square. So many of the games came out looking nearly identical to each other. However, there was still enough variety that it was nice to see how people played the game, and what they ended up doing with it.

TT8: Thoughts on Difficulty

Difficulty in tycoon/management games is hard to do.

A common method of increasing difficulty in most games is to add more things to do, or more things to keep track of, or simply require the player to learn certain skills or tricks, and use those skills to pull off the next set of tasks. Puzzle games, platformers, or action games can increase the difficulty by adding new mechanics, combining previously used mechanics, or just tossing in more of everything into the mix.

With tycoon games, a common method is to just make everything cost more, while giving the player less money. And this works, but there comes a point in most tycoon games where the player has a constant source of income and then it’s just a matter of waiting around a bit for the next source of income. And income usually increases exponentially. In Transport Tycoon and similar games, adding more train routes costs money, but gives you more money faster. In Sim Tower, adding more rooms means you get more money when rents are due, though it usually costs a bit to add those rooms.

Without something in the game to push against the player when they’re successful, a game will quickly turn boring, or, at least, it’ll turn from struggling with needing just a few more dollars to get the next neat thing to struggling with other problems. Transport Tycoon turns from a game of struggling with being able to afford each route and new train, to being able to spend millions sculpting the landscape, while trying to perfect a large, efficient transportation system. Cities: Skylines turns from struggling with getting a basic city set up, to dealing with traffic problems.

Other games give you more to worry about when it comes to budgets. Optimal play in most of the Sim City games is to build out with low income, lower class zones and then once you establish a base of income, work on upgrading the city to high class, high density, highly educated sims via schools and hospitals and other things.

Still others apply pressure simply by the act of having more of everything. Prison Architect is a perfect example, as more prisoners means overcrowding and greater chances of escapes, riots, or other bad things happening. External forces also matter, in the case of city/base building games like Gnomeria or Rimworld, having a “richer” base leads to more, and more powerful raids on the base.

While thinking about this problem for Isotower, I’ve come up with a few different solutions. One is simply the logistics of moving people through the tower, more people = more need for elevators, escalators, stairs, etc. Adding in stuff like staff only elevators, or being able to limit which social class can use what transportation adds another layer to things. This will apply some pressure, but not really enough.

The other method I’m planning on is simply a matter of a bigger tower will cost more to maintain. Most of this cost will be abstracted, effectively the cost of property taxes, utilities, maintenance. These are all things that could be added to the game individually, but most likely, they’d just be busy work for the player, and not really all that interesting from a gameplay standpoint. The goal with this is to keep the player from amassing a huge fortune, at least at first.

Finally, random events such as fires, floods, or threats from terrorists will be more likely to happen in a larger, famous tower. Especially the last one. There are a few other things I have planned to keep the game interesting past the initial struggles with establishing a basic tower. Those are subjects for later, though.

TT7: Elevator waiting! Requests! Ratings!

Isotower will be at the Ohio Game Developer Expo.

So I’ve been preparing for that, along with getting closer to release. The current plan is to release Isotower in the Spring of 2017, so I’m working on getting the last couple of gameplay systems polished, improved, or balanced, as well as finishing up a variety of other things.  One of those things is an improvement to the requirements system. Previously, rooms had various requirements, types of rooms that needed to be built, otherwise the original room wouldn’t be rented out. I’ve expanded that system so that rooms can now also have “requests”, where if you haven’t built a room type yet, the original room can be rented out, but it’ll have a lower initial rating. The screenshot below shows an example of that.

requirements_and_requests

The presentation of this information is still very crude, essentially just a first step towards presenting this info to the user.

The other aspect I’ve been working on has been improving the visuals for the elevator. This includes getting the elevators to display some of the people inside them when they’re being used, as well as display a portion of the people that are waiting for an elevator car to arrive. There’s currently a bug with the elevator that causes it to not let anyone in at a certain point. For now, I left that in to better show off a busy, crowded wait time for the elevator. It will definitely be fixed quite soon.

TT6: Simplify stat tracking with a std::map

This post is a technical post on how I put together stat tracking for Isotower, for the goals system.

A few days ago, I decided to add goals, or missions, or tasks, or quests to Isotower. I don’t have a name for them in the game, but in the code, they’re goals. Essentially, each goal would track a few stats, like how many people of a certain social class were in the tower, or how many rooms of a certain type were built, or how much money was being made per day, or per week. I was already tracking a lot of these stats, but they were often in their own variables stored in factories, or in the finance code. Writing code to look up this information in an easy way would get complicated if each stat had to have a different function pointer, or if there had to be a giant switch/case statement to know which stat pointed to which factory function. Pointers could have worked, and been fast, but there still would have been a need for a switch/case statement to know what to point to for each part of the goal.

Instead, I created a very simple factory to store a collection of stats, and used a std::map<std::string, double> to store everything. Double because finances and averages would be tracked, as well. This lets me store each stat as a std::string for the goals, and then simply look up the value in the StatTracker data to see if the goal has been reached. The code for the goals is easy to use and understand, I can track stats simply by simply calling StatTracker::INSTANCE().addValue(“new stat to track”); and it all ends up working smoothly. The final code came out to 4 public functions, and a mostly used for debug toString() function. The code is pasted here, because why not.

StatTracker.hpp
#ifndef _STAT_TRACKER_HPP
#define _STAT_TRACKER_HPP

#include <map>
#include <string>

class StatTracker {
private:
 std::map<std::string, double> stats;

 StatTracker();
 StatTracker(StatTracker const&);
 void operator=(StatTracker const&);
public:
 static StatTracker & INSTANCE();

 void addValue(std::string);
 void setValue(std::string, double);
 void changeValue(std::string, double);
 double getValue(std::string);

 std::string toString();
};

#endif
StatTracker.cpp
#include "source/Managers/StatTracker.hpp"

#include <sstream>

void StatTracker::addValue(std::string index)
{
 this->stats.insert(std::pair<std::string, double>(index, 0));
}

void StatTracker::setValue(std::string index, double value)
{
 this->stats[index] = value;
}

void StatTracker::changeValue(std::string index, double value)
{
 this->stats[index] += value;
}

double StatTracker::getValue(std::string index)
{
 return this->stats[index];
}

std::string StatTracker::toString()
{
 std::stringstream temp;

 for (const auto &pair : this->stats)
 {
 temp<<pair.first<<": "<<pair.second<<".\n";
 }

 return temp.str();
}

StatTracker::StatTracker() { }

StatTracker & StatTracker::INSTANCE()
{
 static StatTracker instance;

 return instance;
}

69 lines in total (25+44). Much easier to use and understand.

Sidenote: I use this singleton pattern in almost all the areas of my code. It might not be the “right” way to program things, but it’s easy to use, and at the moment, it does what I need.

TT5: Adding an interface

In the past few weeks, I’ve been working to add more depth to the game, and finished up some of the major systems. The biggest set of changes has been with the rooms, switching up how they worked internally, and solving a few problems along the way.

At the moment, the first thing needed is a construction office. It’ll hire construction workers to build the rest of your rooms. Only one construction worker can be dispatched to a newly built room at a time from each individual construction office, but building more offices can speed up the process of building a new room. Once rooms are built, they’ll have various requirements before people will rent them, or show up to shop at stores or eat at restaurants. Hotel rooms can be rented out, but will get dirty once everyone has left for the day, so they’ll need to be cleaned regularly. Security personal will occasionally need to be dispatched to rooms in case of threats. Rooms have a variety of factors that go into keeping high rating, from surrounding noise and beauty levels to how happy their tenants are, to how much money they’re making per day.

 

The interface for querying a room
The interface for querying a room.

There are still plenty of systems and other things to add and improve upon within the game. However, most of the major functions of the rooms are in place, so today, I’ve begun working out the interface layout that shows up when you query a room (seen above). This is not final (it needs a fair bit of work, obviously), but it contains all of the information about the room that the player will need. the red to green rectangle is the rating indicator, which will provide more detailed information when the player hovers over it. The three buttons will turn into tabs (defaulting to showing the info panel), and the info panel contains details from the income of the day and current rent price to how old the room is and “thoughts” which are more like messages from the room itself (and where you can find out if you’re missing a requirement or similar things).

 

The interface in the wild of the full game window.
The interface in the wild of the full game window.

TT4: From Engine to Game

Now that elevators are working and on the map, all of the major portions of the engine are done. Basic construction, pathfinding, visitor and resident AI and simulation. You can see a short video of the elevators in action below.

Now, the goal is to take the engine and transform it into a game. There’s a lot left to do, from graphics, to user interface, to adding additional systems and features. Plus all sorts of minor, but important areas that need to be polished. And playtesting for balance and bug and ease of use.

The ultimate goal of the game is to let players build a wide variety of buildings, from creating a series of brownstone/brick rowhouses, to gleaming skyscrapers. From creating a tiny shopping mall, to recreating the massive monstrosity of the Kowloon Walled City, and all sorts of buildings in between.

 

TT3: Interfaces

There’s a few famous books out there about designing things for usability. The Design of Everyday Things is all about designing physical objects in a way that removes ambiguity and essentially, makes it impossible to use the object the wrong way. Don’t Make Me Think is all about web design and usability, and is handy for other aspects of interface design for computer programs.

Video game interfaces, meanwhile, have some additional complications. A lot of games strive to be immersive, and have minimal interfaces, often incorporating the elements you interact with directly into the world. Often, the interface can be used to enhance the gameplay when this is done well. Other times, the game is almost entirely interface, and the graphics are mostly to prevent the whole thing from being a giant mess of numbers.

Most tycoon style games go for something in between, with the game world being front and center, but with the ability to pull up all sorts of charts, graphs, and numbers. But the important numbers will be visible at all times, such as Sim City’s RCI indicator always being on screen, or Prison Architect’s temperature meter.

I have a philosophy of “don’t make me click”. Actions in the game should take the least number of clicks, in order of their importance. If something is done a lot, it should only take one click to do. If it’s a bit less common, then it can take a few clicks to do. I’m still working out exactly what the important numbers are for Isotower. Money, population, and overall rating are the current important bits, with time and weather also taking a place of importance. After that are tools to let the player design and build their tower, and finally the various details for individual rooms and visitors and residents of the tower.

Unfortunately, until the majority of the game is done, I don’t have a solid idea of what is going to be important and what isn’t. So the interface is going to be very rough until more pieces of the game are in place.

TT2: Decisions

I’ve been thinking a lot around what makes a good simulation/tycoon game compared to mediocre or bad games. One of the elements that’s important is being able to make meaningful decisions throughout the game. Give the player a goal, and then give them multiple ways to reach that goal. In most tycoon games, the goal is to make a lot of money. But sometimes it can be to successfully run an island nation, or to reach a certain technology level and be able to leave the planet, or to keep prisoners from rioting (while also making money).

For Isotower, one of the everyday decisions is elevator scheduling. Making sure that elevators at on the right floor at the right time to catch the lunch rush will be important. Otherwise, people get mad, and the overall tower rating drops. Building more elevators is an option, but it’s important to consider where the elevator is located.

Room placement is another important factor. Rooms generate noise, dirt, beauty, and shops and other retail rooms generate traffic. While retail rooms want to be near traffic, offices and apartments don’t want loads of shoppers walking by every day, causing disruption. Rooms will effect each other in how they’re placed. I do need to ensure that there’s no single, optimal room placement solution, though. My hope is that having different class levels for the rooms will alleviate that problem.

I’m still working out other elements of Isotower’s design when it comes to decisions. One idea is the ability to place solar panels on the roof of the tower. This would help with the energy bill, but would be affected by things like the weather. On the other hand, you could accept regular payments to build a cell phone tower broadcaster/receiver, but it would detract from the overall beauty of the tower, which affects the rating. Or you could build gardens on the roof. Your residents would like it, but it would provide you no outright benefit.

As I work on the game, these are ideas and thoughts I have in the back of my head. There can’t be a decision without some sort of consequence. Otherwise, the game becomes a lot less interesting.

TT1: Isotower’s History

Welcome to the first Tower Tuesday Blog post. I plan on posting on this blog every Tuesday that I can, mostly to talk about various thoughts on ideas that may or may not make it into the game, or randomly write about tycoon game design. For now, a short history of Isotower.

It’s been a year since I started re-writing the engine for Isotower. In that time, the code has evolved from this, a plain tile renderer:

isotower2

To this, a proper game in development:

rooms

And it continues to grow.

It’s actually been over 6 years since Isotower’s initial development. The code first start life as SimMine, a game with the premise of building a mining town, digging into the earth, and trading those minerals for finished goods. Some day, I’d like to revisit that idea, though there’s been multiple similar games that have comes out since then with many of the same elements. You can see the first few screenshots of Sim Mine below.

Sim Mine Town Ground Floor

Sim Mine Town Below Ground

Eventually, I started work on Isotower instead. The first screenshot I have is shown here, with some definite placeholder artwork. Not much was in place then, outside of building on tiles. There wasn’t much simulation behind it.

Isotower's first screenshot

Most of the original code is gone now, though some of the screen -> world coordinates, and back, code lives on. During those years, I’ve learned a lot about game development, and programming practices, and I’m still learning new things and techniques. Fortunately, the code this time around is fairly easy to work with, so finishing Isotower shouldn’t take as long as it has taken to get to this point.