Gilles Vandenoostende

Meditations on the nature of Form and Function

“Banners, Google and Anguish” or “No random numbers please, we’re Google.”

We in the online advertising industry make banners. A lot of banners. They’re a necessary evil of online advertising and annoy us all on a regular basis, but they get results, and that’s all that matters in the long run.

We don’t publish these banners ourselves, instead relying on various Media Centrals to deploy and distribute our ads to the various publishers and eventually across your favourite websites on the intertubes.

Contrary to what you might think, most banner ads aren’t just randomly cobbled together pieces of Flash animation, engineered only to aggravate. There are strict rules and regulations that enforce a level of quality and police the potential disruptiveness of banners.

You can’t, for example, open pop-ups willy-nilly, or start playing sound without user interaction. The Media Centrals enforce these rules and guidelines by decompiling every banner and checking the code for malicious scripts and the presence of certain required snippets of code for the banner to work as it’s supposed to (Well, most of them do anyway. There are a couple of shady Media Centrals out there who’ll publish anything really, but we don’t use them).

Most of the time, this all works without a problem. Aside from a few annoyances that stem from the lack of a standardized “clicktag”, the Centrals don’t needlessly scrutinize our banners. Until a few days ago, that is.

One of these Media Centrals, who, for diplomatic reasons, will not be named, apparently uses Google’s adwords guidelines as a reference for checking banners. Nothing wrong with that, Google is, for the most part, a trustworthy and efficient entity. If only it wasn’t for the small fact that their employees don’t understand basic concepts of Flash development.

And so, for the last 4 days we’ve been involved in a longwinded and frustrating bit of back-and-forth regarding some of our banner ads. They claimed infractions where there weren’t any, and we retorted. Most of the infractions the Central claimed our banners were guilty of were absolute drivel and we were well on our way to winning the argument, when they suddenly pulled this hidden beauty out of the Google Advertising Policies:

“Random Numbers: Your ad may not include code that generates or uses random numbers.” (source: adwords.google.com)

For the record, here is the offending piece of code that caused the problem:

TweenLite.to(mc, 1, {height: 0, delay: Math.random()*.5});

All it did was to delay a certain animation with a random amount of time to create a more natural-seeming animation. It’s a piece of code that’s used all the time to create dynamic scripted animations in Flash banners, without incident.

To claim this as a security risk is seriously demonstrating a sound lack of judgment, both on accounts of the Central AND of Google. The rest of the policies in that document are all common sense standards, but that “random” clause seems strangely out of place.

The end result is a much duller animation and a lot of time lost. We’re still sorting this out with all the involved parties, but I hope Google takes notice and removes that silly clause from an otherwise impeccable policy.

Learning rails - updating to 2.2

One of my New Years resolutions is to learn Ruby On Rails, the hip young web development framework popularized by sites and applications such as Basecamp or Twitter. Being on a mac, installing and running rails is dead easy, just a few terminal commands. I’d toyed around with it a few months ago, but didn’t get too far.But now, with the new 2.2 version out I decided to give it another go.I tried updating to the latest version with the terminal command:

sudo gem update –system

to get the RubyGems to update to 1.3.1. However, the command simply returned:

nothing to update

But checks revealed it was still at v.1.2, so there clearly WAS still something to update. A couple of google searches later, and I’d found the solution to properly update RubyGems to the correct version:

sudo gem install rubygems-updatesudo update_rubygems

Now, if you’ll excuse me, I’ve got a train to catch! *groan*

“SecurityError: Error #2000: No active security context.”

I encountered a strange bug in Flash player 10 today. A simple flash animation, scripted in AS3, which gave no errors inside the CS3 IDE threw the following error when run inside the browser (which was running flash player 10):

SecurityError: Error #2000: No active security context.

Now, the animation itself is completely static, no external content or links of any kind, so this error threw me off. A quick google search later, and I had tracked the bug down the the following innocuous line of code:

setTimeout(_launchTimer.start, 3000);

“_launchTimer” being a simple Timer object. The workaround, was to wrap the call to the timer’s start() function in an anonymous function, like so:

setTimeout(function():void{_launchTimer.start();}, 3000);

Very strange indeed… It seems like FP10 doesn’t like setTimout calling functions that aren’t in the same scope from where the setTimeout is being called for some reason. I’m blogging about this so that hopefully, other developers tearing their hair out at this strange bug might be helped by this.
Also, happy 2009 everybody!

Adobe MAX Autopsy report: Flash Catalyst

Crossposted from pool.proximity.be.

As you may have seen last week, we (Matthias, Pieter and myself) have had the privilege of attending Adobe MAX in the lovely (yet very wet and cold this time of year) city of Milan, Italy.

MAX is Adobe’s yearly conference, held in North America, Europe and Japan, focused on presenting the latest technological advances made by Adobe, as well as providing education on the software currently available. The sessions are presented both by Adobe “evangelists” and members from the community.

In this first blog post, I’ll be talking about the big thing of the show this year, namely Adobe’s upcoming new entry in the front-end webdeveloper market-segment : Flash Catalyst. Read on after the jump.

Read the rest of this entry »

Pet peeve #392 automatic region specific localization

As you may or may not know, Belgium is a funny old country. Not satisfied with just one national language, we decided to have 3 of the buggers, namely Dutch, French and German - with English as an unofficial fourth. This means that most of us are quite gifted multi-linguists, and can read, understand and write several of the 4 languages with varying degrees of success.

The peeve I have though, is that while the majority of the Belgian population is flemish (i.e. dutch-speaking), many international websites/applications throw all of us in with the french speaking lot by automatically changing the site’s language to french, based solely on the region from which we’re surfing.This became quite apparent this morning when I was checking the Facebook app on my iPod Touch, when I noticed that it had decided to automatically assume I was a french speaking belgian, and had translated the entire app since the last update.

As far as I could tell there was no immediate way to change the language back to english, so now I’m stuck with a francophone version of Facebook. It’s not that it’s a huge inconvenience - I can understand french just fine - but I just prefer to enjoy everything in it’s original language where possible. I don’t watch dubbed movies, or read translated books unless it was originally created in a language that I don’t know. I just feel that certain semantics are always lost in translation. So that’s why I want to use the Facebook app in English, thank you very much.The website itself seems to be spared this inconvenience for now.

Now, I’m all for localization - in fact I’ve written an actionscript framework to facilitate different flash site language version - but let’s not take away the choice of language from the user shall we?

Quick tip of the day: Local connection across security sandboxes

If you’re trying to make a flash site or AIR application that uses localconnection to connect to other sites, please remember to prefix your connection-name with an underscore.The reason for this, is that unless the name starts with a “_”, the flash/AIR runtime will prefix the connection-name with the name of the current domain and a colon (i.e. “domain:connectionname”), and as such, crossdomain/-sandbox connections will ultimately fail. Adding an underscore prevents this from happening, which allows you to do some cool stuff, like having a website interact with a desktop application - which is exactly what I’m trying to achieve with MultiLang.More on that later, for now, just enjoy the tip ;)

Pepsi 4MAX shortlisted at Cannes!

Cannes 2008 Shortlist

Woohoo! Last year, some of you might remember that I helped to design and develop the 4MAX website - more specifically the multiplayer connect-4 game, and I just wanted to share that we’ve just been shortlisted, twice, at the Cannes Lions 2008. We’ve been nominated in the Media section, under the Fast Moving Consumer Goods and Best Use of Ambient Media, Large Scale -categories.

Another Proximity BBDO project, Dodge Dare Days has also been nominated, so congratulations to that team as well!

4MAX has won a lot of awards/attention over the last few months, here’s a little recap:

Eurobest 2008

  • Media finalist, Mixed Media
  • Media finalist, Best Use of Special Events
  • Interactive finalist, Interactive Campaigns

Proximity Worldwide 2008 (Milan)

  • Silver for Pepsi 4Max

Best of Activation awards 2008

  • Gold Advertisers Jury, Non-Alcoholic Beverages
  • Gold Press Jury
  • Bronze Creative Jury

Whew, that’s a lot of awards/nominations for one single project! We’ve also won Silver at Best of Activation for KBC Word Rockster, from the advertisers Jury, in the Services category. I designed and developed said site, with the exception of the character designs/animations, which were provided by Eugene and Louise.

For a 22 year old guy who’s only been doing this gig professionally for a little over a year and a half, I’d say I can be quite pleased with myself ;) Right, now back to some serious coding. More on this as it develops.

AnimationSlicer

Hey all, long time no post. I’ve been very busy, what with my trip to Las Vegas for MIX08 (I still have to write a debrief for that), then a trip to San Francisco (still have to clean up and put my photos online), and a lot of hard work back at Proximity BBDO. But I’ve got some time now, so I decided to share something cool with you guys.

Any Flashdeveloper worth his salt knows the benifits (and shortcomings) of the cacheAsBitmap property. This property, introduced in Flash Player 8 3 years ago, enables the flash player to store a complex vector shape in its memory as a single rendered bitmapData object. The benifit of this, is rather than having to re-calculate/redraw every vector point manually every single frame, flash now only has to juggle 2 values, namely the x and y properties, of the cached object, resulting in massive performance gains in some cases.

cacheAsBitmap has a few downsides though, most noteably, the fact that as soon as you begin to scale or rotate your movieclip/sprite all performance gains are gone, but this is an acceptable sacrifice for most cases where cacheAsBitmap would be used, i.e. instances where there are lots of things moving on screen. More annoying though, is the fact that you can’t cache animated movieclips.

The reason I’m telling you all this, is because I recently had to create a crowdsurfing game for Proximity BBDO. You can see the result at http://www.wipbinnenmetkbc.be/ (just click the “Speel & Win” bubble to start the game). An obvious design challenge I faced was the fact that I had to get dozens of fully animated characters on screen at playable framerates. The solution for this though, was found in the first version of my special AnimationSlicer package.

The implementation couldn’t be simpler; You create a new animationslicer object, you assign it a movieclip containing timeline based animations (sorry, no support for scripted animations at this time), and it’ll automatically cache every single frame in the animation as a bitmapData object. Then, once it’s finished caching the entire movieclip, it simply replaces the movieclip on the stage and uses an internal timer to play the cached frames at a specified framerate, which can differ from the stage’s framerate - i.e. the game runs at 30fps, but all animations can run at 24fps, again gaining performance. Here’s some sample code:

import com.vandenoostende.animation.slicer.AnimationSlicer;

/**
*
*@param movieclip The movieclip containing the animation to be cached.
*@param framerate The framerate the animation should run at. If 0, it runs at the stage’s framerate
*@param id The id for the animation. The animationSlicer then stores the cached frames in a
* central repository under this id and re-uses the frames for future animations
* cached under the same id. If empty, it just creates a new set of cached frames
* every time. OPTIONAL
*/

function sliceAnimation(movieclip:MovieClip, framerate:int = 0, id:String = ""):AnimationSlicer{
return new AnimationSlicer(movieclip, true, true, framerate, id);
}

//slice the movieclip
sliceAnimation(animation_mc, 30, "animation_mc");

This has a lot of advantages, the biggest of all being speed. Compare these 2 examples to see the immediate benifit from using my class
(be aware, it is possible that your computer might hang for a few moments when opening the ‘With’ link, as the site caches the animations first time round, I solved this in the game by writing a special preloader for the game which precached all required animations before starting the game proper) :

  1. With AnimationSlicer
  2. Without AnimationSlicer

(the animations are made by Eugene and Louise, freelance animators/designers from Antwerp, Belgium)As you can see, in some cases, this results in a nearly 500% increase in performance (5 fps vs. 24 fps). Of course, there are a couple of drawbacks:

1. Memory usage. As the slicer stores every single frame as an uncompressed bitmapdata object, this can get your memory usage quite out of hand if you’re not careful. I did forsee the ability to re-use cached frames between the same movieclips, so once animation has been cached you can re-use it across the entire site with zero memory increase and zero lag.
2. Initial caching phase. The first time you create an AnimationSlicer for a movieclip it runs through the animation step by step at 24 frames per second, regardless of the stage’s framerate. This was a concious design decision on my part, and serves to relieve the strain on the CPU during the caching phase. The animationslicer does dispatch a few events to let you know when the animation has finished caching. That way you can do a silent/invisible pre-cache without the user being exposed to jerky animations.
3. No scripted animation. As mentioned above, no scripting is supported at the moment. The animationSlicer does have most properties and methods a MovieClip does (i.e. gotoAndStop(), gotoAndPlay(), nextFrame(), and currentFrame, currentFrameLabel properties, as well as dispatching an ENTER_FRAME event, so you could easily write a wrapper class for the AnimationSlicer which turns the cached animation into something more controllable. I created several scripted animationloops for the game using this technique.
4. Same limitations as cachAsBitmap. So no scaling or rotating the animation after it’s been cached, or else you might get aliased pixels (jaggies).

If you can live with these shortcomings (some of which might be fixed in future releases, especially point 2 or 3), then you can reap the benifits of cached animations!

Click here to download. (sources and examples)


Creative Commons License

This work, unless otherwise expressly stated, is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 2.0 Belgium License