It started as a hobby…

…CG, that is. Now, I’m a professional. I’ve been so for 15 years. After a while, though, it becomes a tedium. If you’re good at certain things, it’s quite easy to be scoped in to do those things over and over again because employers would rather employ you to maximise the benefits of your proficiency.

This itself isn’t half bad, if only bosses actually knew what you did.

As I began my career, ‘career advancement’ never entered my mind. That meant that I didn’t know I was coming into a career, nor did I expect my bosses to advance my career while being employed by them. I think this is because I was actively advancing on my own. I was learning new things, I was getting better at the things I already knew.

Now, there is a great dissatisfaction when that advancement stops. When it does, I question why the company doesn’t do more for me. Then I come to understand that even if I had been given a SIGGRAPH pass, or sent to NAB, or some artist convention in Europe, simply knowing more is not career advancement. Neither is a job title — I’m a “CG supervisor” — and neither is a pay raise.

I’ll tell you what it is.

There is a situation that doesn’t allow me to apply what I learned. To be compelled, by my situation, to allow things that go against my knowledge and common-sense tells me that my personal advancement only goes so far as my nose.

When there is no utility in learning or experience, ‘career advancement’ stops.

Let’s compare that with being able to take charge of a situation and come out on top. To apply what I know, to make ignorant mistakes, and by its very virtue to gain experience, that kind of ‘advancement’ is the kind of satisfaction that made me love the craft so much.

This other situation is not dissimilar: not to have the space to learn something new. I want to explore new ground, especially the world of interactivity (it combines my creative interests with the coding skills I’ve learned through the years), but there is no enthusiasm to explore this in the studio where I work. It is only interested in what it already does and continues to ply the same trade routes year in and year out.

When learning is limited to the scope of your established career, –a.k.a boredom — ‘career advancement’ stops.

What started out as a hobby became a profession. It was satisfying as long as you were improving, and learning new things. But 15 years down, it’s become more about evading egos and enduring the squabbles for the Almighty Dollar.

Then there are yearly reviews which tell you that if you only did this or that you’d be worth a lot more.

Workflow: Animated Tiles

Dedicated animated tiles

The syntax to activate animated tiles is in the ‘vars’ (variant) variable of each tile. Again, to recap, the Tiles’ ‘vars’ property denote the any number of states that the Tile can be in. For every state specified in the ‘vars’ property, there is a corresponding data related to the graphic that will be shown when the Tile (of that Layer) reaches that state.

Example:

vars=open*:a,close:a:15

Note * and ‘a’ and ’15’.

The * denotes that it is the default state of the Tile.

The ‘a’ denotes that instead of using another Tile ID for this state, use an animated variant.

The ’15’ denotes an alternate Tile ID which is an extra level of control in order to find the animated Sprite

Ok, so how does it evaluate which animated Sprite to use?

Through the use of Nicknames to reliably instantiate the tileset Family (ts_f) each animated Tile variant is given a unique name. The syntax template is:

<tilesheet_name>_a_<tile_id>_<state>

What this means is this: let’s say we have the above ‘vars’ property in the Tile from the ‘objects’ tilesheet, it’s Tile ID is 10. For a give state, let’s say ‘open’, the system will look for a nickname called:

objects_a_10_open

If this ts_f exists then it will be picked. This ts_f is a dedicated animated sprite for that tilesheet/tile ID/state combination.

Now, as another example, if the Layer’s Tile state becomes ‘close’, the ‘vars’ property above specifies:

close:a:15

In this case, it will look for a nickname called:

objects_a_15_close

No ‘nominal’ state

As an aside topic, this is about whether tile states (ie TcoDict) should have a ‘nominal’ (or default) state. This was apparently not a good idea, since it is logically ambiguous. A default of any state make it impossible to know what is the converse value of it.

At any rate, I’ve made all TcoDict unambiguously have a state, and this is inherited in the C2 import of the TMX.

The behaviour before was that for each TCO, it reads the ‘layers’ property and there initialises the state. This could be tedious in the future. And since it is possible to indicate the state of a Sprite/Tile by visually looking at it (eg open door, closed box), I will do it by reading the Tile’s ‘vars’ and looking for the -1 directive. Whatever state it is, it will be written as the default state of the Tile in the TcoDict.

Workflow: Multiple Tilesets

Dealing with multiple tilesets

C2 Sprite are used as tilesets in conjunction with TMX Importer. One Tile Sprite is considered a single tileset.

This the solution I’ve come up so far.

Use of Family Object and Nickname

Tilesets are grouped into a Family called ts_f (stands for tileset family). They have the instance variables that mimick the previous ’tile’ instance.

tileset_family_variables2

The addition is the Nickname plugin and its corresponding behaviour. These are essential to both instantiate and pick the correct instance of the tileset.

It’s worth nothing that I have tried native C2 methods of generating and picking instances into the SOL. However, what I have observed is that while I am able to instantiate specific Family members (by compare-picking Family instance variables), these newly created Family members were not being picked up properly into the SOL, and thus configuring these new instances were not possible.

Nickname, however, is able to generate instances and then place into the Family again. But unlike C2’s own methods, Nickname somehow allows me to reference the newly-created object by accessing the Family.

This might be a worthwhile bug report.

Because of Nickname I was able to retain all my events save several modifications as to the placement of the Tile/Chess objects. Instead of using Action:Create chess/tile, I had to use the System’s Create object to generate the Sprite instance, position it using the Board’s convenience positioning expressions (eg Board.PXY2LXY), and then use Board’s Action:Add chess/tile, which adds the entity into the Board without additionally creating an instance of it.

In summary, I am loading in tilesets manually in C2 and assigning them the name that corresponds with the ones used in Tiled. When TMX is being loaded, during Tile Placement, the tmx.TileSetname is queried and stored. This is the same being used by Nickname to instantiate that tileset/spritesheet.

Just in case it doesn’t immediately become apparent to my future self, the reason why ts_f even exists is simply to conform all tileset’s instance variables. All tilesets are put into the family to inherit the variables.

 

Gotchas: Losing ‘scope’ while calling function

losing_scope_function1

The above shows a certain situation where function calls are not aware of certain changes made by other functions.

In the picture above, I call “TanimChange by uid”. Part of the events look like this:

losing_scope_function2

Note that I create an instance using Nickname. All ts_f set variable directives work fine.

At the end of “TanimChange by uid” I return the uid of the newly created ts_f.

Back to the top image: when “TcoChange repost tile (ts_f.UID)” is called, it’s actually a very simple function:

losing_scope_function3

All I do here is get reference the UID argument and search ts_f for the UID. Unfortunately, it doesn’t see the ts_f.

In fact, when I bypass the check and let the For each ts_f loop run, it doesn’t register the newly-created ts_f instance.

I consider this a bug, and would try to get report going and try to replicate this without using 3rd-party plugins.