Dev Blog

Dev-Blog 226: Tools for tuning

06/29/2016

devblog_header08

Welcome back followers of the fearsome!

It’s Caley here this week and I’ve got a fun post on a tool we use to tune the in-game economy of Viking Squad (not the real economy, Nicks making a different tool for that).

Game economies, and real ones, are always hard to nail down as you can never fully predict how people will interact with complex systems. Players will miss things, they’ll exploit systems and find bugs you had no idea existed. They may even choose to opt out of certain mechanics entirely. To be fair many of these things are what makes a game engaging. But as a developer you want to leave as little up to chance as possible and develop an economy that rewards but also pushes back.

There are numerous ways to go about testing and tuning a game economy. You can enlist friends and playtesters to play the game so you can see how they interact with it (Early Access anyone?). You can playtest it yourself by trying to mimic various play styles. You can even try to find all the major outliers such as bugs that may cause some players to have an abnormal experience. All of these can and do work to make your game a better experience.

So as we put the finishing touches on the game these are a lot of the questions I spend my time addressing. If you add randomization to the system, such a random drops from enemies the outliers can be even tougher to track down. Let alone how the game will play for the average user. To make all this a bit easier on us Nick has made a tool that simulates thousands of games played and returns the averages. Which you see below.

DestinationStats

Using this tool i can select parts or entire levels and see the average Treasure gain the player is getting based on 1000’s of games simulated (Treasure is the in game currency used to upgrade your character in Viking Squad). You can see it in action below.

DestinationStats

The tool pulls directly from our data so it is always relevant and up to date making it great for checking random drops and ensuring there are no weird bugs that i left on some odd object. I can also see in real time how changes I make affect our economy. It shows the rates for one, two and three player games since more enemies spawn if more players are in the level.

One thing this tool doesn’t show is if a treasure is gained through a secret or some skillful play. This is where I step in and decipher the averages to better understand how your various players will get through the game.

That’s all for this week. Be sure to stop by Jesse’s twitch stream today at 4pm pst.

VS_DevstreamBanner

Twitter: Nick: @nickwaanders Jesse: @jouste Caley: @caleycharchuk SlickEntertainment: @SlickEntInc

Facebook: https://www.facebook.com/SlickEntertainmentInc

Twitch: http://www.twitch.tv/slickentertainmentinc

Posted by: Under: Slick Entertainment Comments: Comments Off on Dev-Blog 226: Tools for tuning

Dev-Blog 225: Frame timing problems

06/22/2016

devblog_header03

Welcome back, followers of the fearsome!

This week I fixed a problem that has been popping up in our game every once in a while. Our game normally runs at smooth 60 frames per second, but every once in a while the game would start to stutter and just generally become very un-smooth, man. The stuttering would last a few seconds and then the game picked up again and was buttery smooth once more. I’ve got some profiling routines in our game to measure what is going on, but every time I started profiling when this effect would show up, it would magically disappear, and the profile data would show that we’re perfectly within the desired frame times. So what is going on?

Our main game loop waits for the video buffers to swap, and then it checks how much time has passed to determine how many times to step the game. A time-accumulator float value is used to keep track of the time elapsed since the game was stepped, which is a pretty basic practice in most games. It guarantees that the game is stepped at 60hz on average, over multiple frames. The general code looks something like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
static const float GameTimeStep = 1.0f/60.0f;

void Game::Update(float dt)
{
	m_timeAccumulator += Util::Clamp(dt, 0.0f, 0.1f);	// Clamp the value to prevent spiral of doom
		
	while (m_timeAccumulator >= GameTimeStep)
	{
		Step();
		m_timeAccumulator -= GameTimeStep;			
	}
}

 
So in this code, m_timeAccumulator is the float value in the Game class that is increased by the delta time every frame, and then the game is stepped however many times to make sure the game gets simulated 60 times per second. This piece of code handles variable frame rates quite well, if the delta time dt is 1/30th of a second, the game will just step twice in a row, to maintain the 60x per second simulation rate.

(Oh, a small note about the spiral of doom. This happens when the game takes longer to step than ‘real time’. By capping the incoming delta time, we potentially slow down the in-game time, but at least the game doesn’t grind to a halt.)

Ok, we’re all good then, right? The code above should fix all our problems, no? Well, not exactly. The code above has one problem that is a bit hidden, and it only really shows up if the render rate is the same as the game step rate AND your time accumulator is very close to a multiple of your game step time. For example, in our game the problem only occasionally shows up when running in a mode that is 60Hz.

Hopefully the graph below will make it more clear:

frametimingbefore600_2

 

Lots of info in the graph above, so here’s some explanation. The black line at the top shows the perfect 60x per second game update time we want to have. The green dots are measured frame times. We measure our elapsed frame time directly after a the swap-buffers call, using the highest resolution timers available. I have found that despite using the most precise measuring routines, there will still be a bit of variation. In the graph you can see that the green dot are somewhat randomly offset from the perfect rate we’d like to have, this is the variation. And this variation is what is causing the problem I’m talking about. Sometimes the measured frame time is a bit before, sometimes it’s a bit after the actual time.

The perfect amount of game steps to take every frame in this case (60Hz render, 60fps game step) is of course 1. In fact on the console games I’ve shipped, I sometimes just hard-coded one game step per render frame, but on PC’s with wildly varying video modes and video cards, this isn’t viable. The preferred game steps are represented by the blue outlined boxes for each rendered frame. However, using the code above, the actual game steps done per frame is shown by the magenta boxes. This shows that in the first render frame, the game isn’t stepped at all, and the next render frame steps the game twice to make up for it. Then there’s another frame of zero game steps, etc. In other words, very un-smooth behaviour.

Now, how did I fix this? Well, in our game it doesn’t really matter too much if the game step is running at exactly 60 fps, or if it’s running at a slightly higher rate. So, I introduced a fuzz factor:

frametimingafter600_2

The fuzz area is basically a time difference that is ‘acceptable’ when determining how many times to step the simulation. It’s only really used ‘downwards’, so for example if your game step is 10ms, and you get a frame time of 9ms, you might still deem that acceptable, and step the game. If your frame time was 12ms, then the fuzz factor isn’t technically needed, and the game is stepped.

Note that the frame steps are exactly where we want them! Buttery smooth. The game update code now looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
static const float GameTimeStep = 1.0f/60.0f;
static const float FuzzFactor = 0.96f;	

void Game::Update(float dt)
{
	m_timeAccumulator += Util::Clamp(dt, 0.0f, 0.1f);

	while (m_timeAccumulator >= (GameTimeStep * FuzzFactor));
	{
		Step();
		m_timeAccumulator = Util::Max(m_timeAccumulator - GameTimeStep, 0.0f);
	}
}

 
The fuzz factor is set to 0.96, which basically allows the game to speed up from 60Hz to about 62.5Hz.

Since I put in the code above, the occasional stuttering when running in a video mode of 60Hz seems to have disappeared from our game. When running at different frame rates such as 50Hz the game will still ‘catch up’ every once in a while causing a one-frame jitter. This is distracting and not preferable, but I don’t currently know of a way to fix this other than running the simulation at a much higher rate to get more granularity (not really feasible in our case), or by interpolating everything in the renderer (which might introduce frame lag, which is also undesirable).

Anyway, I am happy this problem is no longer an issue, and thought I’d share the idea if you’ve seen problems similar to this. Yay, one step closer to shipping! :)

Alright, that’s it for this week, keep those frames buttery smooth!


As usual, today at 4pm there will be another Dev Stream with Jouste the Drawbarian. Don’t miss it!

VS_DevstreamBanner

 

-Nick

Twitter: Nick: @nickwaanders Jesse: @jouste Caley: @caleycharchuk SlickEntertainment: @SlickEntInc

Facebook: https://www.facebook.com/SlickEntertainmentInc

Twitch: http://www.twitch.tv/slickentertainmentinc

Posted by: Under: Slick Entertainment,Tech Comments: Comments Off on Dev-Blog 225: Frame timing problems

Dev-Blog 223: Networking: Pack those bits!

06/08/2016

devblog_header03

Welcome back, followers of the fearsome!

This week is a follow up to Dev Blog 197, which was the first dev-blog on networking. I’ve been working on getting the networking system up and running for Viking Squad, and there are a ton of little peculiarities I could talk about, but I’ll start with a bit more of the basics, in particular about how to squeeze all the unused bits out of your precious network bandwidth.

After setting up the low level networking system described in Dev Blog 197, we are now able to send and receive messages from remote clients. These messages get bundled up into a network packet and sent, only to be broken into individual messages again when they reach the other side. Now, bandwidth is always a concern, so we want to try and minimize the packet sizes, which means minimizing the size of the message that get sent.

If you’re familiar with C#, you’re probably aware of the BinaryReader and BinaryWriter classes to save and load binary data. These are constructed with a stream, and then you can read and write different data types to these streams.

For example, say we have this hypothetical entity that we need to save to the network. (Note: this isn’t what our internal entity class looks like, this is just an example to illustrate what I am talking about). This is what the code would look like:

class Entity
{
	private UInt16 m_entityID;  // Unique ID to identify the entity by
	private Vector3 m_position; // 3D Position of the entity in the world
	private Vector3 m_velocity; // Velocity of the entity in the world
	private bool m_onGround;    // Boolean saving if this entity is on the ground or not.

	// .. More data here

	public void SaveToNetwork(BinaryWriter writer)
	{
		writer.Write(m_entityID);		// 16

		writer.Write(m_position.X);		// 32
		writer.Write(m_position.Y);		// 32
		writer.Write(m_position.Z);		// 32

		writer.Write(m_velocity.X);		// 32
		writer.Write(m_velocity.Y);		// 32
		writer.Write(m_velocity.Z);		// 32

		writer.Write(m_onGround);		// 8
							// 216 bits total = 27 bytes 
	}

	public void LoadFromNetwork(BinaryReader reader)
	{
		m_entityID = reader.ReadUInt16();
	
		m_position.X = reader.ReadSingle();
		m_position.Y = reader.ReadSingle();
		m_position.Z = reader.ReadSingle();

		m_velocity.X = reader.ReadSingle();
		m_velocity.Y = reader.ReadSingle();
		m_velocity.Z = reader.ReadSingle();

		m_onGround = reader.ReadBoolean();
	}
}

As you can see it needs 27 bytes to save the state to the network. The smallest unit of data that can be written using BinaryReader and BinaryWriter is a byte, which is actually quite large if you think about it. For example, when the SaveToNetwork function writes the m_onGround boolean value, it will write an entire byte (8 bits) to save the state of the boolean. That’s 7 wasted bits to write 1 bit of actual data!

Now, how about we take this one step further? How about saving all values using exactly the amount of bits we think it needs? And in our loading code, we use the same number of bits to read the value and store it in our variable. To make this easy to do, I implemented my own BitStreamReader and BitStreamWriter classes. These have the same functions to read and write data types, except they also require a number of bits, and in some cases a minimum and maximum value. Internally they pack data in bit by bit, making it possible to waste no bits when saving the entity state. If you’re interested in the internals of these streams, just click here to see what the C# code looks like.

To be able to save the maximum amount of space, we need to know what the limits are for each of our variables. The m_entityID is a 16 bit value, but we don’t see it ever going over 1024. In this example, we’ll assume that the X Coordinate is always between -150.0f and 150.0f, and the Y and Z coordinates are always between -6.0f and 6.0f. The velocity is always between -10.0 and 10.0.

Now how do we save this efficiently? Well, lets go through them one by one:

m_entityID: This value will never go over 1024, so we can save this unsigned integer by using only 10 bits.

For m_position, we’ll need to be able to save the floating point values using a specific amount of bits, while retaining a minimum precision. Say we determine we want a precision of about 0.02 units. To be able to save the X coordinate we would need to divide up (150.0 – (-150.0)) = 300.0 into 300.0 / 0.02 = 15000 parts. The nearest larger power of two would be 2^14 = 16384. So we’d need 14 bits to save the float and get a precision of 0.01831. For the Y and Z coordinates we do a similar calculation, and come to the conclusion that we can save using 9 bits, giving us a precision of 0.02343.

For the m_velocity we decide we don’t need as much precision, and we can handle 0.1 unit of precision. This allows us to save the X, Y and Z component using just 8 bits each.

The m_onGround just needs one bit to save, since it’s just a true or false value.

The code would look something like this:

class Entity
{
	private UInt16 m_entityID;  // Unique ID to identify the entity by
	private Vector3 m_position; // 3D Position of the entity in the world
	private Vector3 m_velocity; // Velocity of the entity in the world
	private bool m_onGround;    // Boolean saving if this entity is on the ground or not.

	// .. More data here

	public void SaveToNetwork(BitStreamWriter writer)
	{
		writer.Write(m_entityID, 10);                     // 10

		writer.Write(m_position.X, -150.0f, 150.0f, 14);  // 14
		writer.Write(m_position.Y, -6.0f, 6.0f, 9);       // 9
		writer.Write(m_position.Z, -6.0f, 6.0f, 9);       // 9

		writer.Write(m_velocity.X, -10.0f, 10.0f, 8);     // 8
		writer.Write(m_velocity.Y, -10.0f, 10.0f, 8);     // 8
		writer.Write(m_velocity.Z, -10.0f, 10.0f, 8);     // 8

		writer.Write(m_onGround);                         // 1
		                                                  // 67 bits total = 8.375 = 9 bytes 
	}

	public void LoadFromNetwork(BitStreamReader reader)
	{
		m_entityID = reader.ReadUInt16(10);
	
		m_position.X = reader.ReadSingle(-150.0f, 150.0f, 14);
		m_position.Y = reader.ReadSingle(-6.0f, 6.0f, 9);
		m_position.Z = reader.ReadSingle(-6.0f, 6.0f, 9);

		m_velocity.X = reader.ReadSingle(-10.0f, 10.0f, 8);
		m_velocity.Y = reader.ReadSingle(-10.0f, 10.0f, 8);
		m_velocity.Z = reader.ReadSingle(-10.0f, 10.0f, 8);

		m_onGround = reader.ReadBoolean();
	}
}

Now, what we ended up with is a routine that can save the entity data with the precision we needed, in just 9 bytes. That’s 1/3rd of the original implementation! Of course this is a hypothetical entity, but you can see here that there are huge space savings to be had if we know the constraints of our variables.

Alright, that’s it for this week, I need to get back to more network implementation. Writing this blog post made me realize how many little interesting things I did to make the networked game work better. It’s probably worth another future blog post or two!


As usual, today at 4pm there will be another Dev Stream with Jouste the Drawbarian. Don’t miss it!

VS_DevstreamBanner

 

-Nick

Twitter: Nick: @nickwaanders Jesse: @jouste Caley: @caleycharchuk SlickEntertainment: @SlickEntInc

Facebook: https://www.facebook.com/SlickEntertainmentInc

Twitch: http://www.twitch.tv/slickentertainmentinc

Posted by: Under: Slick Entertainment,Tech Comments: Comments Off on Dev-Blog 223: Networking: Pack those bits!

Dev-Blog 222: Roughing in Those Cinematics!

06/01/2016

devblog_header08

Welcome back followers of the fearsome!

We hope your week has been full of pillage and plunder as Slick Entertainment sails another Dev-Blog to you! This week we’ll be going over some of the ways we are approaching the last bits of polish in viking squad. The Cinematic areas! Now there isn’t too much of a story going on in Viking Squad and that’s on purpose. We found that players (and us included) didn’t really need too much justification for going around with cool weapons and beating up things. This was good news for use because that means that we only need to make a couple moments in our game have some exposition and hopefully the goofy actions in the rest of the game fill in the blanks.

VS_silhouette171

Above is some of our rough cinematic storyboard ideas. these are nice and loose and mixed around a bunch. Ones that feel right  are slammed with some quick colors. and chopped up and thrown right into the editor and can be controlled just like one of our puppets! This means we can add awesome stuff like chromatic aberration, screen-shake, and lighting.

I’ll be the first to admit that being atmospheric and cinematic is NOT one of my stronger skills. I can pump out a lot of content but not all the buckshot hits the target, luckily between the 3 of us here at Slick along with the support of the  skilled folks at Power Up Audio, we can get something pretty cool happening.

The original cinematic sections we built for the trailer were a little hard to handle and not very organized (mostly due to my lack of experience). But now we have some super cool and helpful changes added to the Waanderful Engine!

VS_silhouette172

Above you can see that every different shot in the sequence is under a different bone, by hitting ctrl+shift and selecting that bone it’ll select everything in that shot. This makes it super handy to move shots around and play with their length in order to make them fit better in sections. Keeping the effects and animations properly named and organized is something that is important as well because it’s easy to lose track of what’s going on when the puppets get this out of control.


And don’t forget that we’ll be Dev-Streaming today at 4pm-6pm PST! Come on by as we slam some more art down with our great crew! Ask questions about everything from art and design, to coding! Hope to see you there!

VS_DevstreamBanner


So that’s it for this week! Caley has been getting the final boss experiences implemented and Nicks been working super hard on our Networked multiplayer so everyone can play with each other from around the world! Thanks for dropping by and checking out what we are working on, and until next time, keep those cinematic files organized!

Jesse_avatar64-Jesse

Twitter: Nick: @nickwaanders Jesse: @jouste Caley: @caleycharchuk SlickEntertainment: @SlickEntInc

Facebook: https://www.facebook.com/SlickEntertainmentInc

Twitch: http://www.twitch.tv/slickentertainmentinc

Posted by: Under: Art Work,Slick Entertainment,Vikingsquad Comments: Comments Off on Dev-Blog 222: Roughing in Those Cinematics!

Dev-Blog 220: Cramming in Character and a Duskers shout out!

05/18/2016

devblog_header08

Welcome back followers of the fearsome!

Hope you’ve had a great week! This time we’ll be hopping into the world of viking squad with some of the background characters we’ve been placing through the game.

My strengths have always been in designing goofy characters so for the last bit of polish we are adding some of them to the game.

We started in our first zone, where you hit the ice floes and the dark caves. Below there’s a couple ideas along with one little guy we built on the dev stream! These guys can appear during a difficulty swing to sell you stuff, or just be there in the background offering a new light source to spruce up the levels.

VS_silhouette166

As you get deeper into the caves there are crazy exploding mushrooms and shiny blue crystals. We wanted to show some reasons for the Snowclaw to be in there so we designed up a very crafty looking Snowclaw jeweler! These guys appraise the jewels harvested from the deepest caves and make sure the crystals that are brought back to the den are of the utmost quality.

VS_silhouette165

Adding these characters is a quick and easy way to add some fun to the more sparse areas in our zones. once implemented we’ll have a good idea of what else we’ll need to add to the other more lonely areas, and it also gives us fun and interesting things to work on with our Dev-Stream audience!


We’d also like to give a Viking Squad shout out to our pal Tim Keenan of Misfit Attic for releasing Duskers 1.0 today! Duskers is a super cool, low-fi survival game where you control drones from your ship in a lonely, post disaster space. You explore seemingly empty space ships with your trusty drone pals, upgrade them and try and avoid traps and strange creatures. It’s mysterious, challenging and has a super cool aesthetic. So a big congratulations Tim on your release! And check out his company’s site right here!

VS_silhouette167


And as always! we are back to our regular Viking Squad Dev-Stream programming! Hop on at 4pm PST-6pm PST for some searing hot art tips and fun Drawbarian times! See you there Everybody!

VS_DevstreamBanner


And that’s it for this week! Caley and I are getting the final boss touches ready to go while Nick tackles the massive beast that is Networking. Hope your weeks have been going well and until next time. Keep on Dusking!

Jesse_avatar64-Jesse

Twitter: Nick: @nickwaanders Jesse: @jouste Caley: @caleycharchuk SlickEntertainment: @SlickEntInc

Facebook: https://www.facebook.com/SlickEntertainmentInc

Twitch: http://www.twitch.tv/slickentertainmentinc

 

 

Posted by: Under: Art Work,Slick Entertainment,Vikingsquad Comments: Comments Off on Dev-Blog 220: Cramming in Character and a Duskers shout out!

Follow us!

titlebutton_twitter titlebutton_facebook titlebutton_youtube titlebutton_twitch

Join our mailing list!

/ /

Dev Blog

June 29 2016

Welcome back followers of the fearsome! It’s Caley here this week and I’ve got a fun post on a tool we use to tune the in-game economy of Viking Squad (not the real economy, Nicks making a different tool for that). Game economies, and real ones, are always hard to nail down as you can never fully predict […]