Tag Archives: Twitter

If Miyamoto Went Indie …

Wired reports that legendary video game developer Shigeru Miyamoto is stepping down from his role at Nintendo overseeing the company’s large video game projects. Miyamoto, who was behind some of the biggest video game franchises including The Legend of Zelda, Super Mario Bros., Star Fox, Pikmin, Donkey Kong and Nintendogs, says he wants to work on smaller projects with shorter timespans. This led many Twitter adherents to comment that Miyamoto was going “indie”, joining the ranks of self-funded, hipster game developers. i took the concept and ran with it in this Twitter hash tag game.

Link in the Graveyard

  • #ifMiyamotoWentIndie Link would just … you know … wander around. No enemies, no struggle … just piano.
  • #ifMiyamotoWentIndie Every game stars Luigi.
  • #ifMiyamotoWentIndie Mario would walk RIGHT to LEFT. Doesn’t that BLOW your MIND??
  • #ifMiyamotoWentIndie He’d crash on someone’s couch at #GDC, lobby-surf for the first few days, and only spring for an Expo pass.
  • #ifMiyamotoWentIndie The smashable barrels in Donkey Kong would be labeled “hope”, “ambition”, “faith” and “mother”.
  • #ifMiyamotoWentIndie After your first crash in ExciteBike, the rest of the game would be about your slow, painful road to rehabilitation.
  • #ifMiyamotoWentIndie A Star Fox game would last five minutes, and involve a sub-plot about a stillborn son.
  • #ifMiyamotoWentIndie Ocarina of Time would pale in comparison to the series’ crown jewel, Zelda II: The Adventure of Link.
  • #ifMiyamotoWentIndie He’d be making this really awesome MMO but, you know – it’s not ready yet.
  • #ifMiyamotoWentIndie He’d make a twin-stick tower defense platformer for XBLiG using copyrighted spritesheets from an old Genesis import.
  • #ifMiyamotoWentIndie He’d show upto #IndieCade and give a meandering talk using words he remembered from his first-year Psych class.
  • #ifMiyamotoWentIndie Kid Icarus would say “fuck” a lot.
  • #ifMiyamotoWentIndie He’d accept his #IGF award by French-kissing Cactus and kicking over an amp on his way off the stage.
  • #ifMiyamotoWentIndie The hookshot would be a metaphor for how we all need to cling to something.
  • #ifMiyamotoWentIndie Nintendogs would be essentially the same, except you could REVERSE TIME.
  • #ifMiyamotoWentIndie He’d release Stage Debut, and it would sweep the #IGF.
  • #ifMiyamotoWentIndie Samus Aran would take off her codpiece and reveal that she’s a DUDE.
  • #ifMiyamotoWentIndie Mario Extreme Unicycling.
  • #ifMiyamotoWentIndie Mario Power Hackey Sack.
  • #ifMiyamotoWentIndie He’d spent most of his afternoons in the “Mushroom Kingdom”.
  • #ifMiyamotoWentIndie You’d be able to fly one beta mission in Starfox, and he’d charge twenty bucks for it. And then make 4 million dollars.
  • #ifMiyamotoWentIndie He’d give you naming rights to the monkey at the top of the level if you bid more than $1000 on Kickstarter.
  • #ifMiyamotoWentIndie Every Zelda game ever made would show up in a Steam sale for a dollar nintey-five.
  • #ifMiyamotoWentIndie You’d take Super Mario down into a water level from which you’d never be able to escape.
  • #ifMiyamotoWentIndie He’d grow his hair out, take up smoking, and start calling himself “the Moto.” But, you know. Whatever.
  • #ifMiyamotoWentIndie Plaid goombas.

Tutorial: Twitter Updates in Flash Part 2

Our first tutorial, Pull Twitter Updates into Flash, got us a bit of attention. So rather than write an entirely new tutorial, we thought we’d beat a dead horse a little and re-hash some of the same material.

Fwitter

We’re even using the same Fwitter logo. Classy.

This tutorial builds on the last one, and helps us solve an important problem. Untold Entertainment member and friend of the site MichaelJW pointed out last time around that Twitter only allows you to make 100 calls per hour for a given user name. If you’re fabulously swamped with oodles of traffic, or you’re like me, suffering from delusions that you will one day be fabulously swamped with oodles of traffic, then this is a problem. Fortunately, MichaelJW has the solution: simply write to Twitter and ask to be whitelisted, so that you can make all the calls you want!

In short order, you’ll receive this letter from Twitter:

From: Twitter
Subject: Your Request for Twitter API whitelisting has been rejected

Hi Ryan Creighton,
Thanks for requesting to be on Twitter’s API whitelist. Unfortunately, we’ve rejected your request.
Here’s why:
Please investigate other strategies to stay within our rate limits: http://apiwiki.twitter.com/FAQ#HowdoInbspkeepfromrunningintotheratelimit
Please address the issues above and submit another request if appropriate.
The Twitter API Team

CrapDAMMIT. That means we’re actually going to have to do some work to overcome this problem. Aww … i hate things that are hard.

Cold Hard Cache

i don’t know what you’re up to,but i thought this Twitter module idea was pretty cool, so i stuck it at the top of my website in the global nav. That means that every time the page is refreshed, we hit Twitter for a new copy of the tweets. Also, God kills a kitten or whatever. So that’s not being a very good netizen. Why hammer Twitter with more requests than necessary when we can spend hours of our own time writing a caching script to solve the problem? Am i right?

So here’s what we’re gonna do, in pseudocode:

  1. When we load up the module, let’s check the user’s Flash cookie to see if we’ve saved any Twitter data
  2. If the cookie is empty, we’ll hit the Twitter servers and grab new data. Then we’ll save that data for next time.
  3. We’ll add a time stamp to the Flash cookie so we know how long it’s been since we grabbed fresh data from Twitter.
  4. If there IS Twitter data in the cookie, let’s look at how old it is
  5. If it’s still fresh, there’s no need to hit Twitter. We’ll just display that data.
  6. If it’s old data, let’s hit Twitter and get a new copy.

(note throughout the tutorial and the code, i use the vernacular “Flash cookie”. The proper term is “shared object”, but it’s a lot harder to remember what the thing does when you call it that.)

How do we know what constitutes “old” data? It’s right there in the code. You can set the number of hours, minutes and seconds it takes for the data to expire. i think setting the expiry to 1 hour is pretty reasonable, but feel free to be as unreasonable as you like with this value. It’s your Twitter funeral.

Here comes the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package
{
	/**********************************************
	 * 
	 *  This fun Twitter widget is brough to you
	 *  by Untold Entertainment Inc, and 
	 *  peanut butter!  Peanut butter: a gooey,
	 *  yummy snack that might kill you.
	 * 
	 *  http://www.untoldentertainment.com
	 * 
	 **********************************************/
 
	// Here are all the goodies you're going to need 
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.events.Event;
	import flash.events.NetStatusEvent;
	import flash.net.SharedObject;
 	import flash.net.SharedObjectFlushStatus;	
 
	public class Main extends MovieClip
	{
		private var twitterXML:XML; // This holds the xml data
		private var cachedTwitterData:SharedObject; // This stores the data loaded from the Flash cookie
		private var twitterPHPScriptPath:String;
		private var myTwitterID:String;
		private var wereAllowedToWriteToTheFlashCookie:Boolean; // You can use this value to decide whether or not to make repeated save attempts
 
		public function Main()
		{
			// Put your Twitter username here.  For example, ours is "untoldEnt" :
			myTwitterID = "myTwitterID"; 
 
			// Put the path to your php script here:
			twitterPHPScriptPath = "http://www.yourdomain.com/thePathToYourPHPScript";
 
			wereAllowedToWriteToTheFlashCookie = true; // (let's be optimistic until we discover otherwise) 
 
			// Check to see if the user has already retrieved the Twitter updates and stored them in a Flash cookie:
			loadTwitterDataFromFlashCookie();
		}
 
		private function loadTwitterDataFromFlashCookie():void
		{
			// Call up the Twitter data from the Flash cookie on the user's machine:
			cachedTwitterData = SharedObject.getLocal("twitter");
 
			var timeStamp:Date = cachedTwitterData.data.timeStamp;
 
			if (timeStamp != null)
			{
				// The timeStamp variable is in there, which means we've retrieved Twitter info for this user at some point.
 
				// Now let's check the timeStamp. If the last time we grabbed Twitter data was too long ago, let's grab fresh info:
				if (hasExpired(timeStamp))
				{
					// The most recent copy of the Twitter data in the Flash cookie is old!  Let's get some fresh data:
					trace("cookie has expired!  let's get some fresh data");
					loadTwitterXML();		
				} else {
					// It hasn't been very long since we grabbed a fresh copy of the Twitter data. Let's just use what we've got in the Flash cookie:
					trace("cookie is fresh. display the data.");
					twitterXML = cachedTwitterData.data.twitterXML;
					showTwitterStatus();
				}
			} else {
				// If there's no timeStamp variable in there, then the cookie's empty.  We need to hit Twitter to grab our data for the first time.
				loadTwitterXML();				
			}			
		}
 
		private function saveTwitterDataToFlashCookie():void
		{
 
			// This bit tries to write something to the user's Flash cookie. Depending on the user's Flash cookie
			// settings, we may need to ask the user permission before we write to the cookie.  We'll test
			// the water by trying to write something to the cookie:
            var flushStatus:String = null;
            try
			{
                flushStatus = cachedTwitterData.flush(10000);
            } catch (error:Error) {
                trace("Error...Could not write SharedObject to disk\n");
            }
			// If we were able to write to the Flash cookie, let's see if the user was prompted to allow us or not:
            if (flushStatus != null)
			{
                switch (flushStatus)
				{
					// The user is only allowing us to write a very small amount of data to the Flash cookie, and has asked
					// Flash to prompt him so that he can give permission to write something larger.  Let's wait until the
					// user clicks to give that permission:
                    case SharedObjectFlushStatus.PENDING:
                        trace("Requesting permission to save object...\n");
                        cachedTwitterData.addEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
                        break;
					// We're home-free: we can write to the cookie, and the amount of data is small enough to fly under the
					// user's Flash cookie permission radar.  Let's write some data!
                    case SharedObjectFlushStatus.FLUSHED:
                        //trace("Value flushed to disk.\n");
						trace("********* save complete. ***********\n");
						finishedHandlingTwitterData();
                        break;
                }
            }				
		}
 
		private function onFlushStatus(e:NetStatusEvent):void
		{
            trace("User closed permission dialog...\n");
            switch (e.info.code)
			{
                case "SharedObject.Flush.Success":
                    trace("User granted permission -- value saved.\n");
					finishedHandlingTwitterData();
                    break;
				// Dammit!  In this case, the user freaked out and won't let us write anything to his Flash cookie.
				// We'll have to hit Twitter every single time solely for this user's benefit.
                case "SharedObject.Flush.Failed":
                    trace("User denied permission -- value not saved.\n");
					wereAllowedToWriteToTheFlashCookie = false;
                    break;
            }
 
            cachedTwitterData.removeEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
        }	
 
		private function finishedHandlingTwitterData(e:Event = null):void
		{
			trace("Twitter data saved.");
		}
 
		private function hasExpired(timeStamp:Date):Boolean
		{
			// Store the date RIGHT NOW, to compare against the Flash cookie timeStamp:
			var now:Date = new Date();
 
			// Let's say that the cookie expires after 1 hour, 0 minutes and zero seconds:
			var expiryHours:Number = 1;
			var expiryMinutes:Number = 0;
			var expirySeconds:Number = 0;
 
			// Store some handy conversion values:
			var msPerHour:Number = 3600000;
			var msPerMinute:Number = 60000;
			var msPerSecond:Number = 1000;
 
			// Multiply those values to get the expiry time in milliseconds:
			var expiryTime:Number = (expiryHours * msPerHour) + (expiryMinutes * msPerMinute) + (expirySeconds * msPerSecond);
 
			// Return whether or not the timeStamp is past the expiry date:
			return (now.getTime() - timeStamp.getTime() > expiryTime)
		}
 
		private function loadTwitterXML():void
		{
			var urlLoader:URLLoader = new URLLoader();
			// When all the junk has been pulled in from the url, we'll fire finishedLoadingXML:
			urlLoader.addEventListener(Event.COMPLETE, finishLoadingXML);
			urlLoader.load(new URLRequest(twitterPHPScriptPath + "?twitterId=" + myTwitterID));			
		}
 
		private function finishLoadingXML(e:Event = null):void
		{
			// All the junk has been pulled in from the xml!  Hooray!
			// Remove the eventListener as a bit of housecleaning:
			e.target.removeEventListener(Event.COMPLETE, finishLoadingXML);
 
			// Populate the xml object with the xml data:
			twitterXML = new XML(e.target.data);
 
 
			cachedTwitterData = SharedObject.getLocal("twitter");
 
			// Set the date/time RIGHT NOW:
			cachedTwitterData.data.timeStamp = new Date();
			// Store the twitterXML data:
			cachedTwitterData.data.twitterXML = twitterXML;	
			// (Try to) save the whole shebang the user's Flash cookie: 
			saveTwitterDataToFlashCookie();
 
			showTwitterStatus();
		}
 
		private function showTwitterStatus():void
		{
			trace("showTwitterStatus");
			// Uncomment these lines if you want to see all the fun stuff Twitter sends you:
			//trace(twitterXML);
			//trace(twitterXML.head);
 
			// Prep the text field to hold our latest Twitter update:
			twitter_txt.wordWrap = true;
			twitter_txt.autoSize = TextFieldAutoSize.LEFT;
 
			// Populate the text field with the first element in the status.text nodes:
			twitter_txt.htmlText = twitterXML.status.text[0];
		}
	}
}

This is just a modified version of the code we used last time, with the caching stuff added in. It’s very well commented. If you’re new to the concept of Flash cookies, take a careful read-through and make yourself smart.

I Did it All for the Cookie

Cookie Monster

Now DAT a lot of code.

i added one flag to the code called wereAllowedToWriteToTheFlashCookie. Time was, no one knew about Flash cookies, and you could get away with murder. Nowadays, some folks are wise to the fact that Flash can store stuff to their computers, and they’re blocking access, or cranking the permission slider down so that barely any data can be stored to their computers. If this is the case, and you try to store a Flash cookie, a dialogue box will pop up and ask the user to authorize the cookie-writing procedure. If the player says “no”, we’re flagging the wereAllowedToWriteToTheFlashCookie to false.

This tutorial doesn’t really make any further use of that value. But if you check out our super-deluxe version of this module at the top of the Untold Entertainment site, you’ll notice we added paging controls so that users can flip through the last twenty Twitter messages, and an auto-refresh countdown that displays the next tweet automatically. One of the things i noticed was that if you move around the site quickly, the bird keeps tweeting the most recent post. That’s kind of boring.

What i’d like to do (which i may have already done, depending on when you read this), is to save the currentTweet number every time it changes. That way, when the page refreshes, i can retrieve the currentTweet number from the Flash cookie and pick up where i left off. BUT if the user isn’t allowing Flash cookies, he’s gonna see that “Allow?” dialogue pop up every time i try to save the currentTweet number. And that stinks. That guy’s not likely to pay a repeat visit.

So i’ll check the wereAllowedToWriteToTheFlashCookie flag before i try to save anything else to the Flash cookie.

And by then, the Twitter module on our site will be just about as awesomazing as possible.

Making it Work

If this is your first time with these Twitter tutorials, you might make some mistakes. And then you might blame those mistakes on us. Rest assured, the code works. You’re probably doing something silly. Make sure you test this on a web server, because the Flash IDE lies to you, and generally won’t tell you when there’s a securty sandbox issue. Please check the comments at the bottom of these posts to make sure you’re not making the same mistake that someone else has made before you. We’re not that great at troubleshooting this stuff, because we’re usually too busy chasing after the next shiny object to pay proper attention to you. When in doubt, use the boards to discuss. By signing up on our boards, you get the added benefit of being awesome.

You can download the source code for this tutorial here:

cachedTwitterUpdatesInFlash.zip

For more Flash AS3 Tutorials and a pile of other useful stuff, check out our Flash and Actionscript 911 feature.

Tutorial: Pull Twitter Updates into Flash

Fwitter

That’s right – i said “Fwitter”

It’s a very simple thing to display your Twitter updates in a Flash widget. We’re going to use the xml feed, because that’s what i’m most comfy with. Unfortunately, you can’t grab the xml feed from Twitter’s site, because they’ve locked their crossdomain policy file … but you can pull down the data using any other damned process. Here’s the basic flow you have to follow:

  1. Hit a PHP page or javascript function from Flash (we’ll use PHP)
  2. Parse the XML data that the call returns
  3. Display the goodies in your Flash app

Here Comes the Code

This is the Actionscript 3 code you’ll need:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package
{
	/**********************************************
	 * 
	 *  This fun Twitter widget is brough to you
	 *  by Untold Entertainment Inc, and 
	 *  peanut butter!  Peanut butter: a gooey,
	 *  yummy snack that might kill you.
	 * 
	 *  http://www.untoldentertainment.com
	 * 
	 **********************************************/
 
	// Here are all the goodies you're going to need 
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.events.Event;
 
	public class Main extends MovieClip
	{
		private var twitterXML:XML; // This holds the xml data
 
		public function Main()
		{
			// Put your Twitter username here.  For example, ours is "untoldEnt" :
			var myTwitterID:String = "myTwitterID"; 
			// Put the path to your php script here:
			var twitterPHPScriptPath:String = "http://www.yourdomain.com/thePathToYourPHPScript";
			// Fire the loadTwitterXML method, passing it the url to your Twitter info:
			loadTwitterXML(twitterPHPScriptPath + "?twitterId=" + myTwitterID);
		}
 
		private function loadTwitterXML(URL:String):void
		{
			var urlLoader:URLLoader = new URLLoader();
			// When all the junk has been pulled in from the url, we'll fire finishedLoadingXML:
			urlLoader.addEventListener(Event.COMPLETE, finishLoadingXML);
			urlLoader.load(new URLRequest(URL));			
		}
 
		private function finishLoadingXML(e:Event = null):void
		{
			// All the junk has been pulled in from the xml!  Hooray!
			// Remove the eventListener as a bit of housecleaning:
			e.target.removeEventListener(Event.COMPLETE, finishLoadingXML);
 
			// Populate the xml object with the xml data:
			twitterXML = new XML(e.target.data);
			showTwitterStatus();
		}
 
		private function showTwitterStatus():void
		{
			// Uncomment this line if you want to see all the fun stuff Twitter sends you:
			//trace(twitterXML);
 
			// Prep the text field to hold our latest Twitter update:
			twitter_txt.wordWrap = true;
			twitter_txt.autoSize = TextFieldAutoSize.LEFT;
 
			// Populate the text field with the first element in the status.text nodes:
			twitter_txt.htmlText = twitterXML.status.text[0];
		}
	}
}

And here’s the PHP code:

1
2
3
4
5
6
7
8
9
10
<?php
 
$twitterId = isset($_REQUEST["twitterId"]) ? $_REQUEST["twitterId"] : '';
if( $twitterId == "" ){
                exit;
}
$file = file_get_contents("http://twitter.com/statuses/user_timeline/" . $twitterId  . ".xml" );
echo $file;
 
?>

Et voila! Your latest Twitter update appears in a text box on the stage.

[SWF]http://www.untoldentertainment.com/blog/tutorials/twitter/twitterUpdatesInFlash.swf, 550, 100[/SWF]

(note: this tutorial assumes you have a textField on the stage named “twitter_txt”)

Twitter exposes a pile of other information, including time stamp, post count, number of followers, etc etc that you can play around with. This simple example should get you started, anyway.

You can download the source code here:

twitterUpdatesInFlash.zip

Big thanks to Jeffie G for writing the PHP code to circumvent Twitter’s silly security restriction.

Don’t miss the second part of this tutorial:

Tutorial: Twitter Updates in Flash Part 2

For more Flash AS3 Tutorials and a pile of other useful stuff, check out our Flash and Actionscript 911 feature.