Tuesday, November 27, 2018

A Quick Update

Hey all,

I know I've been gone for a bit, and yeah, that's my bad.
I know this post should have been a top ten list, but it's taking a bit longer than I expected, and I wanted to post this short update in the meantime!

Basically, two things:
  • A Sound Plan will launch on 4/30/2019.
    Yes. Finally. Your eyes aren't messing with you, Studio Kumiho will be releasing something.
    Check it.(Please wishlist us, your support means everything!)
  • Chang-e's development has taken off like a rocket, and I'm doing all I can to keep up! I'm so excited to show you all! Summer maybe?
Studio Kumiho has been really busy, we're up to 6 staffers now, and I think we're an incredibly talented group. I honestly believe this team is gonna make something amazing, keep an eye out here, and on our website, or Twitter!

Now, back to making games.
I love what I do.
I hope you're in a similar place in life, genuinely.

Jimmy

Thursday, September 20, 2018

A Dangerous Precedent

Hey all,

So, I was watching a friend of mine (also a game designer) play The Legend of Zelda: Ocarina of Time, and he had various... complaints. Complaints that I thought were not... accurate.

He was complaining about how the game wasn't telling him how to solve the puzzles, where to go exactly, what room to be in, even to the point that the camera wasn't accentuating certain waypoints enough.

One token example, he was stuck in Dodongo's Cavern, unaware that he needed to drop bombs into the eyes of the giant Dodongo skull, despite there being a sign cryptically saying that the Giant Dodongo needed to see red to open the path, and there being holes in the bridge directly above the eyeballs, and the camera looking down (admittedly slowly) when the player walks near said holes. He had just acquired the bombs, the dungeon treasure, and had seen that the bombs explode in a red cloud.

The game was giving him the pieces, but didn't tell him EXACTLY what to do; the game led him to the location, but didn't tell him the solution, you know, a puzzle.

I still enjoy this dungeon.

So after talking to him about these complaints thoroughly, I came to a conclusion that a lot of younger designers fall for a particular design paradigm. The paradigm that I'm talking about, to avoid being vague, is...

"The player must know everything" or "The player must be told everything".

Modern video games have a tendency to overexplain and overcompensate in detailing scenarios and puzzles, in an effort to maintain the game's flow and minimize the player's boredom.

I disagree with this style of design, for many reasons, but primarily it goes against one of my game design rules:

Exercise the Brain: Learning is fun!

Players do not like to be talked down to, especially in a puzzle situation. How many times do you remember when people made fun of Fi from The Legend of Zelda: Skyward Sword? Getting all of the puzzle solutions and directions really killed the mood, at least for me, and a large portion of the internet.

"Master, a playtest in Japan shows that you have a 46% chance to solve this puzzle that you just saw on your own, so let me tell you the answer."

Disclaimer: I don't hate Skyward Sword, I just think there are some dumb things about it.

Why do I think that learning is fun? Good question. To me, I like to explain the fun of learning in this way: Remember the first day of school or work? Everything was new, including the trip there, and it certainly wasn't boring, now was it? That's because the human brain is good at consuming new information, in fact, it loves it! Learning new mechanics, learning about new countries or regions, or even learning about the trip to work, to your brain, it's all interesting, because it is LEARNING. Now, what about the 100th day of school or work? You need to find distractions away from your trip, because you know everything already, your brain doesn't want to waste precious energy on seeing the same stuff. Heck, you can probably do your trip without looking!

That's called "grokking", by the way. Also, that's why backtracking tends to not be fun.

For more details about this, I highly recommend reading Raph Koster's "A Theory of Fun for Game Design", it's a fast read and full of information.

Anyway, players like new information, and being told everything about a game, puzzle, etc. is the antithesis to that.

The goal should be to give the player just enough information, and then GUIDE them towards the solution.

A great example? Super Metroid. Remember the door that looked ominous and you couldn't get through without the High Jump Boots, well, without bomb jumping? That searing memory that you KNEW you needed something to help you through there? That was the hand of the designer leading you, not TELLING you!

Gunpei Yokoi will be missed.

Imagine how different this moment would have been if the game told you that you needed the boots here, or once you got the boots, told you to come right back here? Getting through would not have felt as good, now, would it?

You didn't know everything, and that was fine!

It's okay to not know everything about a game, in fact, I recommend it. But what things SHOULD the player know? In my opinion:

The player should know just enough to know what can be done, and enough to infer what needs to be done.

Great examples include:
  • Super Metroid
  • The Legend of Zelda: Ocarina of Time: Dodongo's Cavern bomb puzzle
  • The Legend of Zelda: Ocarina of Time: Forest Temple's painting puzzle
  • Catherine
  • Dark Souls 
A bad example would include:
  • Dr. Jekyll and Mr. Hyde
If I had to summarize this post, it's that treating your players like they have no memory, nor awareness, is not fun, for you nor the player. Leave a little mystery in there, players will love you for it.

Anyway, it took me forever to write this post, and for that I'm sorry. I've been busy handling Studio Kumiho stuff, you can check the website here. We have some exciting developments coming up, and I'm excited to share it with you all.

Next post will be another design focused one, and it's in everyone's favorite format: a top 10 list! /sarcasm

Thanks,
Jimmy

Sunday, August 12, 2018

Whoops

Hey all,

So... I have some explaining to do, but I swear it's all cool stuff!

First off, Studio Kumiho is real! Visit our website here: https://www.studiokumiho.com/

Second, Studio Kumiho has been working with another developer on a project, but that's all I can say at this time. I will post here as soon as that project is announced.

Third, A Sound Plan is on break for about a month or two while we lick our wounds after being rejected from the Seattle Indie Expo for a second time. This feeling hurts a lot still, but I will recover from this and do better in the future.

Lastly, Chang-e is well on its way, hoping to have something to show by the end of the year. Until then, enjoy this:



That is all. I'll post a more substantial update someday soon.
Jimmy

Sunday, March 18, 2018

Game Engine Design 101: Modularity

Hey all,

As promised, this month's (Quarter's? I don't know.) article will be another Game Engine Design 101. This time, we will be going over the topic of modularity.

This topic is a bit "in the weeds", and if you're not familiar with some of the topics discussed here, feel free to comment on this article.

How can you make sure that your engine can be ported to multiple environments / systems? You could use multiplatform libraries, but what if that library isn't compatible with a platform that you would like to port to?

What would we like to do?
  • Separate out the platform specific code (ex. OpenGL) from the core engine code, to keep the engine code small.
  • Maximize modularity.
This is where inheritance is actually useful.

SIDE NOTE: In general, favor composition over inheritance, consider which objects in your engine are a "has a" relationship versus an "is a" relationship. Example: A car IS A vehicle, a car HAS passengers.

The code examples from JFramework I'll be using are here:
The general idea is to create a layer of abstraction away from the actual platform specific implementation of libraries, i.e. abstract calls to OpenGL away from the core of the engine.

GraphicsManager HAS A Screen to render to, but if you look at the implementation of Screen, it has the most barebones implementation, in fact, there are no calls to OpenGL at all! Also, you can't even make a Screen in its own right, because it's an abstract class! The lines from Screen.h shown below are why it's an abstract class.

virtual void            ResetObjectTexture(Surface* aSurface, TextureData* aOldData, TextureData* aNewData) = 0;
virtual void            ResetObjectShader(Surface* aSurface, ShaderData* aOldData, ShaderData* aNewData) = 0;
virtual void            SetClearColor(Vector4 const &aClearColor) = 0;
virtual void            ChangeSize(int aW, int aH, bool aFullScreen) = 0;
virtual void            PreDraw() = 0;
virtual void            Draw(std::vector<Surface*> const &aObjects, std::vector<Surface*> const &aUIObjects, std::set<Camera*> const &aCameras) = 0;
virtual void            DebugDraw(std::vector<Surface*> const &aObjects) = 0; 
virtual void            SwapBuffers() = 0;

By doing the above, we're telling the reader / compiler: "You need to derive from this class, and implement these methods, all Screens need to have these implemented." Whenever a derived class calls one of these methods, the derived version will ALWAYS be called.

From there, we make a PCShaderScreen class, which derives from Screen. This class will implement the actual drawing to the screen via OpenGL. Displaying the code would be too much so just check PCShaderScreen.cpp. In this type of relationship, a PCShaderScreen IS A type of Screen, thus we use inheritance.

And now, the final piece of the puzzle: When GraphicsManager creates a Screen to display to, assuming we're on PC, it will create our PCShaderScreen:


GraphicsManager::GraphicsManager(GameApp *aApp, int aWidth, int aHeight, bool aFullScreen) : Manager(aApp, "GraphicsManager", GraphicsManager::sUID),
                                                                           mSurfaces(), mUIElements(), mTextures(), mShaders(), mCameras(),
                                                                           mScreen(nullptr), mPrimaryCamera(nullptr)
{
  // Add Default Texture
  AddTexturePairing(DEFAULT_TEXTURE_NAME, new TextureData(DEFAULT_TEXTURE_NAME, -1, 0, 0, "", "", Vector4(), Vector4(), 0, 0));
#ifdef SHADER_COMPATIBLE
  mScreen = new PCShaderScreen(this, aWidth, aHeight, aFullScreen);
#else
  assert(!"Needs screen for this device.");
#endif
}

And now any calls to Screen will call the derived version from PCShaderScreen, which will make direct calls to OpenGL.

NOTE:  The SHADER_COMPATIBLE macro is defined from the compiler, you can look up ways to do that, it's not hard.

So, what have we done?
  • We separated the platform-specific implementation (PCShaderScreen) away from the core of the engine. (GraphicsManager)
  • We used inheritance to extend a class (Screen) to be able to have a platform specific implementation (PCShaderScreen)
What advantages does this bring?
  • When we move to a new platform, we can just not include our PCShaderScreen code, implement a new Screen for the platform, and move on.
  • The code in GraphicsManager stays the same no matter the platform, and stays relatively small.
There, now our code is more modular, easy!
There are other cases that you can use this for, but graphics is the best example, relative to JFramework.

Note: I used hilite.me to render the code.