The purpose of the Social Ref world is to provide developers using the HeroEngine with example implementations of systems that would be necessary to operate a massive online asynchronous social game. It is by no means a complete game beyond the small amount of gameplay we've provided, but the core systems are all there: persistent player farms, friends system, task system, object placement and interaction. The Demo Social Game is only a proof of concept illustrating the use of HeroEngine to create the kind of social game one might find on social networking sites like Facebook or hosted independently across the web. Styled as a common farm game clone, its primary goal is to provide examples of art, programming and game logic that could be used to facilitate the creation of real social games of your own design.
Overview of the Art
Common Art Errors: First off, the savvy developer will notice a number of console errors relating to the foliage in the area. This is due to the fact that the materials have not been given unique names in the 3d art program. This is the most common error new developers will encounter. Our error doesn't affect the visuals of the assets, but more than likely you will encounter mis-mapped UVs on your assets if you were to make the same mistake.
The well in the middle of the zone shows a classic problem that world builders new to the 3d space encounter. The well asset and the bricks asset are placed on the same z-axis (having been snapped to the terrain) and since they are the same density, the faces of the two assets are "Z-fighting", as the renderer fights to determine which face should be rendered. The only solution to this is manual labor moving assets up or down in the z axis, or changing the models themselves.
In the back of the area are two windmill models. One has LODs (levels of detail) built into the model, and as you move the rabbit closer to the windmill you'll see a jarring visual as the final level of detail swaps in. This is because the two LODs are too dissimilar (in this case because one mesh was not grouped with the others for both LODs). In a social game, depending on how large your areas are, you will most likely not make use of LODs, but with a large area, or if you are using game assets in the background of the game, you may want to consider it.
Art Decisions: We used only two textures for the terrain; a grass, and a dirt. We used heavily stylized textures that would not need to rely on lighting, or normal maps to look great and fit the cartoon style of the game. We scaled the UVs for both in order to prevent any texture tiling (seeing repeated textures), and well-made, and larger textures, can withstand being scaled 2x and 4 x times. Neither is making use of a normal map, since the cartoon style does not require it.
For ease of look and feel, the buildings are relatively high resolution, with relatively large textures. Viewing the "Scene Analysis" window will show you the details of the scene. We also chose to have both object [static shadows] and character [dynamic shadows] cast shadows. By default, the HeroBlade uses the shadow settings just as analysis tools for artists and world builders, so you'll see that we wired them up to a graphics slider accessible via the in game UI. As shadows can be a large performance hit to lower end machines.
Overview of the World Building
Relative Scale: You'll notice we scaled the the art assets to larger sizes than are used by default in the HeroEngine. The purpose of this was to demonstrate that in a small focused area the tessellation of the heightmap can be increased by increasing the relative size of the art assets. This is a pointless decision for a game where we kept all of the gameplay space flat for simplicity, but the effect can be seen in the surrounding areas, as well as vertex coloring.
Terraforming: We used 3 brushes to make the terrain. We kept the gameplay space flat, for ease of implementation of a plot system, but outside of the gameplay space we used the raise tool, the flattening tool and the soften tool. The raise tool makes mounds and raised areas. We built the zone with the fixed camera in mind, so you'll see far more detail in the viewable end of the scene than in the lower hidden section. So we raised hills in the back, then used the flattening tool with the CTRL tilt option to draw out inclined sections among the hill faces for a natural plateau feeling. Then took the soften brush, limited its effect to only slopes greater than 0 and less than 90, and just ran it over the whole area. This has the effect of smoothing out any jagged areas, without changing the clean flat or vertical areas.
Texturing: After finishing the heightmap, we applied the grass texture at 100% alpha to the entire area and scaled the UVs to look nice in the gameplay camera view. We then added the dirt texture, but limited it's slope by dragging the green slop bar up from the bottom until only the steep sections of the terrain were highlighted, then we just painted the entire area with dirt using a large brush at 100% alpha, and only the steep sections of the terrain were painted, giving the area a natural rock and grass feel to it, since grass doesn't grow on steep slopes. The dirt texture was used both in the gameplay area, and the surrounding hills, and it looks great. But in a semi-realistic looking game, you would probably need to do a separate layer of the texture for the sloped terrain, and scale the UVs down so that the texture doesn't stretch across the verts.
Shadows vs. Vertex Color: Because there are options to disable shadows, we also used 50% black vertex color to paint or "bake" in the feeling of shadows. This gives the world a feeling of depth, and allows assets to feel connected to the terrain. Generally we daubed color beneath all objects, and then chose sections of the terrain (mostly vertical faces) to darken, both to break of the monotony, as well as provide depth. But you'll notice that some areas can look strange with the shadows enabled on top of the baked in vertex color, so those are artistic decisions you'll need to think about.
Time of Day and Lighting: The environment panel allows world builders to create environment schemes which control all aspects of the the environment from lighting to fog to clouds. One of it's most powerful aspects is the ability to define different settings for any time of day. The time of day slider is a client side only tool to allow world builders and artist to see what the area looks like at any time of day, but changing the time of day in the environment panel is not the same as setting the time of day on the server. We chose to lock the time of day at a specific time, just for demo purposes, and so we wouldn't have to spend as much time tuning the lighting, but you can slide the time of day slider back and forth to see how it affects the world. Just don't blame us for when the lighting intensity and color are terrible, since we didn't do any work tuning them.
Overview of Scripting Work Done
Key features of the Demo Social Game:
- Session-based gameplay that requires minimal client/server communication
- Complete sample game systems for Character Selection/Creation, Inventory, Friends, Quests, GUI and Shop.
- Sample custom isometric camera with smooth linear interpolation of camera movement
- Sample state-based input system
Social games are often session-based and connectionless to maximize the number of concurrent players supported while minimizing the need for constant communication between server and client. To that end, the Demo Social Game implements its own session tracking and data caching and avoids using some of HeroEngine's automatic data replication features. It accomplishes this by leveraging four universal concrete classes which implement custom-defined interfaces: SerializableObject, CacheableObject, VersionedObject and SurrogateObject. Combined, these classes allow any object in the game to be cached locally on the client, version-checked with authoritative server data, serialized for transmission between client/server and between the client/LRC, and replaced with authoritative data at will.
- Session-based play is achieved by storing commands on the client and then batch-transmitting them to the server at pre-defined intervals. The player is never aware of this and can play the game locally between updates.
- To enforce minimal communication between the client and server, all objects in the game (player data, farm data, inventory, friends, etc) are cached in the Local Repository Cache between play sessions; these objects are then read into memory, version-checked with the authoritative server data, and updated from the server only when necessary.
- BaseFarmEntity Class
- IF_Command Class
- TillFarmAreaTillablePlotCommand Class (and other command classes)
Character Selection / Character Creation
Though many online social games restrict the player to a single character (which in turn is locked - for example - to the player's Facebook account), we felt it was worth exploring a means of creating an immersive character creation and selection process for our social game. In the end, this equates to a 3D stage displaying the currently selected character or - during creation - a stand-in 3D representation of your new character. Also displayed on-screen are the player's name, score and money stats.
To facilitate this, we overrode the following:
- The default character selection/creation GUIs
- The default _OnAreaLoad behavior on the client (for camera initialization and character placement)
- The default character creation logic on the server (to add game-specific player data to the account and character)
- Customizing system nodes (BASECLIENT, CHARACTERSELECTIONSYSTEM, CHARACTERCREATIONSYSTEM, etc) by glomming game-specific classes onto them (for custom GUI, custom cameras, custom character data).
- Input event handling in both the GUI (for button clicks) and input layers (to restrict camera rotation and player movement)
- Understanding the login process (logon, enter area, activate character, select character, travel to character creation or in-game area)
- System Node Configuration
- Character Selection System
- Character Creation System
- Camera External Functions
Sample Game Systems
The player inventory, friends, quests and farm-commands are all implemented independently on the client and server to allow play to proceed unimpeded during a single non-connectioned play session. This is accomplished by performing actions locally on the client, then creating 'farm commands' to be later sent to the server and executed. These farm commands, when executed on the server, will be interpreted as authoritative. If they succeed, the client and server will be assumed to be in-sync; if they fail, an update will be made for the involved objects (inventory, farm entities, etc) on the involved client to re-sync the client's data to a last-known-working configuration.
Data for these systems is almost universally driven by the Spec System. All immutable data is stored in specs (e.g. what defines an inventory item? what defines a farm entity? what defines a quest?) and mutable spec derived objects are created for a player's instanced data (e.g. their 'particular' inventory, their 'particular' set of quests). Adding new data definitions then becomes as simple as adding an additional spec (e.g. we want to add 'Radish' as a harvestable farm entity. No problem; just define a new spec for it)!
- The client and server operate independently between 'synchronization updates'; only when farm commands are sent to (and executed by) the server does an authoritative action/change occur.
- Synchronization occurs by 'rolling back' data on a client that is known to have gotten out-of-sync; this determination is made when the server cannot execute a command requested by a given client.
- All mutable data is spec-derived, while all immutable data is stored on the specs.
- various 'command' scripts, 'spec' scripts, 'spec oracle' scripts
- The Spec System
- Remote Calls
Sample Isometric Camera
The isometric camera used in the game farm is an incredibly simple means of providing an overhead view of an area. Initialized upon entering the area, it is set to target an invisible 'tracker' model which follows the player and then lock its view on the tracker. As the player moves, HSL scripts drive the movement of the tracker which - in turn - causes the camera to follow it smoothly. Mouse input that would normally pan the camera is ignored to provide a view which remains locked onto the player.
- We lock the camera onto a target which roughly approximates the position of the player. This target moves smoothly with the character to eliminate camera jitter.
- We ignore mouse input which would normally rotate or pan the camera such that player input has no affect on it.
- Input Layers
- Input System
Sample Input System
Input differs drastically from that of a normal MMO. Instead of controlling our character's movement and actions from the keyboard, we simply point and click on objects and locations on-screen. This is accomplished by defining custom input command layers which ignore keyboard input in-game but respond to mouse clicks by instructing the character controller to move to the target destination or interact with the target object.
Since we have only a single form of player input (namely the 'mouse click'), we differentiate between commands via a set of 'Farm Tools'. These tools may be selected from the GUI at any time and enact a state change behind the scenes which modifies the way player input is interpreted. Depending upon this state, we may enter different visualization modes (for object placement), the cursor may change, and clicking on objects may trigger different effects.
Commands are enacted by creating 'input commands' and inserting them into an 'input queue'. This queue is processed in-order to allow the player to queue up actions to be performed (such as harvest or till). These commands interact with other systems to request an action be attempted. These actions may succeed or fail, and the result will dictate whether the input queue continues to be processed or whether we break from it (due to invalid commands).
- Custom input layers define the ways in which we react to user input. In our case, keyboard input is ignored while mouse clicks are used to direct the player's activities on-screen.
- Due to the limited number of user-input possibilities, game states are used to determine how our mouse clicks are processed and what they mean. By selecting different 'tools' using the GUI, we enable different sets of actions.
- Input commands are created for each requested command that attempt to perform actions and - based upon success/failure - influence the future execution of input commands.
- various 'InputCommand' scripts
- Input Layers
- Input System