topical media & game development
student-twitter-swarm-TwitterSwarm.mx
student-twitter-swarm-TwitterSwarm.mx
[swf]
flex
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
initialize="init();"
verticalScrollPolicy="off" horizontalScrollPolicy="off"
backgroundImage="@Embed('student-twitter-swarm-images-bg.jpg')" backgroundAttachment="fixed"
width="900" height="600">
<mx:Script>
<![CDATA[
import mx.controls.Label;
import mx.rpc.events.ResultEvent;
import flash.utils.clearInterval;
import flash.utils.setInterval;
import mx.controls.Image;
import mx.controls.Alert;
private var screenWidth:int = 900,
screenHeight:int = 600;
private var worldObjects:Array;
private var trees:Array;
private var boids:Array;
// Initialisation
private function init ():void {
// Is called at startup and starts the initialisation process.
Security.loadPolicyFile('student-twitter-crossdomain.xml');
getEmotions();
}
private function getEmotions ():void {
// Calls for the retrieval of the emotions.
emo.url = "student-twitter-emotions.xml";
emo.send();
}
[Bindable]
private var xEmotions:XML;
private var emotions:Array = [], colors:Array = [];
private function setEmotions (event:ResultEvent):void {
// When the emotions have been retrieved from the server,
// this function is called.
// When the emotions and colors have been extracted, the
// trees are added to the application.
xEmotions = event.result as XML;
var emotionList:XMLList = xEmotions.emotion;
for(var i:int = 0; i < emotionList.length(); i++) {
emotions[emotions.length] = extractEmotion(emotionList[i]);
colors[colors.length] = extractColor(emotionList[i]);
}
addTrees();
}
public function extractEmotion (emotion:XML):Array {
// Extracts the emotion and associated words from the XML object.
var words:XMLList = emotion.words.word;
var word:XML;
var result:Array = [emotion.attribute("name")];
for each(word in words) {
result[result.length] = word.toString();
}
return result;
}
public function extractColor (emotion:XML):Array {
// Extracts the three color values from the XML object.
var color:XMLList = emotion.color;
return [parseFloat(color[0].attribute("red")),
parseFloat(color[0].attribute("green")),
parseFloat(color[0].attribute("blue"))]
}
private function addTrees():void {
// The trees are added at the designated x and y coordinates and mood.
// When the trees are added, the initialisation is complete.
trees = [];
addTree(242, 125, "happy");
addTree(737, 460, "tired");
addTree(819, 68, "love");
addTree(489, 360, "angry");
addTree(138, 450, "sad");
}
[Embed(source="student-twitter-swarm-images-ring.png")] public var treetop:Class;
private function addTree(x:int, y:int, mood:String):void {
// An image is created here, because it can only be added to the
// screen in this file. The variable above the function makes sure
// that the image is embedded in the compiled application.
// An event listener is added so the user can shake the tree and
// the tree object is created.
var treeImage:Image = new Image();
this.addChild(treeImage);
treeImage.source = treetop;
treeImage.addEventListener(MouseEvent.CLICK, this.shakeTree);
var tree:student_twitter_swarm_Tree = new student_twitter_swarm_Tree(x, y, treeImage, mood);
trees.push(tree);
}
private function shakeTree (event:Event):void {
// If the simulation is running then find the right tree and tel
// it to shake.
if (simRunning) {
for(var i:int = 0; i < trees.length; i++) {
if (trees[i].getImage() == event.currentTarget) {
trees[i].shake(boids);
}
}
}
}
// Twitter-contact Initiation
private function goAll ():void {
// If someone pushes the Latest Tweets button then set user to
// All and retrieve the tweets.
usernameBox.text = "All";
getTweets();
}
private var simRunning:Boolean = false;
private function simClick ():void {
// Changes the Go button and starts/stops the simulation.
if (usernameBox.enabled) {
getTweets();
simButton.enabled = false;
} else if (!simRunning) {
simButton.label = "Pause";
start();
simRunning = true;
} else if (simRunning) {
simButton.label = "Start";
stop();
simRunning = false;
}
}
private function getTweets ():void {
// Requests the xml for the current user.
srv.url = "student-twitter-tweets.php?user=" + usernameBox.text;
srv.send();
}
// Post server-contact initialisation
[Bindable]
private var xData:XML;
private function newTweets (event:ResultEvent):void {
// Called when the tweets have been retrieved from the server.
xData = event.result as XML;
addBoids(xData);
simButton.enabled = true;
}
private function addBoids (data:XML):void {
// Adds a boid for each tweet in the data.
// The array of embedded images is the sequence for the AnimatedImage
// After the boids have been added the boids are compared to each other
// to calculate which other boids they should be attracted to.
var tweets:XMLList = data.status;
boids = [];
if (boids.length > 0) {
stop();
}
usernameBox.enabled = false;
goAllButton.enabled = false;
[Embed(source="student-twitter-swarm-images-orb-0.png")] var frame0:Class;
[Embed(source="student-twitter-swarm-images-orb-1.png")] var frame1:Class;
[Embed(source="student-twitter-swarm-images-orb-2.png")] var frame2:Class;
[Embed(source="student-twitter-swarm-images-orb-3.png")] var frame3:Class;
var anim:Array = [];
anim[0] = frame0;
anim[1] = frame1;
anim[2] = frame2;
anim[3] = frame3;
var tweet:student_twitter_swarm_Tweet;
for(var i:int = 0; i < tweets.length(); i++) {
tweet = new student_twitter_swarm_Tweet(tweets[i], emotions, colors);
addBoid(tweet, anim);
}
for(var r:int = 0; r < boids.length; r++) {
boids[r].calculateSimilarities(boids);
}
simClick();
}
private function addBoid (tweet:student_twitter_swarm_Tweet, anim:Array):void {
// Adding a boid requires an image that is added to the screen and
// interactivity with the user to display the message attached to the boid.
var boidImage:Image = new Image();
this.addChild(boidImage);
var boid:student_twitter_swarm_Boid = new student_twitter_swarm_Boid(boidImage, messagePanel, tweet, anim);
boidImage.addEventListener(MouseEvent.CLICK, this.hideAllTweets);
boidImage.addEventListener(MouseEvent.CLICK, boid.showTweet);
boids.push(boid);
}
private function hideAllTweets (event:MouseEvent):void {
for(var i:int = 0; i < boids.length; i++) {
boids[i].hideTweet();
}
}
// Animation
private var animID:uint;
private function start ():void {
// Starts the timer that will move the boids.
animID = setInterval(moveBoids, 50, boids, boids.length);
}
private function stop ():void {
// Removes the timer that moves the boids.
clearInterval(animID);
}
private function moveBoids(boids:Array, numBoids:int):void {
// Each boid is subject to these five forces that drive its behaviour.
// When the forces have changed the direction and speed (vector) of the
// boid the images need to be moved. So the function displayWorld() is
// called.
for(var i:int = 0; i < boids.length; i++) {
boids[i].alignment(boids, 300);
boids[i].cohesion(boids, 400);
boids[i].separation(boids, 15);
boids[i].treeSeeking(trees, 200);
boids[i].nesting(trees);
}
displayWorld();
}
private function displayWorld ():void {
// Moves the boids to their new coordinates using the current vector.
for(var r:int = 0; r < boids.length; r++) {
boids[r].move();
boids[r].moveImage(screenWidth, screenHeight)
}
}
]]>
</mx:Script>
<mx:ApplicationControlBar dock="true">
<mx:Button id="goAllButton" click="goAll();" label="Newest Tweets"/>
<mx:Label text="or Username:"/>
<mx:TextInput id="usernameBox" text="default"/>
<mx:Button id="simButton" click="simClick();" label="Go"/>
</mx:ApplicationControlBar>
<mx:HTTPService id="emo" result="setEmotions(event);" resultFormat="e4x"/>
<mx:HTTPService id="srv" result="newTweets(event);" resultFormat="e4x"/>
<mx:Panel id="messagePanel" x="500" y="400" width="387" height="155" layout="absolute" fontSize="13" visible="false">
<mx:Image id="profilePic" x="10" y="10" width="48" height="48"/>
<mx:Text id="tweetLabel" x="66" y="10" width="290" height="75"/>
<mx:Label id="moodLabel" x="66" y="85" width="290" height="20"/>
</mx:Panel>
</mx:Application>
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.