Wednesday, March 04, 2015

The Shifty, Twisty Forest

Wow, that forest is just the shiftiest!
Todd and I spent the past few days putting together a game prototype: check it out! The Shifty, Twisty Forest is a story, err... ...game, about a turtle finding his way through a forest - a very blocky forest with locked yellow doors. Help him get to his destination by shifting the forest around!

We created 12 levels to explore the concept and to see whether it's fun. After you've had a chance to play through it, let us know what you think! Does this game deserve more levels, better art, and a real story line (unlike the stream-of-consciousness that caused the confusing backdrop)? Or should we leave the poor forest alone and not make it twistier and shiftier?

Here's another screenshot in case you haven't time to spend on such frivolity but like to look at things and stuff.

Monday, November 24, 2014

Rescue Ecotopia!

Have you ever wondered what would happen if someone removed almost all of the fish out of a lake?
Hacker, Buzz, and Delete carelessly pollute Ecotopia...
CHAOS. First, storks would eat up the very last few, just to survive, and then fly away to find a better lake. Then, the poor crocodiles wouldn't be able to find anything to eat in the lake with all the fish and storks gone. They'd wander into the forest and mangrove, munching on anything they could find! They might just eat all of the mudskippers flopping through the mangrove, which would terribly upset the mangrove goannas, having their snack taken away. Once there are no more mudskippers, both the crocodiles and the goannas would have to leave, and soon 5 species are gone, just because someone removed some fish! Who would do that!?!
The lake needs another crocodile. Because crocodiles rock.
Find out in our latest HTML5 game for Cyberchase - Rescue Ecotopia! This systems-thinking game was designed in collaboration with the awesome team at WNET. It was great fun making it; we hope you enjoy playing it!

Monday, July 14, 2014

New Dinosaur Train Game on PBS Kids!

The first decision in the game is a tough one.
Todd and I have been thoroughly immersed in the Cretaceous for the past few months, but we've traveled back to the future to share all that we've learned! Foremost, we're excited to share our field notes via our new game Station Race. (We scrawl field notes on our computers using JavaScript and inexplicably they show up as a game on the Internet somewhere.)

Station Race is a fun avoidance game that's fully playable on your computer or on your favorite mobile device. After a few rounds, you'll learn all about Deinonychus, Spinosaurus, and how to build railroad tracks across the Cretaceous landscape. Tap and trace your way from one station to the next as quickly as possible to pick up all the dinosaurs!

Lakes, boulders, trees, and sauropods: prehistoric track-building is hazardous.
Although the journey was rough, and the natives gigantic, Todd and I are now resident experts regarding many dinosaurs, and -- most importantly -- I am now proficient at naming each member of my children's toy dinosaur collection without reading the labels on the bottom.

We had a fantastic time working with both PBS Kids and Dinosaur Train on this project, and we hope you and your children enjoy the game and learn something new along the way!

Thursday, January 23, 2014

How I Taught a Dinosaur to Row a Boat

Go Buddy go! Do what I programmed you to do!
Each project we do presents new challenges. In the case of Dinosaur Train's River Run the new challenge for me was creating an AI for an action/racing game opponent. If you haven't played the game already (which you should, it'll help all of this make more sense), the game has two characters rafting down a river trying to collect bugs that appear along the way. The character that collects the most bugs by the end of the river wins. In two-player both of the these characters are controlled by players, but in single-player the AI handles the extra player. The goal then for my AI was to create a life-like, fun opponent to fill in when a human opponent wasn't available. To do this I broke the problem down into two pieces: river navigation (getting the character from one end of the river to the other) and bug collection (finding and navigating to bugs).

River Navigation

The river in River Run has a few characteristics that played into the river navigation problem. First, the river is not the same every game. The river is composed of pieces that are swapped in and out randomly with each race. This means that a static 'best path' cannot be created for the AI player. The AI must chart its path dynamically.
Second, the river contains solid obstacles that must be traversed around to progress. The AI is expected to be able to reliably navigate around these obstacles and make it down river. Third, the camera dictates the pace at which players can progress down the river, so the rafter AI must maintain a pace that matches that of the camera.

We did not have a discrete solution for each of these problems, rather these problems were overcome by the combination of solutions which I'll outline below.
A couple examples of node placement in river sections.
The first step in creating the AI for navigating the river was to discern a means of expressing the shape of the river so the AI could navigate it. In this case the AI doesn't need to have a complete knowledge of the river since we don't need the AI to be able to navigate to any point in the river, only those points that are necessary to traverse it in a single direction (bottom to top in our case). We chose to represent the river as a series of nodes. These nodes would serve as locations along the river path which the rafter would traverse to. By representing the river as unconnected nodes, we can reorder our level pieces without concern for links between nodes.

The actual traversal AI for the character is relatively simple. Since we want the character to move naturally we restricted its movement method to using paddle strokes like the player. Internally it is 'pressing buttons' just like the player. The AI does a search every few ticks for a target (this scanning process we'll talk about in a second). When the AI finds a target it will begin to paddle straight toward it. To make the AI paddle toward the target it determines where the target is relative to the front of the raft (to the left or right) and paddles on the opposite side. This produces a natural looking motion with the AI alternating paddles to keep its nose pointed at the target when it's target is in front of it or paddling repeatedly on the same side to turn toward a target that is beside or behind it.
The valid nodes are those above the player (the orange line) and in the middle of the screen (between the black lines).
The traversal AI is simple but it is assisted by how the targets are chosen. To find a river node to paddle toward the AI searches the list of river nodes. This search is limited to nodes that have a y-position less than the character's y (meaning they are above it on the map) and nodes that are in the middle of the current game view. With these limitations in place, the search then chooses the closest node as it's new target. If it finds a target better than the current target it replaces it. Otherwise it continues pursuing the current target.
An example of 'most-likely' paths through river sections based on the node locations.
This method of selecting nodes does a few things for us. First, it makes sure the character is only traveling down river since they won't target nodes behind them. This means that our unconnected nodes now behave more like a directed graph with paths weighted based on how close they are to the previous node. Second, by only selecting nodes that are in the center of the screen we ensure that the AI keeps pace with the screen. Finally, because the AI continually pursues a target node even after it reaches it, the traversal AI causes the character to paddle in circles around its target node once it reaches it. This behavior was not intentionally created, but it gives the AI character a pleasant looking idle behavior and gives the player the feeling that the AI is actively searching for bugs.
An example of a level layout we'd avoid. Since the AI always wants to go up a u-shape like this will snare the AI.
Because there is no course correction in the traversal code, the river layout and node layout are both critical for the AI to make it down river. The river layout must be considerate of the abilities of the AI. A key terrain concern was avoiding creating concave terrain that the character can get caught in. Since the AI only attempts to move up, a concave shape that requires the AI to reverse direction to escape would trap the AI.
An example of ill-placed nodes. The left node is closer to the character, but the path to it is blocked by terrain.
Node placement can create similar problems for the AI. Since the AI tries to travel in a straight line between nodes and always chooses the closest valid node, placing nodes so that there is a clear path between close node pairs is necessary. Placing nodes such that the closest node is unreachable could trap the AI.

Bug Catching

Bug catching reuses much of the functionality of the river navigation system with small changes.
An illustration of bug scanning. Bugs inside the white ring are close enough to be considered.
The search for bugs occurs immediately before the search for river nodes. If a chasable bug is found, the AI will give chasing the bug precedence over traversing the river. Finding a chasable bug involves a distance search around the character. The selected bug will be the closest on-screen bug within a given range. If no bugs are found within the range, no bug is selected. When a bug is selected the traversal code used for node navigation is used to navigate the character to the bug. Thankfully this code works well with moving targets too. One change we made was increasing the paddling speed when chasing a bug. This has the benefit of decreasing the turning radius of the character so they are more likely to catch the bug and also gives the impression that the AI character is excited about catching the bug.
As the AI collides with terrain the scan ring shrinks until the problem bug lies outside the ring.
Because, unlike river nodes, bug locations are not static and the search for a chasable bug does not include a check for obstacles between the character and the bug, the situation in which the AI attempts to reach an inaccessible bug is likely. Solving this 'properly' would probably involve implementing a new mechanism for mapping the river and something akin to A*, but, well, we're game developers and sometimes the easy solution is good enough. So, our solution to this problem was to alter the search distance used when finding a 'chasable bug' when a search seems to be going wrong. Each time the character collides with the terrain the bug search distance decreases. If the character repeatedly collides against the terrain, the distance value will eventually shrink to the point that the sought bug will no longer be within chasable range and the AI will 'forget' about it and move on to navigating the river. Once the AI stops colliding with terrain the bug search range slowly grows back to its original size. While this 'bumping into terrain' behavior looks silly when it happens, it happens rarely enough that it isn't distracting and it's a graceful solution to a complex problem.

A Gentle Shove

The final system that assists our AI was actually originally created for human players. When testing the game with human players we found that players wandering off-screen was a significant problem, so we put into place a buffer on the top and bottom of the screen that would push players on-screen. This buffer pushed them vertically toward the center of the screen and horizontally toward the closest river node. This ensures that players pushed off-screen by a piece of terrain will be dislodged by a horizontal push and then pushed vertically back on screen. This ended up working out well for human players and also we discovered offered a fail-safe solution to when the AI got stuck too. While it rarely happens it's nice to have a little insurance in case everything else goes wrong.

Conclusion

This concludes this quick overview of how the rafting AI in River Run works. Hopefully you enjoyed it. If you want to see the AI in action to see the strengths and weaknesses of our solution, you can check it out here. If you have any questions, feel free to leave a comment we'll do our best to answer. Thanks for reading!

Friday, January 17, 2014

Dinosaur Train Goes Mobile!

One thing I love about working on web games is that you get to write lots of blog posts about how you've just finished something because web games tend to a have a pretty quick turn-around compared to the console games I used to work on. So, today, it's my pleasure to write another one!

We've had the pleasure, over the last 6 months, to work with the PBS Kids and Jim Henson folks on several titles related to the Dinosaur Train property. They're moving into the HTML5 realm and we got to be a small part of that and learned a lot about dinosaurs and time-traveling trains along the way.

There were several parts to the project, so here's a breakdown:

I wish the river rafting trips I went on had whirlpools like that!
  • River Run - The newest Dinosaur Train game. This one is based on the latest season of Dinosaur Train in which the Dinosaurs go on various adventures at Adventure Camp. In River Run players join Don and Buddy as they paddle down river in search of bugs for Don's collection. Player's can play single or multiplayer taking on the role of Don or Buddy competing to see who can find the most bugs. I'll probably put up another post talking more about this game, but until then, you can try it out here.
You would think they could make the path to the convention center a little less...maze-like.
  • Buddy's Amazing Adventure ported to HTML5 - Buddy's Amazing Adventure is an example of a great existing title created by the nice folks at Fablevision that we reworked in HTML5 so mobile users could play it too. I think Derek did a great job of recreating the experience and users will be hard pressed to find the difference between the Flash and HTML5 versions. If you want to try to find the difference visit this link on mobile and desktop devices. The mobile version is ours, while the desktop version will load Fablevision's original version.
Prehistory's nemesis to a well-washed car.
  • Field Guide ported to HTML5 - The Field Guide is essentially a giant dinosaur encyclopedia. We took the existing Flash version and ported it to HTML5. Along the way, we learned a whole lot of dinosaur facts by osmosis (Did you know Quetzalcoatlus had a wingspan of 36 feet? That's crazy!). You can check it out here.
Even Giganotosaurus needs his moment in the spotlight.
  • Mobile Website - PBS Kids already has an excellent desktop friendly Dinosaur Train website, but they didn't have a version that worked on mobile devices. So, we put together a site for mobile users. PBS Kids automatically redirects traffic to the correct page, so if you're on a mobile device, that link up there will take you to the mobile site we designed.
We hope you'll take some time to explore some of our recent creations and leave us some feedback. Have fun!




Tuesday, December 31, 2013

Explore the Story

A trip by mule-back makes me appreciate my '76 Datsun
We wish you a Merry Christmas and a Happy New Year! A few months ago, we worked with Forest Hill Church to bring another game to life. They just released the game the weekend before Christmas, so we wanted to share a bit about it now that it's live. We were excited about this opportunity for several reasons:

  • They're local! Interestingly all of our work until this project came along has been out-of-state or international. This meant a few more face-to-face meetings than we're accustomed to, so we shunned our caveman apparel and studiously domesticated our facial hair.
  • Another Platypus project! We designed a front-end game as well as a back-end game editor that allows the staff of Forest Hill to add new stories to the game. We used Platypus as the backbone for both of these interfaces, giving us a lot of interesting use-cases to further strengthen the engine.
  • It's Sunday School++! We loved that the church had a vision to try something new. We created the basic framework, but the Kids@FHC staff will be making the individual games, so we're excited to see the stories and experiences they create with the tools we made.


The Game

Can you find the telephone booth?
Explore the Story is a seek-and-find puzzle where children can select one of several stories to play through. Each story consists of an environment with several hidden items to find. Once an item is found, children answer a few questions about the artifact to score points.

This game is unique in that it uses photographs of the kid's auditorium as the game environment, and each artifact is physically hidden on stage for the photo-op. This presented interesting challenges while designing the game, since an artist can make art that fits a game perfectly, but photos aren't quite so flexible. For example, small hidden items in a photograph become nearly indistinguishable from a distance, so we updated our design by including close-ups. This alleviated the small artifact problem and also gave the game a deeper experience, allowing children to explore the environment in more detail.

For this game, we neglected the HTML5 canvas route we typically use for more animated experiences and strictly used the DOM and CSS. This allowed us to take advantage of hardware acceleration on many mobile devices by using 3D transforms for the visual effects.

The Editor

Archeologists uncover Goliath's armor near Charlotte, NC
In addition to the basic game framework, we created an editor through which the church staff could add new stories to the game, including pictures for the environment, artifacts, and questions to accompany the artifacts. Creating the editor was a bit of a new experience for us, since we typically work on front-end game development, but we're pleased with how it turned out.

We built in a few tools to make creating and editing a game an easy and fluid experience:

  1. We neglected the traditional page form submit in favor of a responsive XHR model. As rooms and artifacts are added and edited, a server-side JSON file is updated to reflect the current state of the story.
  2. We made soft limits on text input: if the text field content is getting too long for its respective place in the game itself, the text field background color becomes yellow or red to signify that the length may be too long.
  3. We created a visual room selection module so that picking the right room for an artifact or room-to-room navigation is intuitive, without unnecessarily naming rooms to use as references later.

Conclusion

Check out the game and give it a whirl. And if you live near Charlotte, NC, you can visit Forest Hill Church and see it in real life!

We would give you a link to check out the editor too, but, you know.


Friday, December 13, 2013

The Components of a Platypus: An HTML5 Engine Mid-Mortem

The Platypus engine is Gopherwood's first foray into the world of component-based design. The engine has a long life ahead of it, but as a sort of mid-mortem we thought we'd take a second to share our reasoning for going the component-based route and how we feel about the results so far.

Components. Kinda like Legos, but less painful to step on.
When we first got the go ahead to put together an HTML5 engine for PBS Kids the first thing we did was fish around for a proper design template for the engine. When a talented programmer friend recommended we look into a component-based design, we did exactly that. For those unfamiliar with the model, the idea is that game entities are made of a simple object whose functionality is fleshed out by adding a collection of objects called components. These components are designed to function independently so that they can be added/removed/replaced with impunity. After a little research into the design we were convinced by a few arguments we found.

Arguments for Components

The first argument for a component-based design was an argument against using the more popular class-based design model with JavaScript. JavaScript is not a class-based language and doesn't lend itself to a traditional class-based design model without some finagling (that's a technical term). We felt that a component-based design fit more cleanly in JavaScript's design tenants. By starting out with a design model that better matched JavaScript's nature we felt that we would benefit by doing less working against the grain.

Another benefit we saw for avoiding a class-based design was to get away from the bloatedness (another technical term) of inheritance. With engines that use inheritance, you often inherit from several standard classes when you are creating a new entity. In the process you often inherit more than you need for what you're doing. This is because each new entity has special cases that requires small revisions and additions to the standard inherited classes until eventually these classes are bloated with functionality that is useless in most situations. Component-based design is in some ways a form of hyper-multiple-inheritance, in that each piece of functionality (logic, ai, physics, etc.) is 'inherited' from a component. The difference is that each component is designed to work discretely, meaning that special cases (and the bloating they tend to cause) can be dealt with using a unique component while the rest of the components remain standard issue.

Finally, because all of an entity's functionality is found in its components, the argument stood that it would be easy to quickly assemble new entities from existing components and reuse components.

The Good Side

You mean we aren't unique?!
So did it live up to all the promises? For the most part, yes. We've been very happy with the ease of developing in the component-based model. In particular, creating new entities from existing components has made the development process considerably quicker. In some cases, such as the playable characters in Wild Kratts: Monkey Mayhem, we are able to create entire entities without a single line of unique Javascript. And in most cases, we are able to reuse existing components to add large pieces of functionality to an entity without adding more functionality than we need. Designing entities is made easier by using JSON to assemble the components that will make up an object and give initial settings for those components. All of these things add up to the ability to make lean entities efficiently.


A good example of how easy it is to put together an entity from standard components is the ant entity in Monkey Mayhem. The ants in Monkey Mayhem behave like Goombas from the Mario series. To create their behavior we use four standard components: ai-pacer, logic-directional-movement, logic-gravity, and collision-basic. Collision-basic allows us to define what the ants will collide with. Logic-gravity will cause the ants to fall when they aren't supported by terrain or a solid entity. Logic-directional-movement tells the ant how to move each game tick (in the ants case it's defined to move horizontally at a steady pace). Finally ai-pacer works in conjunction with collision-basic and logic-directional-movement to tell the ant to reverse direction whenever it collides with a wall. While this is only one example, it's easy to imagine how by swapping out one of these components with a new one we can quickly create new types of enemies.

The Challenges

While many of the promises of a component-based design have come true, that's not to say there haven't been challenges.

There have been multiple systems that have strained against the restrictions of the component-based model, particularly the limitation that components should be discrete and ignorant of the inner-workings of one another. Our collision system is an example of a system that violates this principle. We found that some components needed to be more tightly coupled than was possible in a pure component model and so we opted to violate those principles instead of creating an unnecessarily complex workaround. Deciding when and where to do this in the engine has been a recurring question. As our experience with the engine grows we feel that the answers to when to break the rules will become clearer.

Pew! Pew! Pewpew!
Another challenge was developing a means of communicating between components. It took some iteration before we found solutions that felt natural. For communication within an entity we used an event-based model. For those unfamiliar with this model it is somewhat similar to how a satellite relay works. A component that wants to send a message to another component broadcasts the message to its owner entity (the satellite). Which then rebroadcasts the messages to any listening components. This worked well for communication within an entity, but didn't scale to communicating between entities because there was no simple way to specify which entities would receive the message. Instead, we came up with a couple solutions that were useful for different situations. The first, and most direct, was to let a component listen for when other entities were added to the current scene. If an entity is of interest, the component can retain a reference and then communicate to that specific entity. A second solution was to set up a modified event-based system using our 'entity-linker' component. With this system an entity can link to a particular 'channel'. The entity will receive any messages broadcast on that channel. Similarly the entity can broadcast its own messages on the channel for other entities to receive. 

In addition to these challenges, there is also a general mental shift needed to switch from traditional inheritance oriented design to a component-based model. Thinking about each component as discrete, determining the proper means of interfacing with other components, deciding when to generalize a component or keep it specific, etc. All of these are questions that occur repeatedly as we work on Platypus. These aren't bad questions, just different.

We Like It, Now You Try It

In summing up, we are really happy with how Platypus has come together and continue to believe that going the component-based route was the right choice for the engine. If you want to form an opinion for yourself, feel free to check out the engine here on GitHub.