Chad Wolfe, Indie Game Developer
Chayed Creates (Chad Wolfe)
  • Home Page
  • Portfolio
    • Game Projects
    • Pixel Art - Animations
  • Chad's Blog
  • Bio
  • Contract

Breaker Bots Design - Dev Blog - State Machines and Timelines

12/5/2019

Comments

 
Notice: This is just a duplicate of the Breaker Bots dev blog on Itch.io
What is Breaker Bots?
Breaker Bots is a multiplayer mash up of three genres: Brick Breaker (Breackout), Shmups, and TCG games. The gameplay is completely controlled through the use of cards, and is a multiplayer party game, in development by Chad Wolfe. The cards (Chips) are used to create balls, missiles, and other objects that can be shot across the screen, improve the player's paddle, recover, and more.For more information, it'd be best to check the title page. 
What are the States of Breaker Bots?
What are the States of Breaker Bots?
The reason why I thought it was significant to make a blog post about the State Machine usage in the design of Breaker Bots is that the game actually uses a large tree of State Machines, three of which being the most prominent:
  1. Runtime State: Determines what screen the player is on.
    1. Title, As implied, displays the Title Screen
    2. Main Menu,  displays the Main Menu of the game
    3. Deck Builder, Displays the deck building menu
    4. Game, Displays the game screen
    5. Etc.
  2. Runtime Substates: Determines what "State" the current Runtime State is in
    1. Title States:
      1. "Credits": shows the game credits
      2. "Title": shows the game Title
    2. Etc.
  3. Object States: Determines what functionality should control the game object
At first I was a little scared to compose the entire game of such significant State Machines, because I hadn't actually done that before. As is usual in the discussion of the importance of State Machines, I always used variables to check whether the game currently met conditions that allowed for certain actions to be called. My fear was mostly in that, by using State Machines for the majority of the game, I'd have less flexibility with the kind of functionality that I could code into the game, such as visual transitions between screens and such, but I guess one could say that's a bit of a silly concern to have.
Actually, after developing these state machines and having all the states prepared for usage (Took a day to have the menus and game screen states laid out, which was so much easier than the complex methods I'd used before.) I found that I had much more room of creativity than before, because where before I had to worry about certain code interfering with other code, with the more specific my state machines are, the more I can keep each part separate and abstract them. 
This all creates quite a lot of room for duplicate code at times, but ease of use definitely beats redundancy here. With newer systems, there's no need to worry about redundancy, so long as it's not dealing with heavy operations. 
What are Timelines?
What are Timelines?
Picture
Timelines are each their own "object", which controls the motion and actions that many UX objects perform. Each State Machine includes it's own group of Timelines for each state. Timelines use a simple editor with a slider, and drop down list so I can choose what animation timeline to control, and add functionality to it that happens in between it's beginning and ending point. At the moment, everything uses simple linear interpolation, but I'm in the process of adding curves as well.
Because Timelines are included within states, and Timelines are easy to create, I can activate a Timeline for the Intro substate within the Game State which will move objects onto the screen stylistically, and with tweens and curves I can ease objects in, bounce them in,  or do whatever I want to make it look as fancy as possible. 

Consensus
The best thing about these features is that they were incredibly easy to develop and not only make the development of the game go much smoother, but also makes the game much more functional and look much better. In an older project, such as Machine Minds  (A game that I'd developed that became not much more than a buggy mess), I would have used variables with different values controlling animations between screens and the like. While I did get a lot of positive feedback on the look of the game, without a proper set up, it became riddled with bugs. 
I guess, while a lot of this information might be common knowledge to most game developers, I'm just writing this dev blog piece, and probably any other post I write later, because it's one of the things that excites me about developing Breaker Bots. This simplification of development has woke a joy in development that I'd lost for some time, because of the anxiety to deliver a product without the proper ability to do so. 
But here we are, in a place where; although I've been incredibly busy in my personal life (that happens not to be funded by game development, therefore allowing me little time, as a father of two, home owner, pet owner, and husband, to work on it; I've gotten quite far in a game I'm very passionate about. A game that is only a step in the direction I'm going in my game development journey.
Comments

Machine Minds Dev Blog - About Performance

12/29/2018

Comments

 
Picture

Compromise for Maximum Overdrive

This blog post will introduce you to all the coding magic that's done behind the scenes to enable thousands of objects to exist with a Construct 2 game with little to no slowdown, and how to design your games to boost performance with these tricks in mind. 

Starting with these tricks in mind from the very beginning will make every game loop you code marginally faster, without changing the design of your games to compromise for the limitations of an engine or any kind of code, and expand what you can achieve on even weaker platforms that you develop for. 
Machine Minds, being a game built specifically for Mobile has needed to make compromises that don't have a negative impact on the player. These were compromises you might have seen in another project that I've worked on known as "Jell.io", which had a similar goal in mind, but went through development hell before I designed these tricks. But, now that I have, you might get the pleasure of learning them before you feel the hardships of not knowing them. 
​

"Game Loop Segmentation"


What I call "Game Loop Segmentation" (for lack of a better name), is a method of planning specific blocks of code to run on separate ticks, giving precise control over the performance of any given project. This is just one core feature of any game engine I make nowadays, because this separation (which doesn't include functions involving input and physics) is negligible by most players, and boosts performance by *s, "s" here being the actual count of segments that exist.
Game Loop Segmentation is the first part of any code that I write, which is done within the main project code (the game.cpp's main() function if programmed in C++). I always have a tick counter (the amount of ticks since the game started) that is modulated by a tick segment count integer. 
In the Main method/function, I do this:

tickcount += 1;
tick(tickcount%tickSegments);

This does only one thing: calls the tick function for every included script file in the project. If, in those included scripts, the parameter passed is equal to the tick we need to call the functions of that class, or file, we call those functions. 

In Machine Minds, I actually have 5 core ticks. They're all listed below.
Picture

​The line here separates a different kind of tick that I'll discuss further in a moment. The four on top are of the same nature that I've been talking about. They're segmented Game Loops. As you can see, I call 4 unique ticks:
  1. "game.action_0
  2. "game.render_0"
  3. "game.action_1"
  4. "game.render_1"
The "action" loops are groups of functions that update the game functionally, and the "render" loops manage the spawning and placement of objects visually. 

You might be thinking at this point: if each loop contains different functions, the duration of each loop might be marginally different than another. You'd be right. That being said, this method requires a good amount planning. You must know the bottleneck of the functions being called for each loop, so as to separate them all as equally as possible. In my case, each loop calls the same amount and similar kinds of functions. That being said, I'm somewhat aware of the duration for which each loop will take to process. 

Keeping with the name of "Game Loop Segments", I'm going to demonstrate the heaviest blocks of codes within each tick respectively.

​Now, looking at this code you might have noticed that one other tick has cropped up that I haven't yet discussed. This tick, being the "wave tick" is a tick that calls every second (or the variable duration) and performs actions for the towers and enemies. This "wave tick" is the slowest of them all, and the game does experience some hanging when hitting it right now, because all of this functionality is done on that tick for the sake of simplicity. Moving these to the action ticks would work fine, but I'll need to also add checks to determine whether actions have been called on a specific tick at a specific time, allowing control over the amount of times actions are done on a tick. For my design's case, this amount of control is necessary.

Despite all that, the implementation is easy. You can see that I'm calling really big loops (including a large amount of moving objects) without any slowdown.

Do Not Disturb


One piece of advice when handling a large amount of objects is shared in many places: Do NOT create a lot of objects at any given moment in time, instead, create the amount you know you'll need+a little more, and move their positions and change their appearance as you see fit. 

In the case of Machine Minds, I never delete Tile sprites, for existence. And that little minimap at the top left is looped through to determine where tile sprites should be and what frame within the animation they should be. While you can't see it, there are actually a few tilemaps up there for operational use, and I'm just taking advantage of their 1 pixel per tile placement nature to make a visible tilemap with a viewport box. 

These kinds of loops are used for Enemies and Towers too, but it's slightly different for the two. Tower sprites are created when the tower itself is created by the player, and never leave. Enemy sprites are created upon initialization of each wave, and are deleted after the enemy is destroyed. 

The phases "Build" and "Battle" within my game are used as short pauses that call "init" functionality for the waves, and within those init's complicated code is being called that include filling arrays, spawning enemies, and managing events that'll take place later on in the wave.

The Damage Time Optimization

Picture
Another optimization that was made was the total exclusion of complicated "if enemy hit by X bullet" calculations. The tilemap based nature of the game's design allows me to tell the game to apply damage on each Wave Tick based on the amount of damage that exists within a "Damage Tilemap" that you can see has two orange tiles at the top left because the towers are shooting at those given positions. (Yes, I know there are some Z-index ordering issues here)
The tilemap itself actually has 8 tiles, and each index within it determines the amount of damage to apply if the enemy walks onto that tile. 

So... We Need a Stress Test

I'm going to run the game in debug mode within Construct 2 with a WAVE_POOL (the enemy count) of 10000 enemies.

Jarring Pause

Picture
Okay, so, 1000 objects on my low spec system results in 30FPS. This was a test done after seperating ai_action function calls by a groupcount, and incremented by a group integer to determine which group of AI's to perform functions on at any given moment in time. This works because gameplay in Machine Minds isn't fully updated until "wave.tick" is called. "wave.tick" is commonly called every second. If we have 30-60 FPS, we can create AI groups that are the size of the smalled Framerate we've gotten in the last couple of seconds, so in this instance, we could create 30 groups... I'm going to set it to this value and set WAVE_Pool (the amount of enemies) to 1000. 
(BTW, that object count is the amount of objects within the game, not the amount of enemies. There are 500 enemies in the instance above, and 20 groups)
Picture
You're watching this in semi-realtime, folks. 1339 objects, an average of 30 frames.
Now the great thing about Construct 2 is that we have the handy profiler. This tells us where the slowdown is really coming from, so let's look at that. 
Picture
So, looking at this, we might deduce two things: GAME is where we include our main ticks. That is, as it should be, creating a bottleneck for the game. But what I'm interested in isn't that. It's the amount of processing time it takes for [render] main to complete. And in that, I found a bit of a technical flaw in the code. It's a loop that loops through every 2.5D object in the game to determine z-order.
Picture
I'm going to disable that for just a minute. And rerun the debugger with a WAVE_Pool 10 times the size of the last test. Keep in mind, every enemy has movement and damage calculations. I'll create another loop for ordering that doesn't conflict with the current rendering system later, but just for fun, I want to see these numbers.
Picture
Okay, so 10000, 10 FPS. Not great.
Picture
But at 1000, the performance went back up to 60FPS. Seems good. ;)
While there is still some rendering glitches, and performances hacks that can be done later, this is a good note to end on for today.

Ultimately

These are things I'd advise all developers use when developing a game, even in a lower level language like C++. C++ might be faster, but boosting the performance of your game where you can, without adding much time to development, is always something to strive for. That being said, you shouldn't try to work these tricks into a game that's already in development (unless the game is really that slow), because a lot of these should be things you code from the very beginning. Rewriting code to fit these practices can see you spending many more months coding, especially for a larger game. Especially for "Game Loop Segmentation", because it ​is basically creating multiple game loops. If you code with one game loop in mind, you're coding everything WITHOUT the game loop in mind. You don't write "Do it on this loop" code, because you only have one Game Loop. 
Comments

GDBD: The Fall of Multiplayer Shooters ~ Level Design

12/17/2017

Comments

 

Hello, and Welcome to GDBD!

   It's been a long time coming, and I've been away for some time. Most of that time was actually spent learning, as well as developing KIDE (My game engine) and Byte Sized Heroes. All of these details are crucial to my success as a developer, but I've been neglecting some of my duties because of how much work I'm putting into perfecting everything. I apologize for the lack of updates, but I certainly won't apologize for the way I do things. You'll appreciate that in the end, I'm sure. Regardless, let's get this show on the road.
   Today we're going to be discussing the level design in the FPS genre. This is something that many gamers really notice, without actually saying much, and it's a bit dissapointing. The maps in a shooter often make or break the experience, as they're kind of the mold that the game mechanics are poured into. Simple mechanics doesn't mean you have to have simple molds though, and games like COD: WW2 are not made to be stronger experience because everything is made to be much more basic than previous iterations. I'm hoping that game designers will see what I mean.
   Also, in the next topic, I'm going to be discussing art direction. Art direction, oddly enough, doesn't really seem to even exist in the FPS genre, which is somewhat dissapointing. You'd think that, with games like Persona 5 becoming grand hits for almost only it's visual and audible flair, other developers would take some cues from them, but I guess other's just don't like to listen.
(BTW, I'm not saying Persona 5 isn't a fantastic game without it's visual and audible flare, but I am saying, it doesn't stand out much from it's predecessors without it, it's success VS. the others is telling of how important this aspect really is.)
​   Anyways, without further ado, let's begin.

Confined Space Level Design

Picture
   I want to start this discussion off by talking about what I like to call "Confined Space Level Design", which refers to the heavy use of rooms and corridors to construct a map. This is my personal favorite kind of design, because of the simplicity of dropping in some boxes and churning out an idea. This type of design is still used quite often, but in the sense we're going to discuss, only as reference before artists replace the boxes with artwork.
Doom maps, even in the remake, are constructed using rooms and corridors. These make channeling the flow of gameplay easy, especially for rooms/corridors that have only two exits. The designer will almost always know where to place enemies and objects in relation to the player's location.
Picture
Picture
While the development of these kinds of maps are vastly simplified compared to what we're used to in more modern shooters, the rest of the game tightly fits that mold. Some rooms are filled to the brim with enemies, and before said event you might be handed a big gun like a rocket launcher. 
   This makes Level Design for a Doom game simple enough that millions of people have done it, and I'm sure they're not done, especially considering the release of the new game, which bravely keeps (and expands) on the Doom formula of design.
   Considering Doom's level design, there are many things to take into account. The two main details of the design being the two most memorable pieces of the game: Your weapon and the enemies you encounter.
   As noted before, these two elements are mixed and matched to create a variety of experiences for the player. The weapons are also something to consider when constructing multiplayer experiences, but the great thing is that, with enemies that are relatively similar to the funtionality of the player, accounting for enemy placement  also somewhat determines how a level might feel when playing head-to-head with other players. 
   To expand on this discussion, I want to bring up a classic that is also one of my all time favorites, Time Splitters.

   Time Splitters uses a similar to Map Editor to Doom, but it actually uses it a bit more effectively than the classic Doom games. The thing about Time Splitters: Future Perfect's level design that is really strong is when the Z axis is used heavily, making heavy use of the different layers. This, sadly, makes the AI shit out even more than normal, but we're more worried about PVP, not bots.
Picture
Picture
This map is actually a really good example of what I'm talking about. Just watch the video to really understand the strength that this kind of level design really has. The guns are relatively simple, with some tricks, as well as the gameplay. This lends to having a variety of different experiences available for gameplay, such as peeking out of windows, battling across bridges hanging in the air, etc. This map is so well designed, it's actually kind of incredible.
   So, this kind of level design focuses heavily on confined spaces as the variable to consider for combat situations, and weapons typically have smaller scale functionality than those you might see in a game that focuses on big battle situations. These levels are probably will you will see the most variety as a whole, simply because of the simplistic nature of the creation of a level and the mechanics as a whole. 
   The stronger the limitations in the design of the game, the more there is to experiment with. This fact might sound like I'm saying that making a game slow and clunky allows for more creative gameplay, but it's more that the games mechanics and movements have to be hard-fit to the level creation. The levels in Doom and Timesplitters might not be as fun if the games played more like Warframe, allowing you to sprint around and run on walls.

Open Ended Level Design

Picture
   Open Ended Level Design focuses on allowing the players a kind of sandbox to run around freely in. There usually isn't a definitive strong or weak point in these kinds of maps, at least not in their original carnations, and they're often filled with terrain and hills. 
   These maps allow for the placement of vehicles and tanks, and they often feel like the chopping off of an actual world, rather than playing around inside of a building.
   I usually talk about Halo when I discuss a strong use of both instances of level design. That's not to say other games don't also do it well, such as Unreal Tournament and Timesplitters, Halo's maps are some of the most memorable for me.
   Taking Ascension as an example, the map is
Picture
Picture
almost symmetrical, with two gaurded high points and an uncovered mid point with two covered corridors on the side.
   Players can't sit on the high points for long, as grenades are fantastic tools for pulling camping players out of otherwise very strong points. Players open in the mid have almost complete control over the gameplay.
   Open ended maps combine confined space and open areas to create a back and forth pull of gameplay. They're designed specifically to keep players moving, regardless of skill level. These maps are fantastic, but honestly some of the hardest to make well.
Picture
   Open Ended Level Design offers a lot to the gameplay experience. The problem, in relation to Confined Space, is that many of the Confined Spaces are actually rendered a bit useless in deathmatch themed game modes. The open area is often the safest areas to be. Considering that, it would be nice if, even for deathmatch game modes, there actually were some incentive to make effective use of the maps entire area.

Big Battle Level Design

Picture
   Big Battle Level Design is used for games that include both large teams of players, and usually objective based gameplay. These maps take some cues from the Open Ended Level Design, but chop the map up into sections of smaller design areas.
   While Halo includes this type of map design as well, the game that uses this type of map most prominently and effectively is the Battlefield series.
   Battlefield 4 uses this type of design to the largest possible extent, with the innovation of their "Levelution".

Picture
Picture
   DICE saw that, considering the design of their maps being smaller sections leading up to the biggest central point, they could create a mechanic that handed that scale into the hands of the players. Levelution did this by allowing players to destroy massive structures that were also the central point of the map.
   This would often kill many players in one of the most incredible kinds of destruction ever seen in video games. Then, to add to that, the game replaces that bit of destroyed map with more level design by using the destroyed bits of the structure. It's a cool gimmick. 
   These kinds of games often allow for borderline simulation level mechanics, and that's what fans of Battlefield often enjoy the most, and that fact is why Battlefield does this most effectively. It feels more like a war, and one done by legitimate soldiers. 
Picture
   The question with this type of map is, does it actually change gameplay all that much? The answer is simply: Typically, no. In the same vein as adding more enemy AI, rather than different types, only serves to make the gameplay more tedious than actually improving the experience, typically this kind of gameplay does the same thing. Battlefield would be just as fun if it were scaled down, and in some incarnations (Bad Company) it actually is.

Three Lane... *Cough* Three Lane Level...

Picture
   They... Exist?

The End

   Anyways, thank you for joining me in this discussion! 
   My notes here are mostly that I hope that more developers follow the level design approach present in games like UT, Timesplitters, Halo, etc. I personally love a good mix of confined space and open ended level design, but it seems like, outside of Halo, we haven't had many games that have actually made maps like this. Hell, even Halo's taking steps away from this kind of level design, almost as if to appeal to COD's audience.
   Let's be real here though, Halo's maps are enjoyable because they're not like newer COD maps. Hell, I say newer, because even COD's maps used to be open ended too. Newer games from these franchises often contain limited maps, but not to the benefit of the game. Referring to COD, WW2 actually had some of the most limited maps I've ever seen, and almost all the guns are functionally the same. Almost every multiplayer engagement is the same in that game, and it's just incredibly dull.
   Please, let's make fun shooters again!

Comments
<<Previous

    Chayed Creates 
    a Blog

    Picture
    I'm a game developer, pixel artist, and daddy. I've published about 10 games, and work every day to grow my knowledge and skills to make the best experience for my fans.

    Learn more on my Bio page.

    Categories

    All
    Asset Store
    Breaker Bots
    Dev Blog
    Game Design
    Game Design Breakdown
    Game Engines
    Game Reviews
    Games
    Website Updates

    RSS Feed

Powered by Create your own unique website with customizable templates.