Google

I interviewed at Google multiple times, and “almost” got an offer on multiple occasions. What apparently happened is that I simply had the misfortune of having interview coordinators that didn’t like me. It was like I was denied opportunity due to “human error”. More specifically, when I describe the interaction with Sam Sepah in 2015, think of the telephone sanitizers from the Hitchhiker’s Guide.

But really, there seems to be more to the story than that. Eventually, I realized the timing of the contacts from Google was not a coincidence. The first two interviews were timed with me losing my two full-time programming jobs, and the third one in 2017 was in response to me writing about them in my journal. I wrote about Google and the 2015 interviews in my journal, and I had an email from a Google recruiter the next time I checked my email, within an hour or so. And I didn’t type that journal entry into a Google product.

I don’t want to bother descending into a conspiracy hole. It’s not that hard to imagine how what I’m describing could happen. Maybe some piece of a government spying apparatus like PRISM is being abused for private interests. Or maybe Google is a puppet just like the defense contractors.

Google has been interviewing me since 2014, the first year out of college. I didn’t think much about the first interview at the time. But they didn’t actually reject me, they recruiter/coordinator simply didn’t respond.

The second one was more significant. In fact, the first thing that the recruiter told me is that they almost extended me an offer in 2014 and he was perplexed. During the 2015 interviews,I successfully passed the interviews and was led to think I was going to get the offer. I mean, I had a decent solution for each problem, and on 3-4 of them, solved them completely such that they ran out of extra stuff to have me do on the interview quest. I understand that this is considered well above the performance required to get an offer.

But none of that mattered. What mattered is that the interview coordinator decided in advance that he didn’t like me. Or, that it was all an Orwellian puppet show. Depending on how much you want to read into the events.

When I first met with Sam Sepah, he acted in a way that seems stereotypically normal for a deaf person. The translator was also there. So, he was “speaking” in sign language, which included flipping me off and some other things like that. It was a whole show. And then he would act like he was trying to talk, and it was pretty much the vocalizations someone makes when they are trying to make fun of someone that’s developmentally challenged. This was also a show. Obviously, he seemed to be totally self-aware of what he was doing.

How could someone like that be an interview coordinator without being trained? It’s almost like his actual job is to tell people that Google thinks they are stupid (read: the R-word), but to do it in a way that is excused by a disability and that makes the victim look politically incorrect for describing what happened.

It didn’t seem significant at first, although once you already have the assumption that it is a show they are putting on, it makes sense. Google is spying on me. They know that I am trans, they know that I lost my job(s) because I was self-administering and people didn’t like the way I looked. They know that I am a Touhou fan and that I am working on a fan game.

It also seemed significant that Sam was particularly interested in communicating with me over the phone. He (meaning his coordinator) told me over the phone I didn’t get the offer. He claimed that upper management, specifically an executive hiring committee, denied my application.

When I was in a hackerspace in Orlando, in 2011/2012, I met someone that I can only describe as a defense goon. You know, a “Russian”. He told me this story. I didn’t think much about it at the time, but eventually I realized it was some kind of message: He told me that he had received a job offer at Google after finding an exploit in their software. He told me that he turned it down, and he was now on disability. 

When I was interviewing in 2015, I experienced the usual thing where people “randomly” say things around me. I heard that someone was sending an old truck to the farm to get worn down. And they bemoaned the new reality that people were waiting until they were older to get married.

Basically, it was like the movie “The Internship”. The idea being that Google is all about diversity theater, so they want a sample of every kind of personality stereotype. The only actual qualification to working at Google is being human: meaning, you are a caricature, a stereotype, and you know that Google is hiring you to put on a show.

Bohemia Interactive Simulation

I worked at Bohemia for two months (March 2014 – May 2014); it was my first full-time job after graduating.

Basically, it seemed that I was hired because I had a Touhou fan game on my resume. I also had fairly extensive C++ experience. I was basically put through a puppet show where they were supposedly trying to teach me military-style discipline by preventing me from working, and teaching me that the point of the job is to pretend to be busy and lounge around.

I had also been self administering for almost a year at the time, and it was obvious in my appearance. Basically, the coworkers there were pretty much the worst stereotype of immature gamer-bro types, and management was intentionally defective by design.

So keep that in mind when you read the summary of what I got done in two months. This was in pretty much the most toxic kind of environment you can imagine, with basically no support from anyone. Also, thankfully I thought to write the summary just a couple of weeks after quitting.


The first work was nothing. When I started, my manager was out, and I was given an interim manager, who was someone else they just hired. He literally told me to “hurry up and wait”.

The first work was on a plugin that overlaid symbology on the game in 2D and 3D. Meaning UI, but also objective markers that appear in-game. I worked on the controls, simple things at first like implementing a double click using DirectInput.

During this time I was able to use the VBS script interface to get the ID of UI elements that were clicked on. String processing was lacking in the scripting language. The return value of the function was something like “Element #42”. This got refactored to use a plugin function; the script command sends its result to a callback a command in script to send a message to the plugin and handle it natively in C++. I used boost::regex to efficiently extract the value and check it against a set of values.

This moment still stands out to me, since it was early on in the job. It was one of the first moments of open-ended problem solving. And it was pretty much met with nothing but nastiness. Basically, the coworkers simply acted like they couldn’t stand watching me be successful.

Another problem was that the UI was actually a web page, and it had drop down menus. to check click-through I would check if the web view handled the click (I think there was an isActiveWebView(mousePosX, mousePosY) or something like that in the web view library). there was a bug where if you had the drop down menu open but clicked out, the web view would lose focus, we would ignore the drop-down and click through to a UI element that happened to be right underneath it. This was an interesting bug because it actually required me to pull the web view library from source and modify it to add a function to check if there was any existent web view at that position.

It was a matter of adding one simply function to a library and rebuilding the DLL. The response to this is that I was told developing on the web view library was discouraged because it was being deprecated. My pull request to add this feature got delayed indefinitely and due to personal issues I got moved to a different program. Basically, the impression I got is that the web UI project is like a joke/toy project. And that when you reach this level of programming skill, you’re supposed to be doing something else. 

I was given the task of updating a tool that did data interchange in XML with the OBS format. It is basically a data interchange standard that allows you list out different kinds of entity types like troops and vehicles to in a vendor-neutral way, to provide interop between the different simulation/training software.

There was an interesting moment, possibly my favorite, when I fixed a bug: there was precision loss in the provided functions in a C library for getting lat/long coords of units. The issue is that you would save a map, and upon reloading it, the position of the troops had shifted, typically just off the edge of the map. The lat-long coordinates were off by a bit, but not way off and not nonsense values. I think we were getting it in float in radians, which ultimately led to the position being off by about 0.1 of a degree. I noticed that the problem was on export.

I wrote a C function that made the script call to get the units pos and convert it to lat/long degrees in one nested command and return it with full double precision. In case that sounds like a mouthful: a lot of the native plugin (C++) code had lines of VBS script, where the C code is just running a VBS script and getting the output. This script command was first run to get the position of the unit, which is then converted to global (lat-long) coordinates. Here, there was a cast from double-size to single float. There was also a command in the VBS script that did the conversion. So, by doing it in one command, nesting the call to get the unit pos inside the call to convert coordinates, it maintained double precision.

I thought this bug was funny because of a problem that I had previously encountered in the drawing plugin. They were using the modest maps library to display satellite imagery in a webview, overlaid on the map. This requires poll for the in game coords representing the location and span of the viewport. The code would then get the lat long of these and use that to set the view position of the game’s map.

Even when there was no movement of the map, this back and forth conversion resulted in a downward movement; these were using the same functions that gave me the longitude precision problem later. I eventually determined that telling it move 0,0 or update zoom based on current position would cause the unwanted scrolling.

There was another engineer that was a recent hire, and it was like a joke that he didn’t really have the intellect, but they were pretending to respect him. Basically, this was when things started to take on a more puppet show feel. It was like they were showing me, they wanted to pretend I had no experience and was junior-level, so they had someone there who actually was. Apparently, the guy spent all sorts of time trying to fix this problem, basically learning how to use a debugger, and trying to implement hacks and workarounds.

Finally I was put on the RF program, basically a radio comm plugin. There was a kind of irony to the whole thing, since VBS already had a VoN (voice over network) system built in, and it seemed pretty silly that they would add another plugin to do what’s already in the engine. Basically, the project was in early phase, and actually just involved testing a bunch of different libraries. The thing that the RF project added on top of normal voice communications was that the RF was supposed to represent in-game objects, meaning there would be range and attenuation to the transmissions, and also that RF objects could be spatial sound emitting objects in the simulation.

There was another layer of silliness. There was this commercial program they had already licensed, apparently for a different project. Not a VBS plugin, but a standalone application that runs in its own window, that basically provided VoN between computers. It had a UI that allows adding the different post-processing effects. Apparently, it was written in Java and was supposed to have an API, but the files were missing and no one knew where to find them, or if they were supposed to be there.

Basically, it seemed obvious that they were either going to use the built-in VoN system, or they were going to use this radio comm software they had already licensed. But, for the RF project, we were supposed to test this list of software.

Of all the projects on the list, pjproject was a bundling of libraries for SIP (IP phone protocol) and open source SIP/VoIP command line program pjsua. I was able to get a proof-of-concept chat program working as a standalone executable. I also got access to the raw audio buffer, allowing for processing effects. As a proof of concept, I simply used the boost mersenne twister; which effectively created white noise that could be added to the stream.

The priority, I was told, was copying that audio data and sending it to another plugin that would capture this audio data for mission replay. david and shawn were working on this plugin, and they had a script command that would read in the data as a string. To be clear, their approach was to store the audio data as a string, and then use a script command that sends strings between plugins. 

At this point, the whole thing had a puppet show feel. Like they weren’t even trying, like they were treating the job as a joke. And, as added insult, this guy is harassing me, he has a profound incompetence if he doesn’t realize you can’t do this (what happens where there’ a byte of value zero in the stream). And the rest of the team is basically totally aware of this and just amused and playing the situation.

A few minutes before the meeting, Shawn was standing over my shoulder, ordering me to hurry up and write a line calling this function he wrote. It was like a joke, that he was pretending to be stupid, and trying to harass me into acting stupid and pretending to trust him.

When I mentioned that each audio chunk would need to have a client ID, so the audio chunks from different calls didn’t get mixed up, I was told that I was thinking too far ahead. I asked to see their database schema. adding a column for client ID should have been simple. I was finally told to pull the source for the plugin. When I did, I saw that they apparently didn’t have a database system set up, looked they were just loading chunks of data from a flat file.


I still remember what my supervisor, Sultan Ansari, told me. “I expect you to give up and play around.” That pretty much sums up the experience at Bohemia.

Also, it turns out I was being spied on, even though it was not classified work. At the time I was using Google Docs (as was Bohemia using Gapps), but I have

I had been writing in my journal, describing what I was experiencing. I wrote a short story one morning about people in a sinking ship. That day, out of nowhere there is apparently building maintenance. There is the sound of a drill, and then water starts dripping from the ceiling, onto the desk of the same interim manager who told me to “hurry up and wait”.

That was only two weeks or so before I quit. Things continued to get nastier, and the place took on even more of a puppet show feel, like what I was writing was being relayed to them.

Box2.5D

When I started my first proper game project, it was in libGDX, in Java. Eventually, I realized this was silly and rebooted the project in C++11/17. libGDX includes Box2D, so I got my first exposure to the library without using it directly. Actually, I think this is a common practice, as there are a number of different game engine/libraries that similarly include it prebuilt, via interface.

One of the issues I ran into was that Box2D does not support layers. Objects take up 2D space in the physics world, and they have a type (b2Filter) that describes their identity and what they collide with. At first, this wasn’t a big deal. The first use of 2.5D was for the floor. I made the floor its own physics type, and stuff that needed to “touch” the ground would collide with it.

When I started the project, I used Chipmunk 6. I later realized that Chipmunk 7 is evolved to be more like Box2D; it adds collision filters, but removes layers. It also adds swept collisions and a kinematic mass-type.

Chipmunk had some niceties, additional “out of the box” functionality: point/shape query, callback dispatch per combination of physics types, use of double floats, and of course layers. I was able to get away with using Chipmunk without having to actually modify it. But when I got to the point where I did want to modify it, well the code is rather ugly and not as easy to modify.

It is written in C, and uses a C-style simulation of object-oriented programming:

/// Perform a rectangle query against the spatial index, calling @c func for each potential match.
static inline void cpSpatialIndexQuery(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
{
index->klass->query(index, obj, bb, func, data);
}

/// Perform a segment query against the spatial index, calling @c func for each potential match.
static inline void cpSpatialIndexSegmentQuery(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
{
index->klass->segmentQuery(index, obj, a, b, t_exit, func, data);
}

The logic of what constitutes a collision (do the objects have the same group), isn’t cleanly organized into a single function like it is in the b2 ShouldCollide. The queries that it includes don’t work the way I expect queries to work. Rather than specifying the type(s) of object to query for, it treats the query as though it is a virtual object of the provided type. Thus, similar to the pairwise callbacks, I ended up not using this functionality; all my queries were for type/group 0, so that I could check for multiple types of objects at once.

Actually, all of the physics objects had to be group zero: in Chipmunk 6, a physics object has a single type, and by default, it collides with everything of a different type, but not its own. Lots of objects of the same type need to collide. This meant a lot unnecessary callback dispatch, to return whether or not a specific combination of objects should collide. In the same way that the query system is deceptively cool — I end up having to query everything as type/group 0, so I can get all combination of objects in a single call — the callback system isn’t that useful. Since it’s in C, I can only use plain function pointers for callbacks, which means I can’t use templates functions or std::function / std::bind. So, I end up installing the callbacks for the various combinations of types, but it’s the same function pointer!

Similar to the way you have to provide a b2Transform in order to use a b2Shape, with Chipmunk you have to create a static body, and create a shape in order to do a shape query. The interface for this internally uses dynamic allocation, which isn’t necessary for the Box2.5D version.

Presumably, not all of the simplicity is really a benefit. For example, I realized my code had a problem in that certain AI functions would set the angle of agents during a callback. No issue in Chipmunk; Box2D has an assert for it. From b2’s perspective, updating the angle is updating the same linear transform as the position, and clearly the position wouldn’t be allowed to change. I didn’t find out if this was only allowed for circles (since the rotation of the circle doesn’t affect the linear transform of verticies, as it would for a polygon). (There are a number of possible solutions, such as not actually rotating the fixture, but having it be a game object field. Instead, I simply have a flag I set that indicates a physics step is running, and setPosition & setAngle will push a message to a function queue that will run after the physics step is over.

If your game is complicated enough, you will want to modify Box2D. But the good news is that it is clearly designed to be easily modifiable. However, Catto seems to be very conservative about what he wants to put in the engine. With my updates, I get the best of both worlds. All of the same functionality, but implemented with efficiency.

The Changes

First thing was to change it to use doubles; my earlier attempts first had me refactor all of the float literals to doubles. It makes logical sense, since the macro-defined type that b2 uses for its general arithmetic is a “float32”, which is misleading. But it involves changing too many lines of code, so I didn’t bother. float32 is actually double now.

Next thing was to add layers to the collision filter. While I was at it, I made all of the numbers in the b2Filter 32-bit. I already have almost 16 physics types, and at some point I plan to use more sub-types (or interface types).

const unordered_map<GType, uint32> physics_context::collisionMasks = {
    { GType::areaSensor, g(player) | g(enemy) | g(npc) | g(environment) },
    { GType::bomb, g(player) | g(enemy) | g(npc) | g(environment) | g(wall) | g(floorSegment) },
    { GType::enemy, g(player) | g(playerBullet) | g(playerGrazeRadar) | g(enemy) | g(environment) | g(npc) | g(floorSegment)| g(areaSensor) | g(wall)},
    { GType::enemyBullet, g(player) | g(playerBullet) | g(playerGrazeRadar) | g(environment) | g(wall) },
    { GType::enemySensor, g(player) | g(playerBullet) | g(enemy) | g(bomb)},
    { GType::environment, g(player) | g(playerBullet) | g(enemy) | g(enemyBullet) | g(environment) | g(wall) },
    { GType::foliage, g(player)},
    { GType::floorSegment, g(enemy) | g(environment) | g(npc) | g(player) },
    { GType::npc, g(player) | g(environment) | g(wall)},
    { GType::player, g(enemy) | g(enemyBullet) | g(environment) | g(playerPickup) | g(npc) | g(floorSegment) | g(areaSensor) | g(wall) | g(enemySensor) },
    { GType::playerPickup, g(player) },
    { GType::playerBullet, g(enemy) | g(enemyBullet) | g(environment) | g(npc) | g(wall) },
    { GType::playerGrazeRadar, g(enemyBullet) },
    { GType::wall, g(player) | g(playerBullet) | g(enemy) | g(enemyBullet) | g(environment) | g(npc) | g(floorSegment) | g(areaSensor) }
};

My previous experience with Box2D always involves defining the pairwise collisions, as shown above. Eventually, there were bugs. Certain things I forgot, like environment-bomb. In this case, the entries are supposed to be symmetrical, which means having to change two lines. Eventually, I realized two things. 1) Most of these types are a kind of physics group, “real” physics objects that aren’t supposed to go through any other “real” physics object. 2) I was wasting effort writing out the collision masks at all; the way my collision pairing was set up before, I needed to install a handler function with every combination of physics type that could collide. So, I simply changed it so that my AddHandler() function would set the appropriate bit for each physics type when installing a collision pair. For objects that should collide with each other, but which don’t need a callback (e.g. environmentObject-wall), they are all in group 1.

void PhysicsImpl::addCollide(GType a, GType b)
{
    emplaceIfEmpty(collisionMasks, a, to_uint(0));
    emplaceIfEmpty(collisionMasks, b, to_uint(0));

    collisionMasks.at(a) |= to_uint(b);
    collisionMasks.at(b) |= to_uint(a);
}

void PhysicsImpl::AddHandler(
    collision_type types,
    contact_func begin,
    contact_func end
){
    auto actual = types;
    if (actual.first > actual.second) {
        swap(actual.first, actual.second);
    }

    if (begin)
        beginContactHandlers[actual] = begin;
    if (end)
        endContactHandlers[actual] = end;

    addCollide(types.first, types.second);
}

My next issue is that my Bullets, which are sensor objects, didn’t have collision normals (for ricochet). There are actually two different issues here: 1) It turns out that b2 only computes this information (contact manifold) when it plans to use it for dynamic object collisions; i.e. at least one object is dynamic, and neither object is a sensor. 2) Even with it does compute a contact manifold between two circles, it doesn’t calculate the collision normal. Chipmunk 6 didn’t have kinematic mass-type, so my bullets were dynamic. But their mass was irrelevant, since they were also sensors.

First, I had to allow static/kinematic collisions. I don’t know why it is presumed that static/kinematic shouldn’t collide; obviously, there isn’t going to be dynamics, but there could be a game logic reason for it, just like sensors. This involves changing b2Body::ShouldCollide() – not to be confused with the b2Fixutre method of the same name. That one checks the filter; this one checks logic, like whether two fixtures are part of a constraint, or the same body. In this case, it was also unnecessarily requiring one to be dynamic. Once I changed this, I also had to change b2World::SolveTOI() – The sweep algorithm steps through current contacts, ignoring ones without dynamics; I changed the assert to a continue, so it steps past them, just as it does for sensor contacts. Contacts are used not only for dynamics, but to make sure endContact is called when appropriate.

As stated b2 normally only calculates contact manifolds for dynamic objects. We can change the code in b2Contact::Update(). Previously, it would use b2TestOverlap instead of evaluating a contact manifold. Contact manifold involves calculating a minimum separating line, and gives us contact points and collision normal. The idea is to avoid unnecessarily computing this, when we can simply check the shape overlap instead. However, I want a collision normal in all cases. This can be optimized, by setting a b2Body flag to mark whether a fixture cares about having a contact manifold (contact points & collision normal)  calculated, even if it is non-dynamic, otherwise use b2TestOverlap as before.

Queries

Box2D will assert/abort on a zero length raycast, which seems silly, since it should simply return without doing anything instead. I first noticed the bug when I had two enemies in the same position in the map. The agent’s view sensor does a raycast to check for line-of-sight.

I noticed, as I was exploring the b2 code, that it had a shape system. Shapes describe the geometric properties of a fixture. They have a size, but no position/orientation (linear transform). When I first refactored my code to use b2, I had to deal with the fact that it didn’t have a shape query (or point query). The closest thing it has is QueryAABB. But actually it isn’t the same. As the name implies, this callback actually steps through the spatial-tree (“broad-phase”), and in fact simply checks collision with the AABB of each fixture. So, my initial implementation of a rectangle query was incorrect (if used to query any kind of object that isn’t an axis-aligned box), as was my implementation of point query.

With ShapeQuery, I followed the convention of  RayCast and TestPoint; they are virtual b2Shape methods, that can take any other shape. This means each class has to dispatch the specific collide code based on its type and the type of the other shape, in a similar fashion:

bool b2CircleShape::ShapeQuery(
    const b2Shape* shape,
    const b2Transform& thisXF,
    const b2Transform& otherXF,
    int32 childIndex
) const {
    b2Manifold manifold;
    auto _type = shape->GetType();

    switch (_type)
    {
    case Type::e_circle:
        b2CollideCircles(&manifold, (b2CircleShape*)this, thisXF, (b2CircleShape*)shape, otherXF);
    break;
    case Type::e_polygon:
        b2CollidePolygonAndCircle(&manifold, (b2PolygonShape*)shape, otherXF, (b2CircleShape*)this, thisXF);
    break;
    case Type::e_edge:
        b2CollideEdgeAndCircle(&manifold, (b2EdgeShape*)shape, otherXF, (b2CircleShape*)this, thisXF);
    break;
    default:
    break;
    }

    return manifold.pointCount > 0;
}

b2World::QueryShape is similar to QueryAABB, except that it takes a b2Shape* & b2Tranform rather than an AABB. For convenience, b2Fixture::ShapeQuery wraps the call to b2Shape::ShapeQuery, also supplying the shape’s transform. As an added optimization & to reduce redudancy, I decided that I should be able to pass in a b2Filter to the query. This reduces unnecessary callback dispatch. In case you’re curious, it looks like the all of the various queries in b2World step through the broad-phase and run a callback for each applicable filter. That’s true, but note that the function that steps through the broadphase is templated, so it’s not the same as the overhead of having a callback (function pointer or vptr invoke).

I refactored filter into its own file so that it could be used in b2World.h, and made another change: I refactored the code from b2Fixture::ShouldCollide – into b2Filter::shouldCollide(). this works the same as before, it is just refactored. The new bit is the isBlankType & isQueryCollide. I want query filter semantics to work such that I can pass in a filter that represents the identity of an object, and check what it collides against (Chipmunk functionality). But mostly, what I want is to simply avoid giving the filter a type or group, and simply use the mask & layers. This is what isQueryCollide does; if it’s a blank type, it just uses the mask directly. As written, it will do positive group collision: if I give the filter a group, then it has an identity, and will collide with that same group according to the usual rules. However, as written, it doesn’t work for negative groups (which I am not currently using). I don’t see the point of using negative groups, since by default things will not collide. I can’t currently query for a negative group object using the query filter as written, since by definition the filter isn’t going to collide with a matching negative group. In this case, pass in an all 1’s bitmask, and then check for the group directly.

Once I had the structure, I refactored RayCast, QueryAABB to use filters. And then added QueryPoint.

Later, I started making more extensive use of RoomSensor. Some AI functions, and object sprite fade, depend on knowing what room an object is in compared to the player. The dumb way to do this is have a list of rectangles to represent your rooms and search through them to find a point match. The smarter way would be to organize these rectangles in a spatial-tree. Since the physics engine is already doing this, we can simply point query when we want to know what room an obje t is in. Except, we don’t even need to do that. The smartest way is to have the object collide with RoomSensor and set the current room. It already worked for agents. It didn’t work for static environmental objects.

One solution would be to have classes of objects that might be static mass-type, that need to know their room, do a point query on initialization. For certain object types that don’t really need to collide with RoomSensor, like Bomb and InventoryObject, this was the approach I used. In other cases, the idea that a static sensor needed to handle detection of static objects as a special case was too much. I changed the contact updating logic a bit more so that it would process collisions between static objects, if at least one of them is a sensor. This allows RoomSensor to collide with all environmental objects again, which it was already supposed to be doing, and not have to worry about handling static objects as a special case.

To see the complete code, check it out here: (https://github.com/afluriach/Box2.5D)

Scarlet Devil Underground – Libraries used

The project started as “simply” a Cocos2D project. Cocos2D is in turn a rather large library, not just including its 500+ compilation units, but also the pre-built libraries it includes.

The default Cocos2D project on Windows builds as a DLL. This poses a couple of problems: one is that it is a rather large library, and my project only uses a small fraction of it. The compiled release DLL is almost a dozen megabytes. The whole application exe, which includes everything that it uses from cocos2d and everything else is only 5 MB!

The other problem is that the compiler & code generator has limited ability to optimize code in different libraries. The program has no specific knowledge of the code that implements a certain function in an external library file, just that it is supposed be available in a certain library at a certain address. Even statically linking typically poses this problem: the library is compiled to optimized binary, and the application simply pastes in this code. This is solved with /LTCG (link-time code generation) and whole program optimization.

When I started on the project, I spent a fair amount of time lost in the weeds over Lua. It was nice to build it from source, so I could put timer & profiling code in Lua. I ended up not keeping any of the changes, and moreover it doesn’t really matter: although I do sort of have a working mod API, it is not ready yet. Currently, Lua is only used for the dev scripting console.

Chipmunk has sort of a similar story. I built it from source in order to get Chipmunk++ working; it later turned out that physics objects such as shapes were not getting deallocated when I expected (memory leak), and it required extra boilerplate code to write wrappers for query functions that weren’t part of the library. Solution: remove Chipmunk++ and just use Chipmunk directly. I did make one change to Chipmunk, reducing “slop” so that objects don’t sink into each other as much. Either way, once I was building it from source, I was able to turn on build optimizations.

OpenGL/GLFW – Cocos2D was originally created for iOS (OpenGL ES), and was later ported to desktop. On desktop, it uses GLFW; it handles the platform-specific details of opening a window with an OpenGL context and device input. Cocos2D includes a pre-built library, but I build it from source so that I can get max optimizations.

libnoise – I use this libary just for its Perlin noise model, which is currently only used to calculate torch light flicker.

OpenAL – (technically OpenAL-Soft) When I first tried to implement sound, I found out that the Cocos2D “sound engine” is kind of a joke. The Windows implementation didn’t even support gain or panning, i.e. not even stereo sound. First, I tried FMOD. I was able to basically get it working in a single work session, except that I didn’t get the listener orientation vectors right on the first time (the surround sound was sideways). Unfortunately, it is proprietary software. I do qualify for a free independent license; in fact, I had to sign up for one to download the API. But then when I contacted support to confirm the license, they basically told me I wasn’t welcome to use their product until I divulged all of the details about my game project. Since it was an unreleased demo, and I didn’t want to disclose details to them beforehand, I simply gave up on FMOD. OpenAL takes a bit more boilerplate code, but it basically provides the same features. Just like FMOD, DirectSound, & XAudio, it is actually a 3D sound engine. Just as my game makes use of 2.5D physics, so also it technically has 2.5D sound: most sounds play at the default y-position of 0, and that is the y-position of the listener (player’s head). However, footsteps actually play at a y-position of -1. And when I make more advanced use of 2.5D features, all sound-producing objects will have a y-position. I don’t have a pair of 3D headphones, so I wasn’t able to test this, only regular 2D surround sound.

libsndfile – The most annoying thing about OpenAL is that it doesn’t include helper code for loading audo files–seemingly obvious, basical functionality. FMOD does, but DirectSound & XAudio doesn’t either.

libgainput – GLFW supposedly supports gamepads, but it won’t detect my XBOX360 controller on either Mac or Windows. libgainput provides multi-platform gamepad support.

The only code included in the project that isn’t fully optimized is the pre-built libraries included with Cocos2D. The only one I use that happens to be a DLL is zlib. When you build Cocos2D, it in turn statically links against libraries such as libpng and freetype; the relevant parts of these libraries are in turn indirectly linked into the final product. Cocos2D uses a cache system for sprites & fonts, so each file is only loaded once–or once in a while–ideally all at once when the program is started, or between scenes. Thus, this code isn’t performance critical. Everything performance critical, code that runs every frame, is statically linked with full optimization (/O2 and /SSE2). (Note: shortly after releasing v0.1 of the demo, I did get around to statically linking OpenAL-Soft with the same optimizations as the other libraries. This also removes the requirement for the Visual C++ 2012 runtime):

Cocos2D
GLFW
Lua
Chipmunk
OpenAL
libnoise
libgainput

 

XCode (boost) static linking woes

My project has finally evolved to the point where I am pulling in the Boost libraries.

I ran into an odd problem, where I configured XCode to use a static library, yet when I tried to run the program, it halted with an error, claiming that it was trying to find a dynamic library image.

Here’s what I found out:

-When you build Boost using the default  b2 script, it actually creates both static libraries (.a) and dynamic libraries (.dylib).

When you add a library to a project, it actually generates a linker directive like -llibboost_serialization; so it actually strips the file system information. If there is a dylib file with the same name, the linker assumes you are tried to dynamically link against the file.

I was able to fix the problem by moving all of the Boost .dylib files to a separate folder that was not a linker search target.

C++11 – Concurrency

Early in the development of the project, multithreading wasn’t used. The cocos2d::Director runs the current Scene. This in turn contains the game logic. I never used the convention of cocos2d::Node <–> game object. Instead, this functionality was moved into an game word (GSpace) early on. Rather than looking up objects by Node name, or using the provided wrapper for making Nodes physics objects, I did that sepeartely. It didn’t really take much extra code, once the boilerplate for creating the different kinds of physics bodies and callbacks is set up. And, I knew early on that at some point, I would probably want to move game logic (physics and object update) out of the (application main) graphics thread.

Most of Cocos2D is not thread-safe. In particular, the Scene/Layer/Node graph, which it recursively steps through to build the OpenGL linear transform (matrix) for each element as it draws it to the screen. If you try to do certain things concurrently when cocos2d is rendering, particularly add or remove nodes, it will mess up the transform stack and crash–usuawly with some kind of memory corruption in the Renderer.

During my first attempt at this, I ran into conceptual problems: since I can’t create a cocos2d::Sprite in the game logic thread, I have to create a command to create the Sprite, and wait for it to actually be created. This also creates issues when the initialization code wants to do something to the sprite, like set its color transform or run an animation on it before it has actually been created.

The solution to the problem is rather simple, although it takes some amount of boilerplate code: since the game world logic runs in its own thread, it should not directly manipulate Cocos2D objects at all. Instead, the GSpace, which every game object has access to and is thread-safe (for them), has an interface for making graphical changes.

In GScene (my polymorphic Scene god class), I have to manage the lifecycle of the Nodes; this interface uses unique integer IDs:

typedef unsigned int SpriteID;
atomic_uint nextSpriteID = 1;
unordered_map<SpriteID, Node*> graphicsNodes;
void createSprite(SpriteID id, string path, GraphicsLayer sceneLayer, Vec2 pos, float zoom);

template<typename... Args>
inline SpriteID createSprite(void (GScene::*m)(SpriteID, Args...), Args... args)
{
	SpriteID id = gscene->getSpriteID();

	if (isMultithread())
		sceneActions.push_back(bind(m, gscene, id, args...));
	else
		(gscene->*m)(id, args...);

	return id;
}

I need the initialization code in the game object to get the sprite ID of the sprite it just queued a command to create, but that hasn’t been created yet. When a game object creates a sprite, it doesn’t run the GScene command, it pushes a function bind for that method (a message or comamnd) into a queue in the GSpace, and it will basically get run on the next graphics update in the main thread.

Thus, when the initialization code for the game object runs, it actually gets the next spriteID and provides it to the createSprite() function bind. (In case you are confused, there are number of different “create sprite” methods in GScene, for creating different kinds of Nodes like Sprites, DrawNodes, ShaderNodes, TimedLoodpAnimations, etc.) By doing so, the object’s sprite ID is initialized so that it can be used, even though the object hasn’t been created yet. i.e. It might create a GScene messagae to update the position of the Sprite on the first frame, if it is a kinematic object like a bullet that is initialized with a velocity and moves every frame. This isn’t a concern, since the GScene messages will be processed in the order they are created, so the sprite will be created before the messasgaes that try to use it. The messages that do try to use it are defensive, they look up the Node by ID in the map, and check for end/invalid iterator (i.e. invalid ID).

When the GSpace runs its update tick, which includes updating the relevant objects, it will then push all of the graphics update messages for that frame. If I didn’t do this, I would run into issues where the camera would sometimes stutter, because the message to set the Player’s position, and the message to set the camera position, didn’t run in the same frame.

Actually, at first, I didn’t have the GScene action queue set up in GSpace, only in GScene. What this means is that every call to a scene method to update the graphics would be mutex-protected, and the function would be pushed into a queue. Of course, this is potentially rather wasteful, since it involves lots of mutex acquisitions per frame, instead of just one. But it actually turned out not to have any particular performance effect.

When you have a multi-threaded game where the game logic only takes a couple of milliseconds per frame, you can turn off the frame rate limiter and run things in very fast motion. This allows me to stress test memory leaks and concurrency problems, for example with a spell card that creates a huge number of bullets. I also originally gave bullets light sources just to test the thread-safety of the GScene lightmap code (it uses a similar message-passing convention as the sprite code).

In the production code, it doesn’t use this. If multithread is being used, it runs the space thread in “lock-step” with the main thread, at the same frame rate. If the GSpace update were run at a different frame rate, the game would be in slow-motion or fast-motion. The main thread is still the master timing/update thread; it handles controls, including copying the control state of the current frame to the GSpace. before setting its condition variable.

class GScene {
//...
	unique_ptr<thread> spaceUpdateThread;
	mutex spaceUpdateConditionMutex;
	condition_variable spaceUpdateCondition;

	atomic_bool spaceUpdateToRun;
	atomic_bool isPaused;
	atomic_bool isExit;
//...
}

GScene::~GScene()
{
	isExit.store(true);
	if (App::multithread) {
		spaceUpdateCondition.notify_one();
		spaceUpdateThread->join();
	}
	delete gspace;
}

void GScene::waitForSpaceThread()
{
	if (!App::multithread) return;

	unique_lock<mutex> mlock(spaceUpdateConditionMutex);
	spaceUpdateCondition.wait(
		mlock,
		[this]()-> bool { return !spaceUpdateToRun.load(); }
	);
}

void GScene::spaceUpdateMain()
{
	while (!isExit)
	{
		unique_lock<mutex> mlock(spaceUpdateConditionMutex);
		spaceUpdateCondition.wait(
			mlock,
			[this]() -> bool { return isExit.load() || spaceUpdateToRun.load(); }
		);

		if (!isExit) {
			gspace->update();
			spaceUpdateToRun.store(false);
			spaceUpdateCondition.notify_one();
		}
	}
}

void GScene::update(float dt)
{	
	if (!isPaused) {
		ControlInfo info = App::control_register->getControlInfo();
		gspace->addObjectAction(bind(
			&GSpace::setControlInfo,
			gspace,
			info
		));

		if (App::multithread) {
			spaceUpdateToRun.store(true);
			spaceUpdateCondition.notify_one();
		}
		else {
			gspace->update();
		}

		runActions();
		checkPendingScript();
		runScriptUpdate();
		renderSpace();
	}
}

 

 

Static polymorpism

At some point, I wanted to implement objects that might or might load, rather than unconditionally creating every object in the tile map. The quick & dirty hack is to simply have objects that check if they should exist, and add themselves to the removal queue in their own init() if not. The better way is to provide an interface that can be used to determine if an object should be loaded.

I already have a reflection system, where I map the type-name of an object to a [function that wraps the] constructor that takes a map object and returns the created object:

//Adapters for mapping the name of a class to a factory adapter.
template <typename T>
constexpr GObject::AdapterType consAdapter()
{
	return [](GSpace* space, ObjectIDType id, const ValueMap& args) -> GObject* {
		return new T(space,id,args);
	};
}

template<typename T>
GObject::AdapterType conditionalLoadAdapter()
{
	return [=](GSpace* space, ObjectIDType id, const ValueMap& args) -> GObject* {
		if (!T::conditionalLoad(space, id, args) )
			return nullptr;
		else return new T(space, id, args);
	};
}

#define entry(name,cls) {name, consAdapter<cls>()}
//To make an entry where the name matches the class
#define entry_same(cls) entry(#cls, cls)
#define conditional_entry(name) {#name, conditionalLoadAdapter<name>()}

I implemented this before using SFINAE expressions & member detectors. At some point, I can refactor this to use SFINAE to check whether the class template parameter has a static conditionalLoad() method or not. But when conditionalLoadAdapter<Cls>() is instantiated, it creates a function that will call Cls::conditionalLoad with the map object, and decide statically if that object should be created.

SFINAE expressions & if constexpr – static inheritence with member detectors

In the game, I have Spell objects. It uses a polymorphic interface as you might expect. However, at some point I want to polymorphically get information about a spell before casting it (like its MP cost). This is easy enough in cases where code is checking if it can run a specific spell; that could static polymorphism just as the above case, except cost would be a static field instead of a method. But what if I want to represent a description of a spell as a polymorphic object, i.e. I want to be able to provide a spell descriptor as an parameter to an AI state, or in the case of player, I need equip slots and a set of the spells that are available to the player.

//(C++14)++ SFINAE expressions - the minimum amount of boilerplate requires to make a member detector.
#define make_static_member_detector(x) \
template<typename T> \
struct has_##x \
{ \
	template<typename U> \
	static auto test(int) -> decltype(U::x, true_type()); \
\
	template<typename> \
	static false_type test(...); \
	static constexpr bool value = is_same<decltype(test<T>(0)), true_type>::value; \
}; \

make_static_member_detector(cost)
make_static_member_detector(costType)
make_static_member_detector(icon)

class SpellDesc
{
public:
	virtual string getName() const = 0;
	virtual string getDescription() const = 0;
	virtual string getIcon() const = 0;

	virtual float getCost() const = 0;
	virtual SpellCostType getCostType() const = 0;

	virtual shared_ptr<Spell> generate(GObject* caster) = 0;
	virtual SpellGeneratorType getGenerator() = 0;
};

//Use CRTP to get static constants from Spell class.
template<class T>
class SpellDescImpl : public SpellDesc
{
public:
	virtual inline string getName() const { return T::name; }
	virtual inline string getDescription() const { return T::description; }

	virtual inline string getIcon() const {
		if constexpr(has_icon<T>::value)
			return T::icon;
		else
			return "";
	}

	virtual inline float getCost() const {
		if constexpr(has_cost<T>::value)
			return T::cost;
		else
			return 0.0f;
	}

	virtual inline SpellCostType getCostType() const {
		if constexpr(has_costType<T>::value)
			return T::costType;
		else
			return SpellCostType::none;
	}

	virtual inline shared_ptr<Spell> generate(GObject* caster){
		return make_shared<T>(caster);
	}

	virtual inline SpellGeneratorType getGenerator(){
		return make_spell_generator<T>();
	}
};

This is technically static polymorphism, except it uses template inheritence (similar to but not actually CRTP) to expose static polymorphism via regular (dynamic) polymorphic inheritence. i.e. SpellDesc is the virtual interface class, SpellDescImpl<PlayerBatMode>, SpellDescImpl<DarknessSignDemarcation>, etc. are the specific classes that implement the interface. All SpellDescImpl<SpellCls> does is make getter wrappers to the static const data from SpellCls and expose it as a virtual method. Since they simply wrap static const data, they are not mutable and only one needs to exist for each spell.

#define entry(name,cls) {name, createDesc<cls>()}
//To make an entry where the name matches the class
#define entry_same(cls) entry(#cls, cls)

template<typename T>
constexpr shared_ptr<SpellDesc> createDesc()
{
	return make_shared<SpellDescImpl<T>>();
}

const unordered_map<string, shared_ptr<SpellDesc>> Spell::spellDescriptors = {
	entry_same(DarknessSignDemarcation),
	entry_same(DarknessSignDemarcation2),
	entry_same(FireStarburst),
	entry_same(FlameFence),
	entry_same(IllusionDial),
	...
};

Curiously Recurring Template Pattern

The Agent class basically exclusively uses AttributeSystem. It provides an virtual interface that can be used for the object to provide it default attributes (max HP, agility, etc.). In the simple case, this is static const data and we can use CRTP static polymorphism to provide the attribute map regular polymorphism:

//in class Agent
virtual AttributeMap getBaseAttributes() const = 0;

//CRTP mixin
template<class T>
class BaseAttributes : virtual public Agent
{
public:
	inline BaseAttributes() {}

	inline virtual AttributeMap getBaseAttributes() const {
		return T::baseAttributes;
	}
};

class RedFairy : public Enemy, public BaseAttributes<RedFairy>
{
public:
	static const AttributeMap baseAttributes;
};

const AttributeMap RedFairy::baseAttributes = {
	{ Attribute::maxHP, 120.0f },
	{ Attribute::maxMP, 80.0f },
	{ Attribute::agility, 1.5f },
	...
};

RedFairy inherits from a template class that is templated with RedFairy. That is the definition of CRTP.

Now, what if I don’t want the agent’s starting attributes to be a class constant? Well, the simplest way to do that is to replace baseAttributes (an AttributeMap) with an unordered_map<string,AttributeMap>. In this case, we can created a number of named attribute set variations, and one can be specified in the map object.

template<class C>
class AttributesPackage : virtual public Agent
{
public:
	inline AttributesPackage(C* agent, const ValueMap& args) :
	agent(agent),
	attributes(C::baseAttributes)
	{
		string packageName = getStringOrDefault(args, "attributes_package", "");

		if (!packageName.empty())
		{
			auto it = C::attributePackages.find(packageName);
			if (it != C::attributePackages.end()) {
				attributes = it->second;
			}
		}
	}

	inline virtual AttributeMap getBaseAttributes() const {
		return attributes;
	}

protected:
	AttributeMap attributes;
	C* agent;
};

Out of an abundance of caution, it stores the AttributeMap by value. However, since attributePackages is presumed to be static const (maybe there should be a static_assert to verify), it should be able to store a const pointer to the AttributeMap instead. This is basically prototype code; I have used it to test different variations of enemy attributes, but have yet to particularly want enemies that have the same C++ class (and type_index) but different stats. And of course, all of this is just for convenience. Any Agent class can simply override getBaseAttributes() and procedurally generate its attributes. But if it doesn’t implement getBaseAttributes(), it is a virtual class that can’t be directly instantiated. There is also a convenience NoAttribute mixins that simply implements getBaseAttributes() by returning an empty AttributeMap.