Art Spotlight: Cutscenes, Part I

For the past few weeks, Jack and I have been working on transitioning from the Demo Version to the Final Version of Where Shadows Slumber. One of the finishing touches I’m committed to adding to our demo is a short cutscene that plays when you beat the game. Our fans are always asking us if the game will have some kind of a story. The answer is yes, it absolutely will! But the nature of mobile entertainment and puzzle games in general dictates that we tell a certain kind of story in a certain kind of way.

 

860e6bef748f96c0bfd4d8d5b79626a4

Screenshot from one of Monument Valley’s cutscenes.

Why Cutscenes?

When we decided we wanted the game to have a story, we looked at other successful mobile games (see Monument Valley, above) as well as the games Jack and I usually like to play. It seemed that short cutscenes, placed directly after the player “achieved” something notable, were the best way to hold people’s attention. Jack loves listening to all of the audio books in Diablo 3, and I loved reading entire libraries in games like Morrowind and Skyrim. However, for a casual gamer, massive amounts of text can seem like an information overload. Not to mention, that creates a lot more work for our translator – which translates into a serious cost for us.

It’s also worth mentioning that mobile gamers don’t often play games with the sound on. Clearly, investing our time in fully voice-acted content wouldn’t be worth it. Who would ever hear it? When you think about it, given these constraints, we didn’t have many options.

  1. Mobile gamers can’t hear your game
  2. Casual gamers want a story, but not an epic saga
  3. Mobile gamers play the game in short bursts
  4. The more voice over work and text we have, the more we need to translate

Since the above four points are a given, we decided to have short cutscenes at the beginning and end of every World in our game to serve as end-caps. The action in each of these animated scenes will be completely wordless and textless, and tell a story through body language alone. Sound will be present, but it won’t be important. The cutscenes themselves each tell a unique piece of the story, and may even seem disconnected. This is all by design!

 

3Ds

3DS Max is used to animate the actors, and the file is then interpreted by Unity.

The Technology Being Used

All of the artwork in Where Shadows Slumber is done in a program called Autodesk 3DS Max. I’ve used many studios in my years as an animator, but this was one of the first I ever tried and something about it called me back.

3DS Max is used to create characters (modelling), paint them (texturing), give them bones and animation handles (rigging), and make them move around (animation).

Then, these animations play in real-time within Unity. So when you’re watching a cutscene, you’re really watching the game – not something that was rendered ahead of time as a series of images and played back like a film. It was important to me that we use Unity to its full potential, and always kept players “in the game world”.

 

regret

Within Unity, the actors are given color and lighting.

Process: The Inverted Cone of Cutscenes

When working on a large project like this cutscene, it’s important to work in stages and have clear checkpoints. And make no mistake, even a cutscene that is 1 minute long is a large project! I have spent close to 30 hours on it so far, and I’m not even finished. The problem with stuff like this is that if you want to change something, usually you have to undo or throw out a ton of work. It’s important to make sure that doesn’t happen, and that you start with a wide range of possibilities but eventually focus in on what the cutscene is going to be.

For some insight into how a cutscene begins wide and then narrows to completion, look at this graph:

CutsceneBlog

The further you go down the inverted cone, the more work you lose if you change something.

See the arrow – I am currently at the end stage of Principal Animation. That means the actors all have their general motions and you can tell what’s going on in the scene. But it still isn’t finished! Look at all of the other stuff that has to be done.

The reason things like cloth motion and sound come last is because, should we decide to change some of the Principal Animation, we would have to throw out all of that “detail work” anyway. So it just makes sense to save it for last and only work on it when the work at the top of the cone has been checked and locked.

 

skirt.PNG

The player’s cassock (the white tunic) is animated using 30 individual bones!

Regrets So Far

You don’t work on a game without having some serious regrets. Every regret I have so far regarding this process has to do with time – something I did, did poorly, or did not do, that cost me precious time and made us push our deadlines back.

Giving the character cloth robes: I love robes. I love cloth. But I foolishly decided to give our main character cloth robes that must be painstakingly controlled via spider-leg-like bone tendrils. This process is maddening, takes forever, and never looks good. I regret not using Cloth simulation, something 3DS Max provides and Unity supports.

His dumb hand bones: This is something you would never know from watching the in-game cutscene, but the main character’s hand Bone (an invisible puppet-string object) is stupid, dumb, too big, and I don’t like it. I should have made them smaller. Also I think his left arm bends the wrong way. Let’s just say I ought to re-do his entire rig.

Link To World broke everything: I used a parent-child relationship to allow the characters in the scene to hold objects (i.e. the lantern, the urn, the chest, the scepter, the bowl). This worked perfectly! Except… for some reason, the first time I set up linking on my character’s IK hand setup, it wigged out and sent his hands flying off screen for every single frame of animation I had done previously. This was clearly some kind of offset error, but I never found a good solution. I ended up reanimating his hands halfway through!

People would rather have more levels anyway: The sad truth is, this is a puzzle game. People want puzzles. (“More levels!” – The Proletariat) As much as they may say they want a story, the truth is we’ll get more mileage out of working hard on puzzles instead. It may be that the cutscene is there for a different purpose. My own ego? Winning artsy indie game awards?

Everything mentioned here made me lose time and work on this far longer than I should have, making us weeks (if not months) behind schedule for a demo that was supposed to be done already. Perfect is the enemy of good enough! Live and learn, right? That’s the beauty of working on a demo first. I now know what not to do for the final game! Let’s just hope the damage hasn’t already been done by now.

 

Next Blog Post

By the time I have to write Part 2 of this blog, I should be finished with the cutscene. I can show it to you in full and we’ll do a bit of a postmortem on it. I can give you the short version of the postmortem now: the cutscene is a lot of work, there’s very little payoff (I assume), and the subject matter is controversial. Nevertheless, here’s a sneak peek at it to tide you over until then…

 

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Interested in hearing about the game, now that you’ve peeked behind the scenes? You can find out more about our game at WhereShadowsSlumber.com, find us on Twitter (@GameRevenant), Facebook, itch.io, or Twitch, and feel free to email us directly with any questions or feedback at contact@GameRevenant.com.

Frank DiCola is the founder of Game Revenant and the artist for Where Shadows Slumber.

Mechanic Spotlight: Shaders

Last week I promised I would write a more technical post. So this week, rather than talking about something I do know about, I’ll be talking about something I don’t know anything about, and then you can all tell me how wrong I am! Which brings me to the topic for this week – shaders!

Where Shadows Slumber has a relatively distinct visual style – the bright solid colors, the crisp black shadows, and the sharp line that separates them. Much of the artistic style is due, of course, to Frank’s art. However, a lot of it is also due to the custom shading that we set up.

screen_1920x3412_2017-03-20_22-04-51

Bright colors and sharp edges!

What is a Shader?

Unity describes a shader as a ‘small script that contains the mathematical calculations and algorithms for calculating the color of each pixel rendered, based on the lighting input and the Material configuration’. Basically, shaders determine how the rendering will happen, and how the look of your scene will be affected. Shaders give you a lot more control over exactly how everything will be calculated and rendered – lighting, shadows, gloss, reflections, etc. It’s a lot, and shaders get very complicated very quickly, but they allow you to craft a very distinct visual style.

Shaders are (generally) used by creating a material and specifying what shader that material should use for rendering. This allows you to use a shader for multiple materials, with potentially multiple different configurations.

Now, let me give you a quick disclaimer – I know enough about shaders to put together this one for Where Shadows Slumber, but I am definitely not an expert. So take everything I say with a grain of salt, and if you are an expert on shaders, feel free to let me know, because I’m sure there are some things I could be doing better.

I should also mention that, while I believe you can write CG shaders for some other engines, any specifics in this post will refer to shaders as they are used in Unity. Similarly, since Where Shadows Slumber uses forward rendering, this shader will also will be set up using forward rendering.

 

How real light works, and why that’s bad

Unity comes with something called the standard shader, which lets you get a lot of different visual effects without creating your own shader. It’s very powerful and very useful – so why not use it here?

The problem with the standard shader is that it’s too realistic. It calculates lighting based on the way that lights actually work, which is not what we want. A light in real life fades over distance, so it’s brightest at its center and much darker at the edges. While this is accurate, we want all areas that are in light to be the same brightness. Otherwise, the player would be too bright, but the edges of the light would be too dark.

shadercomparison2

The Unity standard shader (left), and the Where Shadows Slumber shader (right)

Enter our custom shader – in order to get the lighting right, we had to write our own shader, with a custom lighting model. This was a daunting task, but I’ll go through the overall steps we took to get there.

 

Not the most difficult shader

There are two types of shaders in Unity – Surface, and Vertex/Fragment shaders. Surface shaders are a little easier to write and understand, but they give you less control, as they do a lot of the calculations themselves (in reality, a surface shader is just a wrapper that gets compiled down to a vertex/fragment shader). Fortunately, we don’t really need to get too deep into the calculations for lighting and stuff – we’ll just let the surface shader calculate the lighting, and then we’ll use the results to determine what to draw.

So, we know that we have to make a surface shader. What exactly does that mean? How do we actually go in and start changing things? What does a shader really look like?

Drumroll please…

 

Our surface shader

Shader "CrispLightBasic_NoDir" {
  Properties {
    _Color("Color", Color) = (1, 1, 1, 1)
    _MainTex("Albedo (RGB)", 2D) = "white" {}
  }
  SubShader {
    Tags {
      "RenderType" = "Opaque"
    }

    CGPROGRAM
    #pragma surface surf TestForward addshadow fullforwardshadows
    #pragma target 2.0
    fixed4 _Color;
    sampler2D _MainTex;

    struct Input
    {
      float2 uv_MainTex;
    };

    void surf (Input IN, inout SurfaceOutput o)
    {
      fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
      o.Albedo = c.rgb;
    }

    half4 LightingTestForward(SurfaceOutput s, half3 lightDir, half atten)
    {
      half4 c;
      c.rgb = s.Albedo * _LightColor0.rgb * min(floor(300*atten), 1);
      c.a = 1;
      return c;
    }

    ENDCG
  }
  FallBack "Diffuse"
}

This is the simplest shader that we use in Where Shadows Slumber. It’s pretty self-explanatory, so I’ll let you figure it out.

Alright, I guess we can take a look at what’s actually happening here.

Anatomy of a shader

There are a lot of cool parts to a shader; let’s take a look at them from the top down.

  • Shader "CrispLightBasic_NoDir"

    Starting with an easy one! This just means that we’re making a shader, and giving it a name.

  • Properties {
      _Color("Color", Color) = (1, 1, 1, 1)
      _MainTex("Albedo (RGB)", 2D) = "white" {}
    }

    I like to think of the properties as ‘inputs’ to your shader. When you examine a material using your shader in the Unity inspector, these are the values that you will be able to change in order to get a different look.

    shaderproperties

    A material with our shader in Unity

    The line for each property consists of a name, an identifying string (which is what you’ll see in the inspector), a type, and a default value, in order. So our color variable has the name _Color, the description "Color", the type Color, and the default value (1, 1, 1, 1).

    The possible types for a property are Int, Float, Range, Color, Vector, and 2D (which represents a 2-dimensional texture).

  • SubShader {

    This just means that we’re actually starting the real shader block.

  • Tags {
      "RenderType" = "Opaque"
    }

    Tags are a way of telling Unity some stuff about the shader we’re writing. Unlike the properties above, these are constant to the shader. So, for this shader, we are telling Unity that this shader will always have a RenderType of Opaque.

    There are a few different tags you can use, and each of them have a few different options. In the interest of shortness, I won’t go into all of them here.

  • CGPROGRAM
    ...
    ENDCG

    These directives indicate that the actual CG code is contained between them. The CG code is what does the actual shading.

  • #pragma surface surf TestForward addshadow fullforwardshadows
    #pragma target 2.0

    #pragma statements indicate which shader functions to compile into your shader.

    The target pragma indicates the shader compilation target level – higher targets allow the use of more modern GPU functionality, but may prevent the shader from working on older GPUs. 2.0 is pretty low, since we aren’t going to end up doing anything fancy.

    The #pragma surface directive indicates information about our surface shader, and is always of the form:

    #pragma surface surfaceFunction lightModel [optionalparams]

    Thus, our surfaceFunction is surf and our lightModel is TestForward (both of which we will define later). The optionalparams which we provided are addshadow and fullforwardshadows, which allow meshes using our shader to both receive and cast shadows when using forward rendering.

    This concept of ‘optional parameters’ is kind of vague. Basically, it’s just another way to give information about your shader – this time, the information is about how the actual rendering is done. There are a lot of different options that you can put here, and, unfortunately, it’s not incredibly obvious when you might need one. If you’re not doing anything funky with your shader (lights, shadows, depth-testing, etc.), you’re probably fine. If you are, you might want to see if there are any optional params here you should be using.

  • fixed4 _Color;
    sampler2D _MainTex;

    Remember those properties we declared earlier? Those guys are cool and all, but these are the real variables used by the shader. Any of the properties you declared needs a variable (of the correct type) here, so that your shader can actually use the value you provided! In this case, we’re creating a fixed4 variable for our color value, and a sampler2D variable for our main texture. The data types for these variables are kind of strange, so let’s take a look:

    float, half, and fixed – these all represent floating-point numbers, with different precisions. The precisions are (generally) 32, 16, and 11 bits, respectively.

    – float4, half4, and fixed4 – these are 4-dimensional vector versions of the above types. They’re used for vectors (duh), but also for colors, which are of the form (r, g, b, a)

    sampler2D, sampler3D, and samplerCUBE – these sampler types represent textures; 2D is a 2D texture, 3D is a 3D texture, and CUBE is a cubemap.

  • struct Input
    {
      float2 uv_MainTex;
    };

    The Input structure is yet another representation of information passed to the shader, and generally contains texture coordinates. Texture coordinates must be named uv followed by texture name, and indicate positions of pixels on your textures. There are a bunch of other values you can put here, but, once again, I’m not going to list them all.

  • void surf (Input IN, inout SurfaceOutput o)
    {
      fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
      o.Albedo = c.rgb;
    }

    Ah, finally, here we are! We have made our way to the actual surface shading! This is the surface function that we specified in the #pragma surface directive. This function, at its core, describes the properties of a surface. It takes an Input, which we defined above, and a SurfaceOutput, which actually contains those properties (color, normal, emission, etc.). For our very simple shader, we only care about the color, so that’s the only value that we will provide. Note that it’s marked as inout, meaning that it’s both input and output – it comes in, we make changes to it, and then it gets used later, with those changes.

    The inside of this function is the important part, as it’s telling us what the shader will do at any given pixel position. Fortunately, this is a pretty simply one:

    In the first line, we’re calling tex2D, a function which performs a texture lookup. So we’re saying we want the color of _MainTex at the pixel coordinate provided by IN.uv_MainTex. This should make sense – after all, we created IN.uv_MainTex as a way to point to positions within _MainTex, which is exactly what we’re doing. Once we have the pixel color from the texture, we’re multiplying it by our _Color variable, which will result in a ‘tinted’ version of the texture. Finally, we are storing the result in a fixed4 variable, or a 4-dimensional vector of fixed-precision floating-point numbers.

    In the second line, we’re simply assigning the value we just calculated to the Albedo property of the SurfaceOutput variable o. The albedo color of an object is just the color of that object without any external influences (mainly, light). Since we haven’t applied any lighting yet, this is the property we want to set.

    So this function is pretty simple – it just gets the colors from the texture and tints them with the color we provided from the Unity inspector. Note that this function doesn’t return anything – it simply sets values on the SurfaceOutput object, which is used later.

  • half4 LightingTestForward(SurfaceOutput s, half3 lightDir, half atten)
    {
      half4 c;
      c.rgb = s.Albedo * _LightColor0.rgb * min(floor(300*atten), 1);
      c.a = 1;
      return c;
    }

    When we declared our surface shader using the #pragma surface directive above, we also specified a lighting model, which I so cleverly never renamed from TestForward. This function is where we apply our lighting, and it describes how light affects things. In most cases, the surface shader will handle this for you. However, since we want to give our lighting a somewhat special look, we need to mess around in here too.

    This function takes in our SurfaceOutput object (so we can know stuff about our surface), lightDir (a vector indication the direction the light is hitting the surface), and atten (a number indicating the strength of the light at this point). It returns a vector which indicates the color of the surface after the lighting has been applied. This function will run for every pixel on the surface, which allows us to return different values for each pixel.

    Since our shader is pretty simple, the logic in this function is simple as well. We create a vector, c, which we end up returning. We set its rgb values based on the color of the surface (and some other stuff), and set its a (alpha, or transparency) to 1 (completely opaque).

    The interesting part of the lighting model (and the whole shader) is the single line of calculation here, so I’ll go through it step by step.

    • c.rgb – This is the actual color value of the variable c, which is what we want to mess with.
    • s.Albedo –  This is the value we set in our surface function. It’s the actual color of the object at this point.
    • * _LightColor0.rgb – Ah, a piece of magic! We’re multiplying the color by something here, but what? Our lighting function will be called on any pixel once for each light that hits it. These are called passes. In forward rendering, _LightColor0 represents the color of the light that this pass is applying. So, we’re just tinting our surface’s color by the color of the light.
      There are two things to note here. These lighting passes only apply to per-pixel lights. Lighting is expensive, so the Unity quality settings will max out the number of per-pixel lights you can have. In order to create our look, we needed every light to be per-pixel, so we had to increase the cap.
      The other thing is the concept of blending. Since we may have multiple lights hitting the same spot, we’ll have two different color values for that spot. Unity needs to know how to combine them, and the default behavior is additive. This means that overlap between lights will be twice as bright, which may give it a ‘washed-out’ look. I won’t cover it here, but there are ways to change the blending behavior to achieve the look you want.
    • * min(floor(300*atten), 1) – Here’s the interesting part. atten tells you how bright the light is at this point; it gets lower as you move away from the source of the light. A normal lighting model would multiply the color by atten, which would result in a nice fading look. However, we don’t want any values in between 0 and 1. We want the light to be either on or off. So, this funky piece of math basically says ‘if the attenuation is above 0.003, show the whole color. Otherwise, show a shadow’. This is how we disregard the ‘fading’ of the light without disregarding where the light actually reaches.
  • FallBack "Diffuse"

    We started with something simple, and it looks like we’re gonna end that way too. The fallback shader is the shader that should be used if, for whatever reason, our custom shader is unable to be run on the GPU. This could happen if we’re running on older hardware, we specified too high of a shader compilation target level, or we simply made a mistake in the shader code. I find that the latter is almost always the case, as writing shaders correctly is so confusing as to be near-impossible.

    screen_1920x3412_2017-03-21_08-18-43

    The beautiful color of a broken shader!

    Note that the fallback should be inside the shader block, but outside of the subshader block.

Putting it all together

Going through the shader piece by piece took a lot longer than I thought it would, so I won’t go too in-depth here. Most of the shader is boilerplate, so there’s not too much happening anyways.

Basically, we’ve built a surface shader which accepts a texture and a color. We tell that shader that it’s opaque, that it should use shadows, and that it should compile to a very low set of GPU requirements. We also tell it to use a custom surface function to describe the properties of the surface, and a custom lighting model to figure out how light affects that surface. Together, these functions will tell us exactly what color each pixel should be rendered as.

Within the surface function, we simply grab the color from the provided texture, tint it with the provided color, and pass it along. Within the lighting function, we either return the color of the surface, tinted by the color of the light (if the pixel is within the light), or return the color black (if the pixel is in shadow). In this way, everything that is at all touched by light will show up as its full color, and anything in shadow will show up as a crisp, dark black.

Additional resources

Hopefully this adventure into shader-land has given you an idea of how shaders work, and what it was like to work with them. Like I said, I’m not a shader expert, so there may be some stuff you still want to know about shaders. Here are a few links that helped me out in my travels:

There are probably a hundred other pages I ended up reading on my quest for shader mastery, but I can’t find/remember all of them now. Anyways, sorry for going on about shaders for a metric year. I hope you learned a bit about the mysterious world of shaders, and if not, I just hope you didn’t die of boredom. Either way, if you got to this part of the post, well done!

As always, let us know if you have any questions or comments about shaders (or anything else)! You can always find out more about our game at WhereShadowsSlumber.com, find us on Twitter (@GameRevenant), Facebook, itch.io, or Twitch, and feel free to email us directly with any questions or feedback at contact@GameRevenant.com.

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Jack Kelly is the head developer and designer for Where Shadows Slumber.

Where Shadows Slumber at PAX!

The Where Shadows Slumber team has just returned from our biggest event yet. That’s right, this past weekend was PAX East! If you’re just starting to read this blog because you found out about us at PAX, then welcome!

PAx2

An awesome sign for an awesome show

For those who don’t know the details, we were accepted for the PAX East Indie Showcase, which showcases the “best indie [mobile] games you’ve never heard of”. As Frank mentioned when we first found out, we were totally honored to have been chosen, and the showcase really delivered. It was a wild weekend, and I’m here to tell you all about it!

 

What Happened?

We got to the convention center early on Friday morning, and it totally blew away our expectations. Despite knowing the scale of the event, it didn’t really hit us just how big it was, and that was just the main Expo Hall. We set up at our table, and before we knew it, PAX East had begun!

PAX3

Even this shot doesn’t do justice to the size of the hall

We spent the next eight hours showing off Where Shadows Slumber, talking to hundreds of people about the game, getting a ton of feedback, and completely losing our voices in the process. We’ve done this a lot in the past, but it’s always very refreshing to see new people playing our game. It just feels great meeting people and getting our game in their hands.

Once the main expo floor closed at 6 pm, we took some time to catch our breaths – but before we knew it, we were informed that the members of the Indie Showcase were going to be putting on a panel!

Despite all of the awesome things that happened this weekend, I think the panel was my favorite part. Since I do game development as a side project to my actual job, and I haven’t made any money from it, I never really consider myself to be an ‘expert’ of any sort. It was incredibly validating to have people seeking my advice, and I was surprised to find that I had good answers for (most of) their questions. It’s almost as though I’ve been working on indie games for the past three years or something.

After a passable Boston meal (what’s with all the seafood?) and an almost-full night’s sleep, we were back and ready for more! Saturday is always the busiest day at these conventions, and PAX did not disappoint. From the opening at 10 to the closing at 6, we consistently had a full booth, which was awesome. Fortunately, we didn’t have any obligations on Saturday night, so we hung out with some friends before heading back to the hotel early, in preparation for daylight savings time.

We had been taking Uber to the convention center on Friday and Saturday, but since we were leaving on Sunday, we decided to drive in from the hotel. Apparently, a lot of other people had the same idea, and Frank ended up sitting in traffic for over an hour; I ditched him and walked the last mile, and I was still late.

Despite the inauspicious start, Sunday was a great day too. One of the biggest problems with these shows is that we’re at this awesome event, but we spend the whole time at our own booth. It’s great telling people about Where Shadows Slumber, but it’s nice to see some other stuff. Fortunately, our web developer, Caroline, worked the booth with us for two hours or so, so Frank and I took turns exploring the expo floor. There were a lot of awesome games, and I still wish we had had time to see more of them!

After a great three days, we packed up and headed home! The weekend was incredible, and it felt so good to share it with our fellow indie game developers and show off Where Shadows Slumber.

 

What Did We Learn?

The main thing we learned from this show was that, while people may say less is more, in reality, more is more. This was the biggest PAX East ever, and it was definitely the biggest show we’ve ever been to. To be honest, we really weren’t ready for the scale. We brought five test devices and no power strip, which led to some battery problems toward the end of the day.

PAX1

With only five devices, we often had people watching and waiting for their turn!

The devices and the batteries weren’t the only things we didn’t have enough of. We brought 400 drop cards and 300 Where Shadows Slumber buttons, but we didn’t bring nearly enough. We only had a few business cards left when Sunday started, and we were out of buttons halfway through the day. If we had to do it again, I would make sure we brought a lot more – it’s better to have some left over than to leave anyone empty-handed.

Other than that, the other lessons were things we’ve learned before, but they’re still worth mentioning:

  • Bring hundreds of cough drops – continuously talking to people over the ambient sound of a convention for eight hours a day is a real strain on the voice. I went through almost two bags this weekend.
  • Don’t expect to get anything done – for some reason, I always assume I’ll be able to do some work after the convention ends for the day. Between finding food, getting back to the hotel, and planning for the next day, there’s never time for anything else.
  • Daylight savings time is the worst – yeah, it started this past weekend. Sleep is the most valuable commodity at a convention, and it seems totally unfair that we had to lose an hour of it.
  • Plan ahead as much as possible – we had a lot of trouble finding food on Saturday night, because every restaurant in the area was completely booked. Frank has mentioned it before, but I want to mention it again – plan ahead!

 

_Extra

What’s Next?

I definitely consider PAX East to have been a success, which is a good thing – it’s probably the last big event we’ll be doing for a while. Everyone really seems to enjoy our demo, but they also want the full game, and that means that we have to actually make it! So, the next thing on our schedule is to simply get to work and start putting Where Shadows Slumber together. There are really four big things going on in the immediate future:

  • Cutscene – The final step in creating the demo is to give you all a taste of the storyline. Every show we go to, people ask about the game’s story. As of yet, the demo does not contain any discernible storyline, but Frank is working hard to change that. We’re planning on adding a short cutscene to the end of the demo, which will server as a little teaser for the kind of story you can expect to see in the full game.
  • Testing – Over the last two months, we have designed all of the levels for the final game. However, we don’t know if the players will like our levels, and the best way to find out is to ask them! So, we’re going to be creating very basic versions of the levels we have planned, and send them out to our dedicated volunteer testers to tell us what they think! If you want to sign up to be a tester, simply let us know – you can email us at contact@gamerevenant.com, or send a private message with your email to the official Game Revenant Facebook Page.
  • Art – One of the most important parts of Where Shadows Slumber, I must begrudgingly admit, is the art. As such, we are going to be putting a whole lot of work into the art for the final game! The levels we send out to our testers will not have any art on them, since that’s the part that takes the longest. Once we know that the design of a level is pretty good, we’ll start putting some beauty onto it!
  • Refactoring – This is kind of boring to you non-technology folks, but it’s still important. As projects advance, a lot of technical debt and scope changes cause codebases to become a little unwieldy. Right now, Where Shadows Slumber is a house carefully constructed out of sticks; it’ll stay up as long as we don’t blow too hard. So, in the coming months, I’ll be working hard to redesign the code into a strong mansion of stone (or whatever mansions are built out of) that will serve for a full game.

Aside from these main four tasks, we will of course be updating this blog and trying to keep up on social media. We might also swing by a few smaller shows, but we don’t have any plans bigger than that for the next few months.

A few weeks ago, a fan of the game requested that my next blog post touch on the technical side of our process. As much as I wanted to do that this week, we really felt the need to talk about PAX – it was an awesome whirlwind of an experience, and we wanted you to know all about it! But fear not; I’ll be back again next week with a deep dive on one of the most important and most technical parts of Where Shadows Slumber – the shaders.

 

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Were you at PAX East 2017? Tell us about your experience in the comments below! You can find out more about our game at WhereShadowsSlumber.com, find us on Twitter (@GameRevenant), Facebook, itch.io, or Twitch, and feel free to email us directly with any questions or feedback at contact@GameRevenant.com.

Jack Kelly is the head developer and designer for Where Shadows Slumber.

3 Things I Learned at GDC 2017

I’ve just returned from a whirlwind trip to this year’s Game Developers Conference (GDC), and I have a lot to tell you! Unfortunately, most of what I learned is top secret. You hear a lot at these conventions, so between secret news and talks with undisclosed mobile publishers there isn’t a lot I can disclose. More on that later this year…

But I can certainly reveal my impressions as a first-timer to help you out if you’re planning on going to GDC 2018. Here are three things I learned my first time at GDC!


 

Calendar with pushpins

Lesson 1: Schedule Meetings Months Ahead of Time

My number one priority at GDC 2017 was to talk to someone from the App Store about Where Shadows Slumber. My number two priority was to talk to someone from Google Play. Specifically, I’m looking for the people that make promotions and “features” happen. Being featured on an app marketplace can sometimes be the difference between relative obscurity and worldwide fame. It’s that important.

Certainly it can’t be your only strategy, but it’s at the top of my list. Sadly, I failed! Since I was so late to the game (I only found out about GDC when two people mentioned it at MAGFest 2017 earlier this year) I never scheduled times to meet with them. Naively, I assumed there would be some kind of Apple booth and I could meet them there.

No way. Although the major players (PlayStation, Oculus, Facebook, Microsoft, Unity) had large presences at the show, Apple did not have a booth. They probably assume they would just get inundated by indies and it wouldn’t be worth the expense. If you wanted to talk to them, you had to get on their calendar months in advance. They met with business partners in secret rooms during the show, protected under heavy guard. The same is true for Google – they had a booth, but it was specifically to show off Daydream, their mobile VR peripheral. The Google Play team was nowhere to be found.

I learned the hard way – don’t make my mistake! It’s crucial that you do your homework ahead of time and get on the calendar of a major player like Apple, Google, Nintendo, or whoever you want to meet. Don’t leave this stuff to chance!

 

20170303_101342

GDC talk about Chinese localization pitfalls, given by Jung-Sheng Lin of Taiwan.

 

Lesson 2: The Talks Are Great, But You’ll Get Tossed Out

I went to GDC primarily to make connections in the industry. I wasn’t expecting to enjoy the seminars as much as I did. It turns out there are a lot of talks, panels and seminars at GDC and they run the full week. (I arrived on Wednesday, since I was mostly concerned with the Expo – but there are talks and parties beginning on Sunday) The lectures were great! I enjoyed pretty much every one that I went to. The panels weren’t as interesting as the talks because less work went into preparing them. But overall, I was impressed.

One thing bugged me though. I should have seen this coming, but when you buy a pass for GDC you’re effectively selecting what access you’ll have during the show. They have all kinds of “tracks” – Art, Music, VR, All Access, Mega Golden God Status, etc. I got an Expo Pass, which is the cheapest option. This lets you into the Expo and a small smattering of talks.

What this meant was that often I would see a talk advertised (“Nintendo Reveals All About Breath of the Wild!”) and get really excited for it only to be turned away at the door. The paper pocket guide doesn’t warn you about the access required for a talk, it just says where the talk is and who is giving it. To see a filtered view, you need the app. Once I filtered the talks available by the Expo Pass using the GDC app, it become clear that there really wasn’t too much I was interested in. Fortunately I snuck into at least one restricted talk (it was about early access and Ark) and the talks I was able to get into were pretty good. Still, it’s a bad feeling.

So, again, plan ahead! Before you buy a badge, look at the talks available. Filter the list. Ask yourself – are the seminars worth the price jump from $299 to $999? If so, take the plunge. You’ll appreciate getting the access. Otherwise, just deal with the consequences and don’t be surprised when ushers show you the door.

 

20170307_134433

Lesson 3: Don’t Take No For An Answer

The theme of the first two Lessons is quite clear: plan ahead. Having said that, I should also mention that just because you didn’t plan ahead doesn’t mean you shouldn’t muscle your way in anyway.

Rules only matter if they’re enforced, right? Once they stop being enforced they might as well not even apply. Although I don’t believe this is true when it comes to objective morality (don’t go burning down houses because you think you’ll get away with it), it certainly works when it comes to event admissions.

For example, I went to the Big Indie Pitch at GDC 2017 after some urging by Craig Barnes (I owe you one, man!). This is a pitching contest where you show your mobile game to publishers and industry professionals. You get 4 minutes with 5 different groups each, and they judge your game based on its aesthetics, mechanics, marketability, and overall quality. But I never formally applied for the contest because I missed the submission cut-off by one day. Feeling dejected, I almost didn’t even attend! It was 3 pm on a Thursday, I was already exhausted, the event wasn’t close to the convention center, and I very nearly bailed to go to other events instead.

Something told me I’d regret it if I didn’t at least show up, so I took an Uber over. As the event began, I begged the event coordinator Simon Drake of Steel Media to put me on a Waitlist. If people didn’t show up, I could take their slot! There were four others like me so Simon agreed, and to our surprise the Waitlisters were given a chance at the tail end of the contest to make our case to the judges. (OK, this isn’t really “muscling”, more like “pleading”… but you get the point!)

To my utter shock, Where Shadows Slumber received third place at the Big Indie Pitch! Jack and I now have $1,000 in marketing money to use on any of Steel Media’s owned platforms, and we’ll put it to good use. Another awesome thing: the second place winner, Louard of Suzy Cube, was also on the Waitlist! The moral of the story? Plan ahead, and plan for everything.

Then, expect your plans to go wrong, and don’t give up when they do!

 


 

I’m going back to GDC next year for sure. We may exhibit at the show, or just walk the show floor. I definitely want Jack to see this, because it’s an awesome experience. Where Shadows Slumber will hopefully be commercially available by GDC 2018 so the timing should be perfect… but you know what they say about plans.

 

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Were you at GDC 2017? Tell us about your experience in the comments below! You can find out more about our game at WhereShadowsSlumber.com, find us on Twitter (@GameRevenant), Facebook, itch.io, or Twitch, and feel free to email us directly with any questions or feedback at contact@GameRevenant.com.

Frank DiCola is the founder of Game Revenant and the artist for Where Shadows Slumber.