Installing an Air Conditioner in a Window That Barely Opens
Mon 26 May 2014
Michael Labbe
#handy
Around here, air conditioning is almost never part of a deal when you buy or rent an apartment. I converted a spare bedroom into an office, which was great until the sun hit and it turned into a virtual sauna.
In getting an AC unit installed, I was faced with an interesting problem: I had windows that opened up and out at an angle, but just barely. The glass is held in place by metal framing, making it intractable to drill through.
I contacted a few self-described handymen who quoted me anywhere from 50 to 500 dollars and proposed building mounts out of wood, metal, or just plain crazy gluing the AC unit to the frame (!). No two quotes proposed the same solution. That’s when I knew the experience I could hire to solve the problem would be improvising on the job. I had an idea of my own which was cheap and easy to test, so I decided to try it out.
The approach? Industrial strength Velcro® and acrylic glass.
I recently had success mounting rear speakers on stands with Velcro. This isn’t the stuff you kept your shoes on with in second grade. Industrial strength Velcro is at least two inches wide and comes in rolls measured by the foot. The rear side has very sticky glue and can easily attach to the metal frame of your window.
Here’s the finished product, with instructions below:

The total cost was under $40, took two hours, and has worked for me for two summers. I can remove the acrylic glass by tearing away at the Velcro in seconds, making end-of-season take down a five minute chore.
Here is what you need:
- One sheet of acrylic glass — large enough to cover the entire open window.
- Industrial Velcro to run up the sides of the window. The wider, the better. More on this later.
- A circular saw to cut the acrylic glass, or if you’re like me and don’t have a workbench, a scouring knife and some personal tenacity.
- A floor AC unit. Window mounted ones will not work, as they need to hang out too far and will interfere with your barely-opening window.
Step One
Mount the plastic exhaust panel on your window. Your AC panel instructions will tell you to screw it into the wall. This is intractable — we want to avoid damaging our windows by drilling into metal. Instead, throw down a few inches of that sweet, sweet Velcro and the exhaust panel stays in place:

Step Two
Measure your window and cut the acrylic glass to fit.
Unfortunately, I didn’t have a workbench, and didn’t feel like making my way to the ‘burbs to use one, so I used a table on my deck. I scoured the glass with a scouring knife and filed the edges down. This was not easy, and I was punished for my laziness and impatience by grinding away for almost an hour.
The glass:

The scouring:

Step Three
Now that your acrylic glass is cut to fit and filed down for smoothness, attach Velcro to the edges and mount it in the window. You want it to fit in so that it is overlapping the metal frame on the top and sides, with the bottom seating directly into the AC exhaust mount.
Here’s a closeup of Velcro mounted to the metal window edge:

Bonus Tips
At this point, you can fire up the AC and breathe again, but you should keep these tips in mind:
- If you have a wide enough window, consider getting an AC unit that draws its air from outside instead of from in your house. AC units with two pipes are always going to produce a colder room than one. Otherwise, you are drawing warm air from the rest of your apartment when your AC creates a vacuum by expelling the hot air you are aiming to remove from your room.
- You want your Velcro to be as wide as possible. When the sun hits the metal frame, it heats up and some of the glue will melt. If you’ve done your job, you should have a very firm and sturdy acrylic frame, but after a couple of years, the glue will be tired and you will need to replace the Velcro.
- Seriously, scouring acrylic with a knife is a pain. Get a table saw.
Patterns for Multiplayer Game Variety
Mon 28 April 2014
Michael Labbe
#code
Game Rules
So you’ve made a super fun multiplayer game and you want to expand it by adding game modes, tweaks and so forth. Here are some possible do’s and don’ts that allow for rapid expansion and moddability.
The approach of branching your game logic by game modes makes your code unexpandable. Consider:
if ( gamemode == MODE_DEATHMATCH ) { DisplayFreeForAllScoreboard();} else if ( gamemode == MODE_CTF || gamemode == MODE_TEAMDM ) { DisplayTeamScoreboard();}This works with a finite number of game modes, but it makes modding hard. It also makes expanding the number of game modes difficult. A better approach is to create an abstract game rules base class which is derived for each game mode.
class IGameRules{public: virtual int GetTeamCount( void ) const = 0;};class GameRulesDeathmatch : public IGameRules{public: int GetTeamCount( void ) const { return 1; }};class GameRulesCTF : public IGameRules{public: int GetTeamCount( void ) const { return 2; }};Now you can simply write the game logic as:
if ( gamemode.GetTeamCount() == 1 ) { DisplayFreeForAllScoreboard();} else if ( gamemode.GetTeamCount() == 2 ) { DisplayTeamScoreboard();}This approach lets you easily extend your game code to new game mode variants by simply deriving from the IGameRules hierarchy.
Modifiers
Unreal gets credit for being the first game to use modifiers. Modifiers are tweaks to tuning values — they are not holistic mods. This lets the player apply, for example, low gravity and instagib at the same time, by selecting two different mods. (Thereby ruining my vanilla experience, grr…)
This is pretty simple: apply modifiers from top-to-bottom order. Call out conflicts. Unreal did modifier selection with a complete UI in the late 90s.
Combine the Two
Consider exposing game rules methods as modifier tunable values. For example, if you have a game rule bool IsElimination(), which causes players to not respawn after they die, exposing this as a modifier value will allow a modder to go in and take an existing game mode, say, Team DM, and turn it into an elimination mode. Boom! A modder just recreated a simple Clan Arena mode with a text file and no need to learn a scripting language.
Good Code Doesn’t Tolerate Bad Data
Mon 07 April 2014
Michael Labbe
#code
When something is not right in your game’s simulation, complaining loudly to the developer-culprit as early as possible roots out issues. Production code that tolerates failure at a data processing level while producing a completely errant play experience saves no time.
If a developer commits errant content and time goes by, the cost of fixing it goes up. The developer may have forgotten the intricacies of their contribution, or worse, be on a different project. The content may need to be regenerated from source files in a manner that is either unclear or is not available to the person who deals with the bug. The symptoms of the bug may be disconnected from the problem. For example, I have seen a non-normative bitrate in an audio file corrupt a stack, becoming a time consuming issue to track down.
When you realize a subtle warning was added to a programmer-facing debug log that stated the issue, but was ignored by the developer who added the file, it is time to look for better solutions.
Throwing assert messages when an invalid programmatic state is hit is a common practice for trapping code logic errors. Extending this diagnostic trip-up to content issues for non-programmers is a useful tool for getting in developers faces at the right moment in time — when the developer is trying out their new content for the first time.
What can a content alert do for you?
-
Provide validation that content is consistent with the engine’s expectations. For example, if a PNG has a corrupt header, there is nothing wrong with the PNG loader logic. It’s just dealing with questionable data. Sure, it could probably display something if the rest of the file is structured properly, but this is indicative of a bad file and you need to get this up in developer faces before they move on to other challenges.
-
Test code that runs as soon as possible. If you have a cooking stage that runs over your content, throw your alerts then. If you do not, do it at level load. Validate everything.
-
A way of passing a diagnostic message on to the content creator as soon as possible. Short circuit the QA/bug tracker loop for content creators (level designers, artists, audio engineers). This saves time by providing the opportunity for a specific diagnostic message that gets to the root of the issue. Bug reports from QA describe the symptom of the issue and usually lack direct diagnostic messages. This is much quicker.
Real-World Content Asserts
Resource r = LoadResource();if ( r.GetBPP() != 32 ) ContentFail( "Resource has invalid bitdepth" );ContentFail is a preprocessor macro which, in developer-friendly builds, accumulates a descriptive list of issues for the content creator.
How to implement ContentFail in C
You know which builds are going to developers and which are going to the end user. Use conditional compilation to optionally throw a message up in front of the user.
#if ENABLE_CONTENT_DIAGNOSTICS#define ContentFail(msg) (void)(HandleContentFail( __FILE__, __LINE__, msg ) )#else#define ContentFail(msg) ((void)0)#endifvoid HandleContentFail( const char *file, int line, const char *failmsg ){ /* Append failmsg to diagnostic list here */}In this implementation, ENABLE_CONTENT_DIAGNOSTICS is on for all builds going to developers and, presumably, off for ship. You accumulate a list of issues and push them to a dialog box after a level load, treat them as compile warnings in a build process or purposely sound an alarm in the cook process.
One benefit of compiling out the content asserts in release builds is avoiding the fear that you are adding a ton of diagnostic strings to shipping code. Go nuts here — be as descriptive and as helpful as possible.
None of this is particularly fancy, complicated or tricky to implement in any language. It amounts to adopting a philosophy of enforcing correctness as early as possible in the design of your tools.
Edit: thanks to @datgame for pointing out a bug in the example code. It has been fixed!