Jump to content
  • Advertisement
  • Remove ads and support GameDev.net for only $3. Learn more: The New GDNet+: No Ads!

  • 09/14/17 11:16 PM

    3 Game Design Mindsets

    Game Design and Theory

    Penkovskiy

    (you can find the original article here along with future 2D monogame tutorials)

    It was a late Saturday afternoon as I began the walk across the crooked streets of the inner city.

    With a small tip-off from one of my trusted friends, I decided to go looking for this suspicious and mysterious looking man who usually hangs out behind Yarn’s cafe on cold nights like these.

    It was out of sheer desperation and utter determination that pushed me to get my hands on a rare type of night vision goggle that was off the market.

    As I located the shadowy figure behind the cafe, his face slowly illuminated as he moved into the light. It was easy to see from his worn and anxious face that it was urgent business that had brought him.

    Tracking this guy down was hard. After many wrong turns, a lot of false information, and a risky run-in with authority, I had finally located the dealer.

    But I noticed something strange.

    My friend from earlier had bought these goggles at a quarter of the price this guy was selling them for – I couldn’t believe it!

    His prices had actually raised significantly for night vision goggles… and only within a few hours…

    3 mindsets you can use to design practically any system in a game – and KNOW it works

    When designing the nitty gritty numbers for your game, the process can be fun. It can also simultaneously feel like you would rather poke small, long needles into your eyeballs.

    How much damage does this flaming sword of skulls and bones deal? 5,000 hit points YEAH !!!

    It’s extremely easy to get carried away or end up with an unbalanced mess that ends up breaking your game at spots where you least expect it.

    There’s a specific reason I decided to fluctuate the price of popular items in my game’s black market, however, as you’ll learn below, the reasoning why is anything BUT random.

    I love balancing my games. Not just because I’m a complete nerd, but I also use a very refined and methodical system.

    I’ve always envied games that have a fairly large-ish (consistent) player base, mostly because of two reasons:

    1. They have access to a large amount of ‘statistical’ numbers we can test
    2. Getting a large and consistent player base to test your game from scratch is hard

     

    Is it weird that when I start getting a lot of players in one of my games, I track how many times each tile has been stepped on since the beginning of the game (and then continue to run it through a heat-map process that tells me how densely populated that area is)?

     

    popularityheatmaps.png

    (lighter areas are heavily populated)

     

    I know I know, I’m a complete weirdo. You don’t have to tell me.

    I design my games using 3 simple concepts and strategies that are extremely powerful.

    By following this strategic and methodical system, you’ll be able to rapidly test, move fast, and experiment further than if you were to just throw spaghetti at the wall and hope something sticks (like everyone else).

    I’ve read a lot of game design documents, and most are super boring, or too vague to really give me actionable advice.

    “Design with the player in mind!” What does that even mean?

    What does that look like when you’ve been awake for 40 hours straight staring at your computer screen, talking to yourself, questioning your sanity?

    Here are some unique things I did to my game’s market recently;

    1. Capped the amount of money players could hold.
    2. Inflated prices on popularly bought items with a slow decay time. 
    3. Example equation:
    4. (price = 0.99*price + (1-0.99)*initial_value) called every second
    5. Fined players through money (something you don’t want players to do? Fine them heavily for it – you’ll quickly see that nobody is cursing anymore )
    6. I made players have to repair their most used items with money.

    Why did I make these decisions?

    I’m not just waking up one day and saying “Let’s fine the players! They suck!”

    Each decision was based upon testing and previous data, ran through this framework.

    If I thought it would be beneficial to fine players when they curse, I would first spend 5 minutes making a code that tracks how many times players curse and store it in a log.

    I’d look at it a week later, and based on how often players curse I would decide if fining them would have an effect on the economy. 

    Money inflation is a problem in most multiplayer games, but using a systematic approach that I’ll show you below, you will always know which lever you need to pull to get your game on the right track and finely tune it like a well-oiled machine (no matter what problems you’re facing).

    Step 1. A benchmark is something simple to track.

    Follow me through an overly simplified rpg “leveling up” process.

    A player starts at 50 health.

    Each level, they gain 10 health.

    The max level is 20, meaning the max health is 250.

    The most powerful weapon in the game deals 10 damage per second.

    The most powerful armor in the game protects 80% of damage.

    It would take (~2 minutes, or 125 ‘hits’) to kill the strongest player in the game who’s wearing the strongest armor in the game while you’re using the strongest weapon in the game (assuming every hit lands while both of you are running around).

    These are what I call benchmarks. With these benchmarks, it’s infinitely easier to see exactly how balanced your game is from an overhead angle.

    Step 2. Working Backwards

    By knowing your benchmarks, it’s infinitely easier to decide “I don’t want it to take 2 minutes to kill Bob, I want it to take 1 minute” — rather than continuously guessing why it takes the strongest weapon so long to kill bob but one hits everything else.

    Knowing this, you can adjust each variable accordingly to set an accurate (to what you feel is right) amount of time it takes to progress in the game.

    Just from our benchmarks alone, we can adjust the following variables:

    1. Bob’s max health
    2. Bob’s health gained per level
    3. Percentage of damage our armor deflects
    4. Bob’s speed slowed by his armor (changes combat dynamics)
    5. Speed of the top performing weapon (1 hit per second to 1 hit per 2 seconds)
    6. The damage of the top performing weapon

    With this mindset and formula alone, we are already 98% ahead of where you were before (and where most people are when designing games).

    Notice when most people react to an overpowered weapon, they usually just turn the damage down without knowing A.) Why they are doing it and B.) What their ultimate target is

    We could even get creative and introduce new designs to balance this.

    1. Weapon damage is (reduced or multiplied) by a percentage based on player’s overall level.
    2. Health gained per level can slowly decrease (from 10 down to 1) by every level closer to the maximum level allowed.
    3. Changing the percentage of damage our armor deflects based on player’s level
    4. How easy do items break? By striking the best armor in the game, does it destroy an item faster? If so, would your weapon be destroyed within the amount of time it would take to kill Bob?

    It can get complicated very quickly, but that’s why we test each change we make to the game one at a time, develop data, and make decisions accordingly.

    Step 3. Building a finely-tuned machine (perhaps the most important step of all)

    We can debate, and ponder, and guess all we want about how to balance a game. How to design your game. I know first-hand because I love doing it.

    It’s fun.

    It’s fun to dream about how great your game could be, and romanticize about some kind of super complex chemistry mixing system with its own periodic table of elements where player’s can mix to change their genetic codes to enhance stats or change appearances and give them special abilities, and what would happen if blah blah blah.

     

    This, my friends, is where I’ve seen more “indie game devs” fail than what I call a ‘dish graveyard’.

     

    dishgraveyard.png

     

    When I used to work for Dish installing satellite cable, I would see stuff like this. When old people moved out and new people moved in, they would change service, or in most cases, a new dish was just put up because it was easier than adjusting/tracing cables back/swapping parts off an old dish.

    It was easier to just throw up a new dish.

    And I say Indies because I’m a fellow indie who’s been plagued by this. I say Indies because most don’t have a team pushing them to focus on their most important KPIs (key performance indicators).

    It’s fun to make up ideas, get halfway through a project, and come up with some other random idea that you just have to try because motivation strikes.

    Riding that high of motivation, you jump to the next project, eventually getting bored of that until the vicious cycle begins to repeat itself.

    We can conquer this by using small tests and tracking our KPIs.

    We have the ability to test literally anything within our games — and that gets my inner nerd all fluttery and excited.

    I track things like how many times an item is bought in a specific period of time.

    I track how often that same item is discarded.

    If you aren’t tracking stats like these, shame on you!

    However, we can get super carried away real fast trying to track everything.

    What do you think is more important to track?

    • How many times a player gets killed (for no specific reason) or;
    • How quickly a player is leveling up (in general)

    Setting KPIs in the initial phase

    This is where you need to get solid on specific KPI’s first, preferably straight from the initial design phase.

    These Key Performance Indicators are going to be the most important benchmarks that you need to hit in your game.

    They will guide you towards the things that are most important now, and steer you away from the wrong things that will cause you to lose focus.

    If I were just starting out making a game, my KPIs would be the most basic –

    1. Player movement engine (with collision)
    2. Basic player animation (walking)
    3. Bear bones interaction system

    If I was trying to balance a weapon, my KPIs would probably look like this;

    1. Strongest weapon in the game takes 5 minutes of combat to kill the strongest player in the game
    2. Strongest weapon in the game takes 1 minute of combat to kill the weakest player in the game

    Simple benchmark to hit.

    The goal is to get something up and playable ASAP so we can begin testing different things with the players.

    This is another fatal mistake I see so many people make.

    They spend months (sometimes years) creating this super complex combat-combo-style-point system, only to release it to few (if any) players — (because the developer didn’t want to let people play the game when it wasn’t ‘perfect’, they couldn’t develop a pre-alpha player base)

    And come to find out, the players hate it.

    Small test loops is where the real magic happens

    • Using previous benchmarks and data from extensive testing and player feedback, we iterate through small loops.
    • Take action and test based on a small change in our benchmark.
    • Did we hit our KPI?
    • (Did our KPI change?)
    • Repeat.

    You can only plan something so far. When your work meets the real world, it’s the fine-tuning that will push it over that ‘excellent line’.

    Because in reality, your players are the market, and as much as it sucks to hear, no matter how much you liked putting in that lizard sword machine gun, if nobody uses it, buys it, or it can kill anything with 1 hit, you will have to adjust it to your player’s (market) demand.

    Unless you are tracking, planning, and hitting your KPIs (the only things that matter in the initial phase), you’ll easily get sidetracked, overwhelmed, start looking at the wrong things, make bad design decisions, and eventually, lose focus.



      Report Article


    User Feedback


    There are no comments to display.



    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

  • Advertisement
  • Advertisement
  • Latest Featured Articles

  • Featured Blogs

  • Popular Now

  • Similar Content

    • By 999PING
      I'm very often facing one small problem when trying to learn some new stuff - hard to choose what to learn next.
      Even if the problem seems to be small it has a very huge impact on the final result I think. And because Game Programming offers so much to learn, I'm always feeling that I'm missing something important and wasting my time learning something not important or unneeded. Or usually, I'm afraid to focus on something specific and huge for a long time, because I think that I'll spend all my time on that particular filed and will not be able to solve another problem.
       
      So I've tried to fit all my thoughts in this questions.
      1) Are you trying to cover all the aspects of Game Programming? Or you trying to focus on some specific aspects like physics, animations, or networking etc.
      2) What is your way to find a new theory or whatever else for your learning process? (Manuals, Courses, Books, Documentation? etc.)
      3) When you trying to learn while practicing, are you search for learning because of a problem that appears, or because you wants to try new things? How do you choose this new thing? And finally, Which of this two approaches was the best for you if any?
       
      Not actually in the scope of the topic, but I'm also very interested to hear your thoughts on this.
      What is Game Programming for you? How would you describe what should Game Programmer able to solve?
    • By FlyX
      Hey Gamedev.net Community!
      I am working on a mobile builder game that's already running for 8 years.
      In its early days, the game had a nice content progression until level 30(current max level is 140). With content progression, I mean at what level items unlock in the build menu. However, over the last ~4 years, the previous developer decided to unlock all the content between lvl 1 and level 30 (reasoning that the new content should be available for all players). This results in 1200 ~available items at level 1 and ~3300 items at level 30. Overwhelming players at the start and missing any content progression after level 30(can be reached within a few weeks, while a big part of the community is playing since multiple years).
      But how should this be addressed in a running game with a considerable user base across all levels?
      Internally we have a passionate discussion between moving existing items to later levels(and risking to anger existing players) or just adding new content to later levels(don't address the too much choice issue at the start)
      Since we are kinda stuck in the discussion, it would be nice to hear some external input
      Thanks!
    • By supermikhail
      You click on objects in the world and get their name and how it's pronounced, in Russian which is my native language.
      That's pretty much it. Basically I want to be 100% sure that I can accomplish the project. The problem is, as a player, would I want to buy it? I myself am poor and consequently very selective with my entertainment spending. Which means, it'd be too lean an offering for me.
      On the other hand, I more or less believe that there are... enough "suckers" out there who'd pick up anything with "language learning" in description... To put it plainly.
      I guess that's the short of it. I don't know if that last intuition of mine is correct. And if it is, I don't actually want to scam people. But I don't want to promise something that I don't know that I'll be able to deliver, like... voice recognition or anything as useful and preposterous. Or even a story. I've never written for games. I've never designed a puzzle. All of which would probably add all the value necessary, but more likely just show me my limits.
      I suppose you could say "make a prototype". And I know I won't enjoy playing it, simply because, well, Russian is my native language and I like challenge. But I'd enjoy making it, and I like the idea of using videogames for studying languages.
      Any thoughts to help my conscience, more or less?
    • By Septopus
      Okay, looking for some constructive feedback/criticism here... 
      What follows is the code of my c# UDP Socket Class.  I've written this based on a number of online examples and a few distant memories from the past, so I really have no idea how "bad" the code is/could be in a 100+ concurrent connection scenario(my dev environment is just two machines at the moment)...  It works, I know that, it is fairly stable(I can't break it when using it normally), and it behaves how I believe I want it to. 
      It is a dual purpose class for handling both Servers and Clients.  It uses an asynchronous receive and synchronous send(I may switch to async send if it proves beneficial later on).  My servers use Client sockets to communicate with each other and to perform internal connection tests in a multiple server, "single shard" type environment.  I'll be devising some heavy load testing methods a little further down the line, but I'm hoping to fish out most of the major gotchas before I get there.
      So, please, let me know how to fix it up if it smells terribly to you, or if not, that's even better...
      Sorry for the large code dump, but THANKS for checking it out!
      using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using UWAvatarServerData; namespace UWAvatarServer { public class UDPSocket : IDisposable { //Some simple string length counters and averages to get a rough idea of generated traffic. public int sndMax = 0; public MovingAverage sndAvg = new MovingAverage(); public int csndMax = 0; public MovingAverage csndAvg = new MovingAverage(); public int rcvMax = 0; public MovingAverage rcvAvg = new MovingAverage(); //Constant for configuring the prevention of ICMP connection resets private const int SIO_UDP_CONNRESET = -1744830452; //UDP socket private Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //Buffer Size Constant private const int bufSize = 8 * 1024; //Raw string data from client packets private Dictionary<EndPoint, Queue<string>> messageDictionary; //Queue for holding raw string data from server packets when in client mode. private Queue<string> cQ; //Referece to the data store used by the server(for access to the current game time clock) private UWDataStore dataStore; //Time code storage for last sent/received messages private double lastSentMessage = 0; private double lastReceivedMessage = 0; //Boolean to determine which mode we're in so received messages get put in the right place. private bool clientMode = false; //Max string lenght allowed by the servers. private int maxMessageLength = 1450; //IDisposable stuff public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { // free managed resources if (_socket != null) { _socket.Dispose(); _socket = null; } } } //State class for async receive. public class State { public byte[] buffer = new byte[bufSize]; public EndPoint epFrom = new IPEndPoint(IPAddress.Any, 0); } //Server "Mode" public UDPSocket(Dictionary<EndPoint, Queue<string>> msgsDict, UWDataStore DATASTORE) { clientMode = false; messageDictionary = msgsDict; dataStore = DATASTORE; lastSentMessage = dataStore.UWServerSeconds; } //Client "Mode" public UDPSocket(Queue<string> mq, UWDataStore DATASTORE) { clientMode = true; cQ = mq; dataStore = DATASTORE; lastSentMessage = dataStore.UWServerSeconds; } public void CloseSocket() { _socket.Close(); } //Internal connection status checking public int SendHowStale() { if (lastSentMessage == 0) lastSentMessage = dataStore.UWServerSeconds; return (int)(dataStore.UWServerSeconds - lastSentMessage); } //Internal connection status checking public int ReceiveHowStale() { if (lastReceivedMessage == 0) lastReceivedMessage = dataStore.UWServerSeconds; return (int)(dataStore.UWServerSeconds - lastReceivedMessage); } //Start/Bind a Server. public void Server(string address, int port) { //In case restarting uncleanly, dunno if this actually does anything.. _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true); //Ensure all async packets contain endpoint info and etc. _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true); //Ignore ICMP port unreachable exceptions. _socket.IOControl((IOControlCode)SIO_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null); //Bind to port. if (address == "all") { _socket.Bind(new IPEndPoint(IPAddress.Any, port)); } else { _socket.Bind(new IPEndPoint(IPAddress.Parse(address), port)); } //Start receive callback process. Receive(); } //Setup a Client to Server socket. public void Client(string address, int port) { //Dunno if these two options do anything for client sockets, but they don't seem to break anything. _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true); _socket.IOControl((IOControlCode)SIO_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null); _socket.Connect(IPAddress.Parse(address), port); //Start receive callback. Receive(); } //ServerSend sends to any EndPoint from THIS server. public void ServerSend(string text, EndPoint ep) { try { byte[] data = Encoding.ASCII.GetBytes(text); _socket.SendTo(data, ep); lastSentMessage = dataStore.UWServerSeconds; if (text.Length > sndMax) sndMax = text.Length; sndAvg.ComputeAverage((float)text.Length); //Console.WriteLine("TO NET: " + text); } catch (Exception ex) { Console.WriteLine("ServerSend Exception: " + ex.Message); } } //Client Send only sends to the connected Server. public void cSend(string text) { try { byte[] data = Encoding.ASCII.GetBytes(text); _socket.Send(data); lastSentMessage = dataStore.UWServerSeconds; if (text.Length > sndMax) sndMax = text.Length; sndAvg.ComputeAverage((float)text.Length); //Console.WriteLine("TO NET: " + text); } catch (Exception ex) { Console.WriteLine("cSend Exception: " + ex.Message); } } //Setup Async Callback private void Receive() { try { State so = new State(); _socket.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref so.epFrom, new AsyncCallback(_Receive), so); } catch (Exception) { } } //Receive Callback private void _Receive(IAsyncResult ar) { try { State so = (State)ar.AsyncState; int bytes = _socket.EndReceiveFrom(ar, ref so.epFrom); lastReceivedMessage = dataStore.UWServerSeconds; string smessage = Encoding.ASCII.GetString(so.buffer, 0, bytes); //Console.WriteLine("FROM NET: " + text); if (smessage.Length < maxMessageLength) { if (smessage.Length > rcvMax) rcvMax = smessage.Length; rcvAvg.ComputeAverage((float)smessage.Length); if (clientMode) { cQ.Enqueue(smessage); } else { if (!messageDictionary.ContainsKey(so.epFrom)) { messageDictionary.Add(so.epFrom, new Queue<string> { }); } messageDictionary[so.epFrom].Enqueue(smessage); } } _socket.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref so.epFrom, new AsyncCallback(_Receive), so); } catch (Exception) { } } } } Generally speaking I use it as such:
      public static bool running = true; static void UDPServer() { using (s = new UDPSocket(MessageDictionary, UWDataStore)) { s.Server("all", 37373); while(running) { //Servery Stuff Goes Here. //Like reiteratively dequeuing the Message Dictionary Queues and processing/replying to all commands/etc... } } } All processing of individual messages from clients is handled with Task.Factory tasks, and a reference to the server's socket varible (s), and the client's EndPoint is sent along the ride for use in replying to clients.  There's no game logic and there are no client replies that happen directly from within the UDP server's main while loop, mostly just connection status checking and reorganizing of the Message Queues into Tasks.
      Thanks again for making it this far.
    • By JoAndRoPo
      Hi!
      I have a doubt regarding the Daily Bonus.
      Let's say 7 days. Player receives Daily Bonus in Day#1, Day#2, Misses Day#3, Plays on Day#4, and so on. What happens when the player misses a day? Does the Daily Bonus reset back to day#1? or does the player miss the reward of the missed date and continue to receive the reward on the next day? Can you name me some games that have used a unique daily bonus logic?
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!