Category Archives: Graphics

Prototyping – A Killing House

After six months (almost seven!) I can say that I’ve reached what is effectively the ‘end of the road’ insofar as the Citizen prototype is concerned.

I’d like to recap what I am trying to accomplish in this prototype.

I am very aware of my inexperience; I’ve never done a game before, and so I don’t know what works and what doesn’t. I only have my own taste and sensibility for what it’s worth. Though I believe (or hope) I can pull it off, I don’t know what it really is, so this prototype has been an effort to put all the ideas that I’ve come up with into one package. I thought to myself that creating systems for a game is relatively straightforward. But can I integrate any number of those systems with each other, and have them work? If I can manage that in a prototype, then I would have the blueprint for an actual game.

I created this prototype with that mind. And having experienced the troubles of illogical inconsistencies in system, bugs of a generic sort, it feels like I’m about to ‘ship’ a game without the danger of flagellation from Steam reviews.

This is my version of the Killing House, where I rehearse and train for the game I’m going to make. I’m using live rounds and making it as realistic as possible because I want to, as much as possible, be prepared for the task up ahead. I put as much effort into it because if I can get this to a level that I’m happy with, then it’s quite possible that I can pull it off when I make the final game in Unity.

Making the prototype itself was grueling enough. I don’t remember burning so much midnight oil since I was a fledgling 3D artist back more than a decade ago. Not every idea or implementation would make it to the end. But none of those aborted/abandoned things were wasted on the experience of trying to make it.

For example, the game narrative script that I wrote at the beginning is now completely different. However, it served as a springboard for identifying and designing the systems I need to have in place, so it was still a profitable and necessary first step.

There were other ideas, like the ‘Multi-Vision System’, ‘Stacker’, and ‘Map Layers’ that I dreamed up up that had to be thrown away due to either being too oblique, complicated, or just plainly stupid.

Also, I had created and rendered NPC assets which were not used in the final version of the prototype due to a change in narrative.

While there are clear advantages working in Unity — certain bugs and limitations that I’ve encountered in C2 will no longer be relevant — I’m aware that I’m facing a world of hurt in Unity-land, too. Naturally, I will take advantage of what Unity has to offer, as well, such as a full 3D environment (something which I’m comfortable with), dynamic lighting, and a robust pathfinding system, among others. All the while, I must remember to keep it simple. It’s possible that I may have to even dumb down the game more so in Unity, to keep it within my capabilities.


Sights…


Towards the end of the development, I started working on a introductory cinematic, which was a fun thing to do. It wasn’t intended to accurate represent the all the details of the story but only to give a good idea what it’s all about. Here are some screen shots:






Here are some additional screen shots demonstrating how it looks like.

Sample environment. On-screen interfaces (bottom, upper-left, upper-right)
Sample inventory screen. Item descriptions, icons.
Sample dialogue panel (Convo). Portrait.

I posted a gameplay sampler which demonstrates some of the systems in action.


… and sounds!


I’ve also cut up some audio (re-learning Cubase again!) to use with the prototype. I may post a complete playthrough in the future, perhaps after some of my friends play it first themselves and hopefully give some feedback.

 

Advertisements

Prototype sampler # 1

So, finally, I’ve completed my last major developmental milestone and I think that deserves a post. 🙂

The above video simply shows the playthrough of some of the game mechanics. The quest has not been fully written yet, and though all of the game mechanics are working, they’re not readily apparent without some introductions. The video is mainly to see how adventure and combat are blending as one piece.


I’ve slaved away on numerous aspects to accomplish all the major milestones I had set out to do. There were a few additions to these, but they were minor changes, and all in part of the iterative process of figuring out the closest gameplay mechanics I wanted to implement in Unity.

Though my work isn’t done yet — there are still UI issues I need to sort out — and there are still some niggling bugs present in the prototype, it is largely playable. By ‘playable’ that means you can run around, talk to people, and shoot Robots, and get shot back. You can plant a bomb, blow it up, and you can blow yourself up in the process as well. You can ‘pox’ a powerlet to get energy, you can buy and use meds to heal yourself. Frankly, a few months ago I didn’t think I could end up saying all this in one paragraph.

Most of the joy, and fear, of this prototype has been the implementation of a bespoke AI graph framework. It’s a joy because it actually works; it’s a fear because it sometimes feels too deep for me to always grasp its innards when some things don’t go right.

I’ve gone through mounds of halved/quarter-A4 to-do sheets with heaps of orange highlighter marks signifying all the big and small tasks or goals I needed done. There are so many disparate systems working that that if I didn’t have a calendar tracking my progress, I wouldn’t be able to grasp what I myself had accomplished.

For example, here’s a quick run-down of the aspects.

  • Asset creation.
    • I’ve heavily used Janus to break out animated sequences.  Using FORFILEs, a Janus looping construct that iterates through the lines of a file, creating an animated character, such as the Player character, was simple as I needed only to set up one angle and let Janus break out all the other 15 directions. Variable frame ranges for a particular animation were also taken care of using the same principle.
    • Janus was an important cog in the making of the prototype because of the amount of iterations for the scenes. An element would sometimes become designated as an interactable element, which had to be split from the main scene and rendered separately.
    • NPC/Robot portraits had a separate animation and render, and specifically had to go through post-processing.
  • Tiled was used in making the maps, and Rex’s TMX Importer was used to carry that information in C2. I had to do some modifications to the TMX Importer to enable the retrieval of the Tiles and Objects image source. Tiled enabled me to experiment and implement concepts by introducing certain datatypes for the engine’s use, which informs me of how I may implement the maps in Unity.
    • This had to be balanced with Game Data Documents which are comprised of text-based files of varying structures. These Data Documents are the immutable attributes used by the systems. In the beginning, the data would come from different sources; one would be defined in the TMX, while others defined in a CSV table. As I progressed, I refined the categorisation of data.
  • The in-game Inventory system was one hell of an undertaking, The Inventory system is connected to the Trade system, which is further split into two variants: the Container system, and the Merchant system; the former simulates the ability to store items in ‘containers’, and the latter simulates buy/sell transactions with NPCs. Merchant data, like price, buy/sell limitations, and price adjusters are tied to tables and the NPC entity as defined in the TMX.
  • While the code related to the movement was entirely specific to C2, I had to nevertheless overcome these issues to get a working prototype. Pathfinding needed some optimisations, behaviours related to physicality of entities needed to be coded in relation to the established movement behaviours. This aspect will largely be replaced by Unity’s navmesh, in addition to a target grid overlay that I may custom-build myself.
  • The Action Strip (a.k.a. Astrip) system — the method for interacting with elements in the game — was developed to be authored using text files (like most systems in the game).It serves as the hub for all ‘adventure’ interactions. It was also designed to be generic so that the display of interaction results can be be tweaked directly from the text file. For example, a ‘look’ action,  at an object may initiate a display of a description, or the narrative box, or initiate a dialogue, or anything else that has been allowed in the engine.
  • The Convo system was another early development. Some additional Python code was necessary to convert the authored .graphml files (using yEd) into a Markdown format (for readability in a text editor). However, the development of the AI graph framework proved that the Convo system was inferior, though both used node graphs. Although the Convo system has not yet been upgraded to use the same (or similar) framework of AI, this would eventually be done when the port to Unity is made.
    • The Convo system could be called by the Astrip system.
    • The Convo system also allows implicit trade of items. For example, if through speaking with an NPC, it gives you an item to be used. The Convo system communicates to the Inventory system and places the item in the Players inventory.
  • The AI system used the TGF format to represent a nodal graph. Then an in-game parser and callback/event handler framework handled the execution of the AI graph on a per-Robot basis.
    • The AI system is connected to other systems, such as the Inventory, the Trade, Convo (dialogue system) and of course, NPCs/Robots themselves.
    • Using the AI system, a Robot can accost you to do a contraband check, which was one of the first implementations of the AI (even before combat).
    • The AI can contextualise its own dialogue with the Player, changing it from a contraband check to an arrest, for example.
  • Lookups for gameplay values, such as hit-chance, effect of skills on gameplay, were done using a non-linear interpolation that was accomplished by using Open Office Calc’s cell formulas. This allowed me to tweak lookup values utilising functions as opposed to doing it individually, per cell! This application was conveniently placed to export to CSV directly, so no other intermediate process was needed to get it to C2.
  • The Combat system is closely tied with the AI and is comprised of many factors, a few of which include:
    • Alert level behaviour of Robots; certain actions at a certain alert level means differently for Robots. For example, running or crouching is OK when Alert Level is 0. But when the Alert Level is 1, running or crouching is interpreted as suspicious and Player will be fired upon.
    • Behaviour of Robots differ from one another. Some guard, some patrol, some check for contraband.
    • Offensive component
      • Player accuracy skill
      • Weapon attributes such as range, max_range, weapon dropoff (weapon damage and chance to hit is affected)
      • Rate of fire
      • Dual-wielding of weapons
      • Crouching increases accuracy
      • Bomb placement and detonation
      • Shock effect; certain weapon may stun a Robot for a period of time.
      • GMAC system, which is a modifier on top of a typical random number generator.
    • Defensive component
      • Use of cover for defence
      • Crouching reduces profile, increases Player defence against being hit
      • Running increases Player defence against hit but only if running perpendicular to Robot.
    • Stealth component
      • Crouching behind low obstacles for stealth
      • Noise level when running; Robot hears you!
      • Glitters is Electronic Counter-Measures and makes the Player invisible for a short period of time.
    • Hacking powerlets to get more energy, and the associated success rates, and the penalties for failure
    • And others that are too lengthy to include, but you get the idea…

Normally, a prototype is small, whose gameplay represents the root of what the game is about. Sometimes, a prototype is created to determine if a gameplay works or not, or if people like it enough.

But I built the prototype as a technical reconnoitre  of what I’m going to come up against. You can say I was also trying to form a beachhead at the same time. I don’t know if people would like it, but I can’t be dissuaded either way; I’ve gone this far solely on the excitement of taking a childhood game to my present.

But a prototype is also made to present the gameplay as clear as possible, that if the prototype is fun to play, then the real thing would be as fun, if not more fun to play. The problem I have with Citizen is that it is an adventure as much as it is a shoot-em-up game. The fun in 2400 AD, Fallout, or Shadowrun, for example, is the fact that it is an adventure. But I find it difficult to express the full adventure by doing a half-adventure. I think that’s due to my lack of experience writing for games. At the same time, I think that I’ve been focused so much on the technical aspects that I’ve not really dug as deep as I should into the potential of the narrative. I’ve been working on the framework in which I hope to base an adventure story (of which I have a first draft already), and I think that this prototype, as it stands, should be just seen as the prototype for the framework.

More to come.

 

Isometric reveal mechanism wip

A short demo of the mechanism of revealing the Player behind certain elements in the scene. Still rather rough; some adjustments are needed, but the principle seems to work.


The image below illustrates the implementation.

The mechanism consists of 3 colliders, and elements that have a reveal attribute that can either be always, back, front, top.

The 3 colliders are:

  • frontface_reveal_collider
  • backface_reveal_collider
  • top_reveal_collider

The procedure is:

  • When the frontface_reveal_collider overlaps a reveal=front element, then that element becomes semi-transparent.
  • When the backface_reveal_collider overlaps a reveal=back element, then that element becomes semi-transparent.
  • When the top_reveal_collider overlaps a reveal=top element, then that element becomes invisible.

Inventory

One of Citizen’s gameplay themes is the limitation of what weapons you can use. As a citizen of a dystopian, Robot-controlled city, you couldn’t freely carry dangerous goods and not expect to be accosted by Robot patrollers.

It was in the INV system that I first wanted to express that game concept. The INV system was originally conceived so that the Player can carry only a few weapons. So I delineated certain types of items can only be placed in certain ‘slots’. I also limited the number of slots for a particular category.

However, in time, I came to think that the limitation was a bit too extreme. It was complicated from the point of view of mechanism, but it also had logical game problems.


Nearly 3 years ago I was working on an RnD game project (dubbed Henry) which was supposed to feature multiple characters. The system allowed the viewing of different inventories within the same interface, and allowed trading between characters through a drag-and-drop mechanism. It featured multiple pages and a categorisation of items; weapons and armour were automatically put into the upper slots, and other adventure items were put underneath.

The Inventory system from the RnD project called ‘Henry’. I think there’s a bit of Jagged Alliance in the graphic design decisions…

It was Henry‘s Inventory system that gave me my first experience in the in the difficulty in doing inventories, from the organisation of items, to the behaviours of drag-and-drop and how the logic of how things are arranged and displayed.

Also from Henry I took the idea of categorisation, which is the exclusive placement of items of a certain type into a section of slots in the interface.

But categorisation, I later decided, was not necessary if I was just simply gunning for weapon limitations. There were other ways of discouraging the Player from carrying too many, from the increased likelihood of getting checked by Robots, or simply the inability to use them effectively once the shooting started.

Because there were hundreds of ways to skin the limitation cat, I eased my rigid rules in the INV system. However, unlike Henry I had two other Inventory-related concepts that I had to address to introduced their own complexity: Readyslot, and Trade.

The Citizen INV (right), Trade( left) and Readyslot (bottom-right) interfaces.

Readyslot

Without going into too much details about the the Readyslot’s mechanics, it is simply the place where weapons that will be used immediately for combat are put.

Switching weapons that are already in the Readyslot are done immediately. However, there’s a time-delay when you try equipping weapons from the INV, which may be akin to taking something from your backpack. This is how the game discourages the Player from swapping weapons from the INV which may potentially contain a lot of different weapons in the game.

There are other characteristics: there are only 3 slots in the Readyslot area, and that is significant. Pistols are 1-slot weapons, subguns (i.e. SMG) are 2-slot weapons, and rifles are 3-slot weapons. You can mix and match any weapon configuration that the number of slots numerically allows.

But there are special considerations for pistols, too: you can dual-wield pistols.

If you choose to equip a subgun, you can carry another pistol as ‘backup’.

If you choose a rifle, the most powerful weapons in the game, you are limited to that weapon only, and if you try to change weapons from the backpack, there’s a time-delay to get it.

The technical challenged associated with the Readyslot is how that in itself is an extension of the INV system even though it may not look like it visually. The Readyslot is a categorisation, so only weapons can be placed in there.

Trade

The Trade system is essentially the INV system, but using a different source for the contents of the INV. For example, NPCs have their own INV database, and even scene elements, like a rubbish bin that can potentially hold items, have their own INV system.

The Trade system is a little different from INV in that there is a variable slot designation that is dictated by some database (in this case it’s specified in Tiled). For example, a rubbish bin will have 2×2 Trade INV (a.k.a. TINV). A dead robot will have 1×1. Some may have 3×1, or 4×2, etc. And thus there were many considerations about how the system will respond if there was an attempt to populate the TINV with more slots that it could hold, or items that wouldn’t fit the dimension of the slots. For example, a 3-slot rifle cannot fit in a 2×2 TINV.

Slot size, width and height

In games like Diablo, items occupy ‘slots’ in the inventory. But Diablo’s system is very elaborate, as items have both width and height. For Citizen, I decided only to consider how many slots a certain item will occupy. For the most part, only rifles and subguns occupy more than one slot. This greatly simplified the system.

The reason why this is a big deal is because one of the challenges of making an INV is the correct display of items in their proper slots. When dragging a rifle (3-slots) at the right-most slot of the INV, you expect the system to compensate for the size; it must not place it the right-most slot, but 3-slots to the left in order to the rifle to fit the intended placement location.

Also, you have to consider if there are items currently in place in those slots. Will you allow items to be displaced? If so, how do you logically re-position them that makes intuitive sense?

If dragging a rifle from the INV to the Readyslot that is already full of weapons, will you make a swap? Or disallow it?

It’s questions like that, and every conceivable permutation of how one item is dragged from one place or another, dropped onto itself, or another dropped onto it, or something else entirely, all those things filled the 2 weeks I spent designing and iterating through the INV and Readyslot systems

The multi-page function isn’t yet implemented, but I have to make sure to what extent I implement it. How many items will I end up implementing in the game’s narrative and combat? How many pages will it fill? Should I have unlimited pages? Or is one page a good simply limit?

Lots of questions. But it’s all part of the fun, right?

 

Another method for z-sorting

Z-sorting has been, in my experiments, been based on the Y value of a given Sprite object. It’s the sorting mechanisms have been specifically explored rather than the logic that they were arranged.

In this post I want to describe an alternate method to sort using collisions.

This method was developed to solve the issue of complex graphical elements. By ‘complex’, this refers to images that are possibly concave, or elongated. In previous z-sorting implementations, the Sprites being sorted needed to remain within a given Tile area in order for the Y position to be specifically determined for that graphic element to be properly sorted. So what I aimed to do is to overcome/get rid of the limitation that forced discrete graphical elements to remain within one Tile.

Consider the image below.

Note the elongated ‘wall’ and the L-shaped wall, both of which implicitly extend beyond one Tile area. The goal here is this: given these irregularly-sized/shaped elements, find a way to determine whether the character Sprite should be sorted behind/above the ‘walls’.

First I considered finding intersections of 2d vectors in which to construct a depth stack, but then thought it was too computationally cumbersome as an initial approach. Furthermore, this required multiple definitions of 2d vectors if, for example, the shape of the ‘wall’ was L-shaped. Note that the bottom edges were the 2d vectors that were being checked against the character’s position and vector which was, in turn, based on the isometric tile ratio, which determined the vector direction to check with. Again, very cumbersome.

So I came upon an idea of using collisions for a check. The logic is simple. If the character’s base position touches (collides into) a wall, it will be set to be behind the wall. This is the starting point and main principle of the method.

The image below describes it in C2’s event sheet.

The main Sprite being sorted is pc, and mover is the collision line. pc is pinned to mover.

The offsets shown in the image above are somewhat arbitrary. What’s important is the principle of the collisions, which are explained below.

The first issue is that the base of the character (a.k.a mover’) must actually be a volume or area, not a single point because the Sprite needs to check for a hit on the full base width of the Sprite.

The red line is the ‘mover’, and is tailor fitted to the width extent of the Sprite that is being sorted. In fact it should encompass the widest width of the Sprite animation. The ‘mover’ is collision-aware, of course.

Second, we have to consider the Y position of the mover in relation to the Sprite being sorted. Ideally, the position should be the bottom vertex of the virtual Tile diamond.  When the ‘mover’ is too high, the collision will occur ahead of time and will seem too premature. This offset doesn’t need to be precise as it is based on the specifics of the graphics, and the parameters of the game’s aesthetics.

Third, the ‘wall’ Sprites must have accurate collision polygons; as accurate as you need them to have.

Fourth, since we are dealing with 2d layers, we need to design our ‘sortable’ graphical elements so that they can split up so that can be sorted at all.

So if we were designing a four-sided room, you can encompass it with 2 elements. The first element is the bottom L-shaped wall, and the second element is the upper L-shaped wall. In this way, it possible for the character to appear either in front, or behind, either of these two elements.

 

MTile/GTile edge definition syntax

Though this syntax was developed many months ago, I had forgotten to document this.

Overview

This edge definition refers to the edges that exists in any GTile tile/sprite. This obviously means that edge definition is a Tiled property of the GTile, which is then passed on in C2 to generate MTile edges at runtime.

Note that a GTile refers to a graphics tile which is a bigger-sized tile. An MTile refers to a movement tile which is smaller and forms the grid of possible tiles to move to. Every GTile is subdivided into equal square MTiles.

Edge definition

Below is an image representing one GTile, and the MTile IDs within it:

For every GTile, there can exist any number of edges. Using this image as an example:

That sprite is mapped out as:

Here, we introduce the edge syntax used to define those edges.

<mtile_id>:<gridmove_direction>[,<mtile_id>:<gridmove_direction>...]

Where mtile_id is the id of the MTile that needs an edge definition (because it is neighbouring a GTile edge), and gridmove_direction is the direction where the edge lies on that MTile specified in the GridMove format.

In the sprite above, the edge definition is:

1:0,5:0,8:3,9:3,10:3,11:3

That is, the MTile ID 1 and 5 have a edges at Direction 0 (east), IDs 8, 9, 10, and 11 have edge at Direction 3 (north). Note that it’s possible to have defined other MTiles, such as:

6:1,7:1

…to replace 10:3, 11:3. It doesn’t matter, as long as the same edge is not specified twice.

Tiled

Note that the edge definition is inputted in Tiled in its tilesheet editor. Currently, there are two Tile properties associated with edge: edge and edge4. edge was the original use, which subdivided each GTile into 2×2 MTiles. edge4 subdivided it further (4×4) giving it a maximum of 16 MTiles per GTile (this depicted in the image above).

In the C2 project, only one type is used and can be interchanged or modified depending on final design choices.