Nonsense Waffle with Meteor

Demo: nonsense-waffle.meteor.com
Repo: github.com/kalinr/nonsense-waffle

Nonsense Waffle is a word game that I started building as a personal project in February of 2015 using the new real-time Node.js based framework called Meteor.

In this game, players compete by compiling randomly generated words to create funny phrases then try to sell their ideas in the most humorous ways possible, in sort of an advanced like button and popularity challenge with a lot of role-playing elements that’s all based on silly nonsense.

The game is in its infancy right now, but I do have a working demo up and running at nonsense-waffle.meteor.com, with the core functionality to draw word cards and add them together to create what I’m calling a “waffle”. It also has a tab to view those waffles. The admin tab will eventually be only available to game administrators (myself), where I can add new words to the collection or get a JSON backup of the MongoDB collections. If I continue with this project I will be adding user accounts, experience points, searches, challenges, categories, tags, Facebook and g+ integration, animations, a tutorial, chat rooms and much more.

If you open the application on two different devices or tabs, you can witness one of the wonders of the Meteor platform as everything magically updates across the different instances without so much as coding an AJAX call. I can understand why people are saying Meteor is the future of web development.

The first version of this game I built in 2011 using Adobe Flash Builder/Flex with a Python backend running on Google App Engine. You can view a disorganized dump of my workspace from that project in this github repository: github.com/kalinr/Wacky-Words-Facebook-MMO. Back then I was calling this project Wacky Words, but I’m relatively sure now that I’m going to stick with calling it Nonsense Waffle because the game is all about nonsense and waffles are delicious.

Actually, that’s sort of a lie. After renaming this game, I looked up “waffle” and found that the British definition is “to speak or write, especially at great length, without saying anything important or useful.” That is totally the embodiment of this game!

The rough draft of the view page with a few of the waffles I created
The rough draft of the view page with a few of the waffles I created

AS2 Slot Machine Number Scroll Class

An AS2 class that allows you to easily create and animate a slot machine style number scroller with two simple function calls.

Here is an AS2 class that allows you to easily create and animate a slot machine style number scroller with two simple function calls. You can scroll numbers up or down by any increment, stopping and starting on any number. It contains many options using an optional greensock-style vars object. You can fine-tune animation speeds and heights individually for each character, or set a delay or onComplete function. Requires the GreenSock tweening engine.

Here’s an example. Note you can style or move the characters around on the stage virtually any way you’d like.

Download class file and FLA. Note: the SWF will work, but you will need to download greensock for the FLA to publish correctly.

And here is the class itself, comments and everything.

/**

* VERSION: 1.0

* DATE: 2011-01-18

* AS2

* AUTHOR: Kalin Ringkvist

**/

import com.greensock.TweenLite;

import com.greensock.easing.Sine;

import mx.utils.Delegate;

import com.greensock.plugins.TweenPlugin;

import com.greensock.plugins.BlurFilterPlugin;

/**

* 	NumberScroll is a class designed to conveniently scroll a series of numbers up and down, as in a slot machine or price countdown animation

*

*

* 	To use this class, first create several movieClips, one for each digit in the number you wish to animate, each containing a textField named 'txt'.

*	If you want to scroll from 1 up to 999, or from 200 down to 10, you would place three movieClips on the stage. These movieClips can be identical or

*	different from each other, and can contain other content, just as long as they contain a textField named 'txt'. Be sure the textFields also have the

*	font properly embedded to show numbers.

*

*	Next, create the NumberScroll object, passing in an array containing your movieClips, and an optional vars object to set options.

*	Then, call startScroll(), along with the same optional vars object to begin the number scrolling

*

*	<b>EXAMPLE:</b><br /><br /><code>

*	import com.NumberScroll;

*

*	//create the NumberScroll object, passing in an array of movieClips that each contain a textField named 'txt'. In this case, the movieClips are all inside a movieClip called 'numbers'.

*	//the second paramater (1), sets the starting value

*	var ns = new NumberScroll([numbers.txt1, numbers.txt2, numbers.txt3, numbers.txt4, numbers.txt5], 1);

*

*	//start the scrolling. The object parameter is optional, but in this example, we use it to set the end value to 40, delay 2 seconds before beginning, set background textFields to %30 opacity,

*	//set delay of .4 of a second between each iteration, call scroll99() upon animation completion, count by 1,

*	//set animation height for each individual clip to 80, 80, 60, 40 and 20 pixels, and set the animation duration to 2 seconds, 1 second, 1 second, .8 of a second and .4 of a second

*	ns.startScroll({endNum:40, delay:2, backgroundTextAlpha:30, incrementDelay:.4, onComplete:scroll99, increment:1, animHeight:[80, 80, 60, 40, 20], animDuration:[2, 1, 1, .8, .4]});

*

*

*

*</code>

**/

class com.NumberScroll{

private var textBGArray:Array;//the textFields that sit in the background

private var textArray:Array;//first set of moving textfields

private var text2Array:Array;//second set of moving texfields

private var parentMC:MovieClip;//the parent of the movieClips that are passed in

private var startNum:Number;

private var endNum:Number = 0;

private var curNum:Number;

private var curNumString:String;

private var numDigits:Number;//the number of digits in the current number

private var digitSpaces:String = "";//the string we add to the beginning of curNumString to insure it has the proper number of digits

private var delay:Number = 0;//delay before the main animation starts

private var incrementDelay:Number = 200;//delay between each increment, converted to milliseconds

private var increment:Number = -1;//the amount to count by, defaults to decrementing by one

private var backgroundTextAlpha:Number = 0;//the transparency of the background digits

private var animHeight:Array = new Array();//array of heights for the new number animation; must have one item for each textField movieClip

private var animDuration:Array = new Array();//array of animation duration values for each textField moviClip

private var onComplete:Function;//the function to call when the final number is done animating in

private var origYArr:Array;//the Y values for each of our passed in textField movieClips

private var readyToComplete:Boolean = false;//tells the tween complete listener whether we are ready to fire the onComplete function

private var countInt:Number;//the AS2 interval we use to call the animations

private var goingDown:Boolean = true;//whether or not we are incrementing or decrementing

private var arrLength:Number;//the number of textField movieClips in our animation

private var varList = new Array("endNum", "delay", "incrementDelay", "increment", "onComplete", "animHeight", "animDuration", "backgroundTextAlpha");

/**

* Constructor <br /><br />

*

* <b>SPECIAL PROPERTIES</b><br />

* The following special properties may be passed in via the constructor's or startScroll()'s vars parameter, like

* <code>new NumberScroll({endNum:100, onComplete:myFunction, increment:-5, animDuration:[2, 1, .5, .2, .1]})</code>

*

* 	<ul>

* 	<li><b> endNum : Number</b>					The number you want the animation to end on</li>

*

*  <li><b> delay : Number</b> 					The number of seconds to wait before beginning the animation</li>

*

*  <li><b> incrementDelay : Number</b> 		The delay in seconds between each count iteration</li>

*

*  <li><b> increment : Number</b> 				The amount to add on each increment (use negative numbers to count down)</li>

*

*  <li><b> onComplete : Function</b> 			The function that will be called when the animation completes</li>

*

*  <li><b> animHeight : Array</b> 				An array of numbers, one for each digit, to define the animation height for each individual character</li>

*

*  <li><b> animDuration : Array</b> 			An array of numbers, one for each digit, to define the animation duration for each individual character</li>

*

*  <li><b> backgroundTextAlpha : Number</b> 	Sets the alpha of the digit that sits in the background</li>

*

*

* 	</ul>

*

* @param vars optionally pass in special properties like

*/

public function NumberScroll(_textArray:Array, _startNum:Number, vars:Object){

TweenPlugin.activate([BlurFilterPlugin]);

textBGArray = _textArray;//setup our new variables

text2Array = new Array();

textArray = new Array();

origYArr = new Array();

parentMC = textBGArray[0]._parent;

startNum = _startNum;

curNum = _startNum;

curNumString = _startNum.toString();

numDigits = textBGArray.length;

var adjustLength:Number = numDigits - curNumString.length;//if we're counting up, see if the start value has fewer digits than the end value

for(var i=0; i < adjustLength; i++){//loop once for every digit difference and add a space each time

digitSpaces = digitSpaces + " ";

}

curNumString = digitSpaces + curNumString;

arrLength = textBGArray.length;

parseVars(vars);//convert any optional passed in vars to be saved till a startScroll() call

for(var i=0; i<arrLength; i++){

duplicateMovieClip(textBGArray[i], "scrollMC_" + i, parentMC.getNextHighestDepth());

textArray[i] = parentMC["scrollMC_" + i];//add the first animation copy to our list

duplicateMovieClip(textBGArray[i], "scrollMC2_" + i, parentMC.getNextHighestDepth());

text2Array[i] = parentMC["scrollMC2_" + i];//add the second animation copy to our list

text2Array[i]._alpha = 0;

textBGArray[i].txt.text = curNumString.substr(i, 1);//set the BG array to correct number

textBGArray[i]._alpha = 0;//we don't actually need this until the animation starts so we hide it in case we don't want it at all

textArray[i].txt.text = curNumString.substr(i, 1);//set the main array to correct number

textArray[i].isCurrent = true;//tells which copy is the one currently visible so we know which to animate out and which to animate in

text2Array[i].isCurrent = false;

origYArr[i] = textArray[i]._y;//record the original Y positions of the numbers

if(animHeight[i] == undefined){//set animation height and duration defaults if we didn't get a proper value passed through the vars object

animHeight[i] = 20;

}

if(animDuration[i] == undefined){

animDuration[i] = .2;

}

}

}

/**

* main function that starts the animation

*

* @param vars object containing any of the optional variables listed for constructor function

*/

public function startScroll(vars:Object){

if(vars.delay || delay){//if we have a delay, delay the beginning of the animation

delay = vars.delay;

TweenLite.delayedCall(delay, Delegate.create(this, startInterval), [vars]);

}else{

startInterval(vars);

}

}

private function parseVars(vars:Object){//loops through our list of allowed vars and sets the ones that have been passed in

for(var i=0; i<varList.length; i++){

if(vars[varList[i]] != undefined){

this[varList[i]] = vars[varList[i]];

}

}

}

/**

* @private

* begins the animation process after the initial delay

*

*/

private function startInterval(vars){

parseVars(vars);

if(endNum > curNum){//determine if we're going up or down

goingDown = false;

}

countInt = setInterval(this, "updateNumber", incrementDelay*1000);//begin the interval

}

/**

* @private

* function that runs once per number increment

*

*/

private function updateNumber(){

curNum += increment;//increment our number

if(curNum <= endNum == goingDown){//if curNum is equal to or moved beyond endNum

curNum = endNum;//make it match

readyToComplete = true;//tell the final tween we're ready to fire the onComplete func

clearInterval(countInt);//and delete the interval so this iteration is our last

}

curNumString = curNum.toString();

matchDigits();

for(var i=0; i<arrLength; i++){//loop once for every textField movieclip

var newMC:MovieClip = text2Array[i];

var curMC:MovieClip = textArray[i];

if(newMC.isCurrent){//figure out which clip is the current one and which is the new one, since they alternate roles

newMC = textArray[i];

curMC = text2Array[i];

}

if(curMC.txt.text != curNumString.substr(i, 1)){

newMC.txt.text = curNumString.substr(i, 1);//set the new clip to the correct text

textBGArray[i].txt.text = curNumString.substr(i, 1);//set background to correct text

textBGArray[i]._alpha = backgroundTextAlpha;

setupClipPair(curMC, newMC, i);//setup starting values and engage animation

}

}

}

/**

* @private

* adjusts curNumString to have the correct number of digits in case number drops a digit, e.g. when it goes from 100 to 99

*

*/

private function matchDigits(){

if(goingDown){

if(curNumString.length + digitSpaces.length < numDigits){

digitSpaces = digitSpaces + " ";

}

}else{//if we're moving up, we may need to strip a space instead of add one

if(curNumString.length + digitSpaces.length > numDigits){

digitSpaces = digitSpaces.substr(0, digitSpaces.length - 1);

}

}

curNumString = digitSpaces + curNumString;

}

/**

* @private

* sets up the pair of animation clips and engages the animation. runs after its been determined which is new and which is current

*

* @param curMC the movieClip that is currently sitting, displaying the current number that is about to be replaced

* @param newMC the movieClip that will be animated in to replace curMC

* @param index the index of these clips in their clip arrays so we can reference matching values for animHeigh, origY, etc

*/

private function setupClipPair(curMC:MovieClip, newMC:MovieClip, index:Number){//checks if it's necessary, then sets up the pair of animation clips  and engages the animation. runs after its been determined which is new and which is current

newMC._y = origYArr[index] - animHeight[index];//return new clip to its top, invisible position

newMC._alpha = 0;

TweenLite.to(newMC, 0, {blurFilter:{blurX:10, blurY:50}});//instantly blur so its ready to fade in

//now we actually animate the new number in

TweenLite.to(newMC, animDuration[index], {_alpha:100, _y:origYArr[index], ease:Sine.easeInOut, blurFilter:{blurX:0, blurY:0}, onComplete:Delegate.create(this, tweenComplete)});

//animate the old one out

TweenLite.to(curMC, animDuration[index], {_alpha:0, _y:origYArr[index] + animHeight[index], ease:Sine.easeInOut, blurFilter:{blurX:10, blurY:50}});

curMC.isCurrent = false;

newMC.isCurrent = true;

}

private function tweenComplete(){

if(readyToComplete){

readyToComplete = false;

onComplete();

}

}

}

 

AS3 Character Text Effect Class

This is a class I built in 2008 to animate any textfield, character by character. All you have to do is create a textfield, enter the text you wish to animate, then pass that into the class and it will animate each individual character in or out based on different parameters.

This is a class I built in 2008 to animate any textfield, character by character. All you have to do is create a textfield, enter the text you wish to animate, then pass that into the class and it will make a nearly exact duplicate of the textfield, with each individual character in its own movieclip, then animate them in or out based on different parameters. It includes a dozen or so animation options. Go ahead and download the source and feel free to use this code wherever you like.

 

 

Retail Price Calculator

In 2009 I made this Walmart price calculator/wishlist banner in AS3. The data comes from an XML file and a folder full of merchandise images.

In 2009 I made this Walmart wishlist banner in AS3. The data comes from an XML file and a folder full of merchandise images. It had two versions, one calculated price, the other served as a wish list without prices.

Flex FaceBook Image App

In early 2010, to learn the FaceBook API, I built a Flex application to allow you to quickly look through all your friends photos in one easy location.

In early 2010, to learn the FaceBook API, I built a Flex application to allow you to quickly look through all your friends photos in one easy location. It no longer works because the server was taken down and FaceBook changed their API, but here’s a video to give you an idea of what it was.

AS3 QuickTimer Class

I needed an easy way to see how long my animations were taking, but something that could be quickly turned off when I needed to publish for a client review. I came up with this simple QuickTimer class.

When making banner ads, often times you need to condense your animations into a short period of time. I needed an easy way to see how long my animations were taking, but something that could be quickly turned off when I needed to publish for a client review. I came up with this simple QuickTimer class. Simply import the class, then create a new instance of QuickTimer, passing in a MovieClip. The class will create a little white box in the upper left corner that will count up the seconds. Alternately, you can pass in a textfield that it will use to display the timing, or you can pass in nothing, which will turn on traceMode to simply trace out the time.

package com{

	import flash.text.TextField;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	public class QuickTimer{

		private var mainTimer:Timer;
		private var _txt:TextField;

		private var milliseconds:int;

		private var strTime:String;
		private var traceMode:Boolean = false;

		public function QuickTimer(txt:* = null){//pass in either a textfield or movieClip to attach a textField

			if(!txt){
				traceMode = true;
			}else{
				if(txt is TextField){
					_txt = txt;
					_txt.parent.visible = true;
				}else{
					_txt = new TextField();
					_txt.height = 15;
					_txt.width = 26;
					_txt.background = true;
					txt.addChild(_txt);
					txt.visible = true;
					_txt.x = 5;
					_txt.y = 5;
				}
				_txt.visible = true;
			}

			mainTimer = new Timer(100);
			milliseconds = 0;
			mainTimer.addEventListener(TimerEvent.TIMER, updateTime);
			mainTimer.start();
		}

		private function updateTime(evt:TimerEvent):void{
			milliseconds += 1;

			var seconds:int = Math.floor(milliseconds/10);
			var remaining:int = milliseconds - seconds*10;

			strTime = seconds + ":" + remaining;
			if(traceMode && remaining == 0){
				trace("QuickTimer: " + seconds + " seconds");
			}else{
				_txt.text = strTime;
			}
		}

		public function stopTimer(){
			mainTimer.stop();

			/*if(traceMode){
				trace("QuickTimer end: " + strTime);
			}*/
		}

		public function traceTime(timeLabel:String = null){
			if(timeLabel){
				trace(timeLabel + ": " + strTime);
			}else{
				trace("QuickTimer current time: " + strTime);
			}
		}

	}
}

 

Mooster Day Flash Banners

In 2010 I built a set of animated Flash banners for a nonprofit called Global Nomads Group using the GreenSock engine.

In 2010 I built a set of animated Flash banners for a nonprofit called Global Nomads Group centering around a character called the Mooster, half moose, half rooster, who goes “Cock-a-doodle-moo”. These banners were developed entirely with the GreenSock tweening engine. The versions I’m showing here are in ActionScript 3, but I also converted all of them to ActionScript 2 for a few sites who would not accept AS3 ads.

This first one is the 300×250 version. Be sure to look at the other two, as they are very different designs, by clicking on the page buttons at the bottom of the post.

http://kalinflash.com/wordpress/wp-content/uploads/2011/06/gng/300×250.swf

 

Here is the 728×90 version of the Global Nomad’s Group Mooster Day banner:

http://kalinflash.com/wordpress/wp-content/uploads/2011/06/gng/728×90.swf

 

And here is the 160×600 version of the Global Nomad’s Group Mooster Day banner:

http://kalinflash.com/wordpress/wp-content/uploads/2011/06/gng/160×600.swf

 

Catch the Water Droplets (Flash Game)

In 2010 I built a set of interactive banner ads for the clean water charity, Tap Project, using a little piece of transparent video.

In 2010 I built a set of interactive banner ads for the clean water charity, Tap Project, using a little piece of transparent video. Hover to control the cup.

I also made a number of other sizes, like 300×250, 728×90, 160×600. Here is the 130×400:

 

 

Hotel Contest Microsite

In early 2010 I built a Flash microsite for HomeAway. It was a Griswolds Vacation themed contest where people could upload their videos and stories describing their worst hotel nightmares. I worked with the Kyte API for video serving, built a voting system and integrated a bunch of pre-built timeline animations.

In early 2010 I built a Flash microsite for HomeAway. It was a Griswolds Vacation themed contest where people could upload their videos and stories describing their worst hotel nightmares. I worked with the Kyte API for video serving, built a voting system and integrated a bunch of pre-built timeline animations.

The site was designed only to be used for this special event, but I did capture a couple recordings of it in use.

This microsite and campaign won a Gold Effie and was an honoree at the 15th annual Webby Awards. You can get more information and watch the Griswolds Vaction film at The HomeAway Campaign page at Publicis’ website.

And here’s another example of the site in use: