Home >
Welcome back to the series and the concluding article of the exciting facebook series. So far we worked hard to implement features like the front end, administration, loading of YouTube videos etc. In the last article the application came finally to life. We implemented a database that contains 14 levels for the game.
In the screenshot we see the level where the movie clip from Forrest Gump appears. This is the famous running scene where Forrest simply decides to run and run . We mentioned briefly last time where the mistake is in the movieclip.
The key features that we are going to cover in this article are:
- Displaying of hints
- Publishing of news (within the iframe)
- Creating the level overview
Open the FLA we worked on previously.
We can see the two buttons that we placed from the previous article. Still there are lots of stuff missing here. We need to set up the following controls in order to complete the application:
- A text field where the hints will appear
- A slider component to display the level state
- A hint button that will trigger the level
- A status text field that will contain information about the application progress
- A the two buttons below, will trigger database actions
Here is the image of the elements so you get the idea:
Let's start with the elements.
Place one text field, size 211 x 200 on position x: 476 and y: 6. Select Trebuchet MS as the font and black as font color.
Next, place one Slider component on the stage. Set the direction property to vertical. Here is a quick overview of the properties set:
Set the position of the slider to x: 468 and y: 49.
Next, place one button component on the stage. Label it "Give me a hint!" and place it on the position x: 323 and y: 380. Ok, now the stage on your side should look close to the image shown as a reference.
The only thing left is the status text field. Place one status text field called status_txt on the on the stage. Make it 646 px wide and 19 px high. Set it on the stage to x: 5.0 and y: 405 so it should appear somewhere near the bottom.
The two images don’t need to be explained since we placed the in the previous article and are part of the database saving procedures.
If you still don't have a stage similar to this:
Then it’s a sign that you missed something.
Displaying of hints
We talked about hints in the previous article and what role they play in this application. So, before we move on to the coding of hints, we need to make sure where we stopped last time. This is the image of the application state from the last article.
As we can see, the first level when we enter the app is the Simpsons level.
So far, we had this code on the main timeline:
import classes.*;
import classes.choppingblock.video.*;
import flash.utils.*;
import com.facebook.Facebook;
import com.facebook.net.FacebookCall;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.events.FacebookEvent;
import com.facebook.commands.feed.*;
import com.facebook.data.feed.*;
import com.facebook.data.feed.*;
stop();
var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
var videoHolder = new YouTubeLoaderPlus();
videoHolder.create();
addChild(videoHolder);
videoHolder.addEventListener(YouTubeLoaderPlus.PLAYER_READY, ytPlayerReady);
videoHolder.addEventListener(YouTubeLoaderPlus.VIDEO_READY, ytVideoReady);
videoHolder.addEventListener(YouTubeLoaderPlus.ERROR_ADDED, videoErrorAdded);
videoHolder.addEventListener(YouTubeLoaderPlus.ERROR_SPOTTED, errorSpotted);
videoHolder.addEventListener(YouTubeLoaderPlus.CLICKED_FIRST_TIME, playerStarted);
var gameManager = new GameManager();
gameManager.addEventListener(GameManager.VIDEO_SAVED, errorsSaved);
gameManager.addEventListener(GameManager.LEVEL_PREPARED, levelPrepared);
gameManager.addEventListener(GameManager.GAME_OVER, gameOver);
gameManager.uid = String(paramObj["uid"]);
var errorCollector = new ErrorCollector();
function levelPrepared(e:Event):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
}
function playerStarted(e:Event):void{
//to do…
}
function ytPlayerReady(e:Event):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
//trace("gameManager.level: " + gameManager.level);
}
function ytVideoReady(e:Event):void{
videoHolder.play();
}
function gameSaved(e:Event):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
}
function gameOver(e:Event):void{
}
function errorSpotted(e:Event):void{
trace("You spotted the error...");
}
function moveToNextLevel():void{
videoHolder.stop();
videoHolder.visible = false;
gameManager.save();
}
var addVideoClip_mc = new AddVideoClip();
addChild(addVideoClip_mc);
addVideoClip_mc.addEventListener(AddVideoClip.VIDEO_BEING_ADDED, videoBeingAdded);
addVideoClip_mc.addEventListener(AddVideoClip.VIDEO_ID_ADDED, videoAddedForEditing);
function videoBeingAdded(e:Event):void{
videoHolder.stop();
videoHolder.visible = false;
cancel_btn.visible = true;
}
function videoAddedForEditing(e:SuperEvent){
var id = e.get("id");
videoHolder.loadVideoById(id);
videoHolder.editable = true;
errorCollector.id = id;
save_btn.visible = false;
cancel_btn.visible = true;
}
function videoErrorAdded(e:SuperEvent):void{
videoHolder.stop();
errorCollector.add(e.get("error"));
var num = errorCollector.length;
if(num > 0){
save_btn.visible = true;
}
}
save_btn.addEventListener(MouseEvent.CLICK, saveRequested);
cancel_btn.addEventListener(MouseEvent.CLICK, cancelRequested);
save_btn.visible = false;
cancel_btn.visible = false;
function saveRequested(e:MouseEvent):void{
gameManager.saveError(errorCollector.id, errorCollector.errors);
}
function cancelRequested(e:MouseEvent):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
videoHolder.editable = false;
save_btn.visible = false;
cancel_btn.visible = false;
addVideoClip_mc.visible = false;
}
function errorsSaved(e:Event):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
videoHolder.editable = false;
save_btn.visible = false;
cancel_btn.visible = false;
addVideoClip_mc.visible = false;
}
So, far, this code worked and did not produce any errors. What do we need to do to add hints?
As we can see on the image of the application state we want to achieve:
We see the button with the label “Give me a hint”. As we already can imagine, when the player presses the button, a hint appears helping the player to find the error in the movie more easily.
Since we already placed the hint button, we need to update the the classes and the timeline code in order for this to work.
Update the YouTubeLoaderPlus class with the following code:
package classes.choppingblock.video{
import flash.events.*;
import flash.display.*;
import classes.*;
public class YouTubeLoaderPlus extends YouTubeLoader {
protected var _count:Number = 0;
protected var _controls:YouTubeControl = new YouTubeControl();
protected var _error:Object = new Object();
protected var _circle:Circle = new Circle();
protected var _hintClip:MovieClip = new HintClip();
protected var _editable:Boolean = false;
protected var _editing:Boolean = false;
protected var _currCounter:Number = 0;
protected var _errors:Array;
protected var _errorButton:ErrorButton = new ErrorButton();
protected var _errNum:Number;
protected var _inited:Boolean = false;
public static var PLAYER_READY:String = "playerReady";
public static var VIDEO_READY:String = "videoReady";
public static var ERROR_ADDED:String = "errorAdded";
public static var ERROR_SPOTTED:String = "errorSpotted";
public static var CLICKED_FIRST_TIME:String = "clickedFirstTime";
function YouTubeLoaderPlus() {
super();
this.visible = false;
this.addEventListener(Event.ENTER_FRAME, checkPlayerReady);
this.addEventListener(YouTubeLoaderPlus.PLAYER_READY, ytPlayerReady);
this.addEventListener(YouTubeLoaderPlus.VIDEO_READY, ytVideoReady);
this.addChild(_controls);
_controls.addEventListener(YouTubeControl.PLAY_PRESSED, playPressed);
_controls.addEventListener(YouTubeControl.PAUSE_PRESSED, stopPressed);
this.addEventListener(SeekBar.BAR_CLICKED, seekBarClicked);
if(_editable){
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
this.addEventListener(MouseEvent.MOUSE_UP, mouseIsUp);
_controls.addEventListener(MouseEvent.ROLL_OVER, controlsRolledOver);
_controls.addEventListener(MouseEvent.ROLL_OUT, controlsRolledOut);
}
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseForNews);
}
private function mouseForNews(e:MouseEvent):void {
dispatchEvent(new Event(YouTubeLoaderPlus.CLICKED_FIRST_TIME, true, true));
this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseForNews);
}
private function hintsAdded(e:SuperEvent):void {
var ex:SuperEvent = new SuperEvent(YouTubeLoaderPlus.ERROR_ADDED, true, true);
_error.hint1 = e.get("hint1");
_error.hint2 = e.get("hint2");
_error.hint3 = e.get("hint3");
ex.add("error", _error);
dispatchEvent(ex);
_circle.startDrag(true);
_circle.visible = false;
_hintClip.visible = false;
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
this.addEventListener(MouseEvent.MOUSE_UP, mouseIsUp);
_controls.addEventListener(MouseEvent.ROLL_OVER, controlsRolledOver);
_controls.addEventListener(MouseEvent.ROLL_OUT, controlsRolledOut);
this.play();
}
private function mouseIsDown(e:MouseEvent):void {
if(this.getPlayerState() == "2"){
return;
}
_error.x = this.mouseX;
_error.y = this.mouseY;
_error.startTime = this.getCurrentTime();
_circle.visible = true;
_circle.stopDrag();
}
private function mouseIsUp(e:MouseEvent):void {
if(this.getPlayerState() == "2"){
return;
}
_error.endTime = this.getCurrentTime();
_hintClip.x = _circle.x;
_hintClip.y = _circle.y;
_hintClip.visible = true;
this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
this.removeEventListener(MouseEvent.MOUSE_UP, mouseIsUp);
_editing = true;
this.pause();
}
private function controlsRolledOut(e:MouseEvent):void {
if(_editable && !_editing){
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
this.addEventListener(MouseEvent.MOUSE_UP, mouseIsUp);
}
}
private function controlsRolledOver(e:MouseEvent):void {
if(_editable && !_editing){
this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
this.removeEventListener(MouseEvent.MOUSE_UP, mouseIsUp);
}
}
private function seekBarClicked(e:SuperEvent):void {
var prc = e.get("prc");
this.seekTo(prc * this.getDuration());
}
private function ytPlayerReady(e:Event) {
this.setSize(450, 370);
_controls.y = 380;
this.addChildAt(_circle, this.numChildren);
_circle.startDrag(true);
this.visible = false;
this.addChildAt(_hintClip, this.numChildren);
_hintClip.visible = false;
_circle.visible = editable;
_hintClip.addEventListener(HintClip.HINTS_ADDED, hintsAdded);
this.addChildAt(_errorButton, this.numChildren);
_errorButton.visible = false;
_errorButton.addEventListener(MouseEvent.CLICK, errorSpotted);
_errorButton.alpha = 0;
}
private function errorSpotted(e:MouseEvent) {
var index = e.currentTarget.index;
_errors.splice(index, 1);
_errNum = _errors.length;
if(_errNum == 0){
_errors = [];
}
dispatchEvent(new Event(YouTubeLoaderPlus.ERROR_SPOTTED, true, true));
}
private function ytVideoReady(e:Event) {
this.pause();
this.addEventListener(Event.ENTER_FRAME, updatePreloadStatus);
this.visible = true;
}
private function updatePreloadStatus(e:Event) {
var l = this.getBytesLoaded();
var t = this.getBytesTotal();
_controls.setProgress(l, t);
if(l >= t){
this.removeEventListener(Event.ENTER_FRAME, updatePreloadStatus);
}
}
private function updateSeekStatus(e:Event) {
var curr:Number = this.getCurrentTime();
var dur:Number = this.getDuration();
_controls.setSeekProgress(curr, dur);
var i:Number = 0;
var len = _errNum;
var active = false;
for(i = 0; i < len; i++){
var c = _errors[i];
if((c.startTime < curr) && (curr < c.endTime)){
setErrorButton(i);
_errorButton.index = i;
active = true;
} else {
removeErrorButton(active);
}
}
if(len == 0){
removeErrorButton(false);
}
}
private function setErrorButton(c):void {
if(!_errorButton.visible){
_errorButton.visible = true;
}
_errorButton.x = _errors[c].x;
_errorButton.y = _errors[c].y;
}
private function removeErrorButton(active):void {
if(_errorButton.visible){
if(!active){
_errorButton.visible = false;
}
}
}
private function checkPlayerReady(e:Event) {
_count++;
if(_count >= 50){
this.removeEventListener(Event.ENTER_FRAME, checkPlayerReady);
dispatchEvent(new Event(YouTubeLoaderPlus.PLAYER_READY));
}
}
private function checkVideoReady(e:Event) {
if(this.getDuration() > 0){
this.removeEventListener(Event.ENTER_FRAME, checkVideoReady);
dispatchEvent(new Event(YouTubeLoaderPlus.VIDEO_READY));
}
}
private function playPressed(e:Event):void {
this.play();
}
private function hideHintControls():void {
_circle.visible = false;
_hintClip.visible = false;
_circle.startDrag(true);
}
private function stopPressed(e:Event):void {
this.pause();
}
override public function loadVideoById (id:String, startSeconds:Number = 0):void{
super.loadVideoById(id, startSeconds);
this.addEventListener(Event.ENTER_FRAME, checkVideoReady);
hideHintControls();
}
override public function play():void{
super.play();
this.addEventListener(Event.ENTER_FRAME, updateSeekStatus);
_editing = false;
hideHintControls();
}
public function set editable(e:Boolean):void {
_editable = e;
_circle.visible = e;
if(_editable){
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
this.addEventListener(MouseEvent.MOUSE_UP, mouseIsUp);
_controls.addEventListener(MouseEvent.ROLL_OVER, controlsRolledOver);
_controls.addEventListener(MouseEvent.ROLL_OUT, controlsRolledOut);
} else {
this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
this.removeEventListener(MouseEvent.MOUSE_UP, mouseIsUp);
_controls.removeEventListener(MouseEvent.ROLL_OVER, controlsRolledOver);
_controls.removeEventListener(MouseEvent.ROLL_OUT, controlsRolledOut);
}
}
public function get editable():Boolean {
return _editable;
}
public function setLevelData(e:Object):void {
_errors = e as Array;
_errNum = e.length;
}
};
};
So here is the revised code for the main timeline, make sure you paste it exactly as it is:
import classes.*;
import classes.choppingblock.video.*;
import flash.utils.*;
import com.facebook.Facebook;
import com.facebook.net.FacebookCall;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.events.FacebookEvent;
import com.facebook.commands.feed.*;
import com.facebook.data.feed.*;
import com.facebook.data.feed.*;
stop();
var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
var fbook:Facebook;
var session:FacebookSessionUtil = new FacebookSessionUtilPlus("1e9e88bae0cc78d53f998f6d3506d129", "9f4867e360bcc1e42bece165024530a5", loaderInfo, String(paramObj["sessID"]));
fbook = session.facebook;
var videoHolder = new YouTubeLoaderPlus();
videoHolder.create();
addChild(videoHolder);
videoHolder.addEventListener(YouTubeLoaderPlus.PLAYER_READY, ytPlayerReady);
videoHolder.addEventListener(YouTubeLoaderPlus.VIDEO_READY, ytVideoReady);
videoHolder.addEventListener(YouTubeLoaderPlus.ERROR_ADDED, videoErrorAdded);
videoHolder.addEventListener(YouTubeLoaderPlus.ERROR_SPOTTED, errorSpotted);
videoHolder.addEventListener(YouTubeLoaderPlus.CLICKED_FIRST_TIME, playerStarted);
var gameManager = new GameManager();
gameManager.addEventListener(GameManager.VIDEO_SAVED, errorsSaved);
gameManager.addEventListener(GameManager.LEVEL_PREPARED, levelPrepared);
gameManager.addEventListener(GameManager.GAME_OVER, gameOver);
levelSlider_mc.enabled = false;
levelSlider_mc.visible = false;
gameManager.uid = String(paramObj["uid"]);
var errorCollector = new ErrorCollector();
function levelPrepared(e:Event):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
status_txt.text = "Found " + gameManager.errorsFound + " error(s) out of " + gameManager.errorCount + ", you have " + gameManager.score + " MoviePoints";
levelSlider_mc.value = gameManager.levelCount;
var call = new PublishUserAction("106871439002", {}, [], null, com.facebook.data.feed.StorySizeValues.SHORT, null);
call.addEventListener(FacebookEvent.COMPLETE, newsPublished);
fbook.post(call);
}
function playerStarted(e:Event):void{
var call = new PublishUserAction("106585214002", {}, [], null, com.facebook.data.feed.StorySizeValues.SHORT, null);
call.addEventListener(FacebookEvent.COMPLETE, newsPublished);
fbook.post(call);
}
function ytPlayerReady(e:Event):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
status_txt.text = "When you spot the error in the movie, simply click on it.";
levelSlider_mc.minimum = 1;
levelSlider_mc.maximum = gameManager.levels.length;
levelSlider_mc.tickInterval = 1;
levelSlider_mc.value = gameManager.levelCount;
levelSlider_mc.visible = true;
hint_btn.visible = true;
}
function ytVideoReady(e:Event):void{
videoHolder.play();
}
function gameSaved(e:Event):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
status_txt.text = "Found " + gameManager.errorsFound + " error(s) out of " + gameManager.errorCount + ", you have " + gameManager.score + " MoviePoints";
}
function gameOver(e:Event):void{
status_txt.text = "Congrats! You are a real MovieExpert.";
var call = new PublishUserAction("106585214002", {}, [], null, com.facebook.data.feed.StorySizeValues.SHORT, null);
call.addEventListener(FacebookEvent.COMPLETE, newsPublished);
fbook.post(call);
}
function newsPublished(e:FacebookEvent):void{
trace("Data: " + e.data);
//trace("Error: " + e.error.errorMsg);
}
function errorSpotted(e:Event):void{
gameManager.errorsFound++;
gameManager.score = gameManager.score + 100;
status_txt.text = "Found " + gameManager.errorsFound + " error(s) out of " + gameManager.errorCount + ", you have " + gameManager.score + " MoviePoints";
if(gameManager.errorsFound == gameManager.errorCount){
moveToNextLevel();
}
}
function moveToNextLevel():void{
videoHolder.stop();
videoHolder.visible = false;
gameManager.save();
}
var addVideoClip_mc = new AddVideoClip();
addChild(addVideoClip_mc);
addVideoClip_mc.addEventListener(AddVideoClip.VIDEO_BEING_ADDED, videoBeingAdded);
addVideoClip_mc.addEventListener(AddVideoClip.VIDEO_ID_ADDED, videoAddedForEditing);
function videoBeingAdded(e:Event):void{
videoHolder.stop();
videoHolder.visible = false;
cancel_btn.visible = true;
}
function videoAddedForEditing(e:SuperEvent){
var id = e.get("id");
videoHolder.loadVideoById(id);
videoHolder.editable = true;
errorCollector.id = id;
status_txt.text = "When you spot a mistake, press and hold the mouse on the mistake, when it's over, release mouse button.";
save_btn.visible = false;
cancel_btn.visible = true;
hint_btn.visible = false;
}
function videoErrorAdded(e:SuperEvent):void{
videoHolder.stop();
errorCollector.add(e.get("error"));
var num = errorCollector.length;
status_txt.text = num + " errors added so far";
if(num > 0){
save_btn.visible = true;
}
}
save_btn.addEventListener(MouseEvent.CLICK, saveRequested);
cancel_btn.addEventListener(MouseEvent.CLICK, cancelRequested);
hint_btn.addEventListener(MouseEvent.CLICK, hintRequested);
save_btn.visible = false;
cancel_btn.visible = false;
hint_btn.visible = false;
function hintRequested(e:MouseEvent):void{
if(gameManager.score == 0){
hint_txt.htmlText = "<b>No MoviePoints left! MoviePoints are required for hints. Every hint costs 100 MP. Submit a video below to get 3000 MP or fill out offers <font color='#0000ff'><u><a href='#offers'>here</a></u></font> or simply scroll down. After you complete the offer, refresh this page to update your points.</b>";
return;
}
var randIndex:Number = Math.round(Math.random() * (gameManager.errors.length - 1));
var randHintNum:Number = Math.ceil(Math.random() * 3);
var hint:String = unescape(gameManager.errors[randIndex]["hint" + randHintNum.toString()]);
hint_txt.text = hint;
gameManager.score -= 100;
status_txt.text = "You have " + gameManager.score + " MoviePoints left";
}
function saveRequested(e:MouseEvent):void{
gameManager.saveError(errorCollector.id, errorCollector.errors);
}
function cancelRequested(e:MouseEvent):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
videoHolder.editable = false;
status_txt.text = "";
save_btn.visible = false;
cancel_btn.visible = false;
hint_btn.visible = true;
addVideoClip_mc.visible = false;
}
function errorsSaved(e:Event):void{
videoHolder.loadVideoById(gameManager.level);
videoHolder.setLevelData(gameManager.errors);
videoHolder.editable = false;
status_txt.text = "Thanks! Video saved along with mistakes. As soon as we approve it, you will get 3000 MoviePoints!";
save_btn.visible = false;
cancel_btn.visible = false;
hint_btn.visible = true;
addVideoClip_mc.visible = false;
}
Publishing of news
Of course we need to publish news from the application. Well there is one problem that we need to deal with. Aside the fact that we have the right news template, we also need to know that the application lives inside a normal iFrame, not FBML. What does it mean for us? It means that we cans use the starndard actionscript facebook api procedure descibed earlier, because the previos sample worked inside FBML. So, what do we need to do? We need to extend the existing FacebookSessionUtil class. Ok, the new class will be called FacebookSessionUtilPlus and needs to be saved inside the classes folder of the project.
Open you favorite text editor, save it as FacebookSessionUtilPlus.as and paste the following code inside it.
package classes {
import com.facebook.Facebook;
import com.facebook.events.FacebookEvent;
import com.facebook.session.DesktopSession;
import com.facebook.session.IFacebookSession;
import com.facebook.session.JSSession;
import com.facebook.session.WebSession;
import com.facebook.utils.*;
import com.facebook.facebook_internal;
import flash.display.LoaderInfo;
import flash.events.EventDispatcher;
import flash.net.SharedObject;
import flash.system.Capabilities;
public class FacebookSessionUtilPlus extends FacebookSessionUtil {
public function FacebookSessionUtilPlus(api_key:String, secret:String, loaderInfo:LoaderInfo, key:String) {
session_key = key;
super(api_key, secret, loaderInfo);
}
}
}
The class essentially extends the existing FacebookSessionUtil class and adds the missing session key that is not passed per default when running inside an iFrame. The class is ready for usage, the only difference to the Super class is that we need to pass the session key manually to the constructor.
Now let’s move on to the feed template. Because adding feed templates was the main topic in one of the previous article, we do not need to repeat ourselves. Just make sure you have the following to template bundles ready:
{*actor*} seems to know movies since he spotted some errors in MovieExpert.
{*actor*} is searching for movie goofs in MovieExpert.
Here are they in my console:
Notice that the template bundle id will be different for your application. I will show you where the necessary code changes in order for the news to appear.
The final thought
So, now that the application is coded, we can finally test it.
As we can see, we finally achieved the harmony in the application. The components on the stage perfectly cooperate with the code. As we advance through the levels, by clicking on the mistakes found, we can see how the slider moves up displaying the current stage of the movie. Also, when we press on the hint button. We can see that there is a hint in the upper corner.
Conclusion
Maybe the application is a bit diffucult, but with the sample I wanted to utilize a lot of resources, from videos from YouTube, to the exensive use of the facebook api in actionscript. Maybe the application is missing some social part, so feel free to add features to the application that make the application lot more social and engaging.
I hope you enjoyed the whole series. It was fun to write about the topics and from your commonts, I can see that the series was quite successful. I hope to see more attractive facebook applications that will utilize the knowledge from my articles.
To view the entire series please visit http://www.insideria.com/series-facebook-dev.html




Facebook Application Development
Thanks for all !
very good job :)
but where is the source ?
it's always a good idea to publish source when we explain some code!
I'm quite confused with these codes, but I can still say you did a great job! You've made a great tutorials. Thanks for sharing!
Are you a Simpsons fan or is just a coincidence? Couldn't stop wondering because of the video you chose :)
Tim
This article looks well thought out and well written! I would love to have access to the code as well... is that possible?
Thanks for sharing!
Is there a way that you can pass Flashvars to a swf that is posted to a wall?
n terms of technology, Rojham used external contractors to build the Facebook functionality, although he also runs a small internal IT team for the SuperSwitcher site development. "Facebook is only four years old. A contractor may cost more, but they will have the experience and can produce better quality code fastermetal swing set."In terms of support, Rojham said the documentation was "quite good". He said, "There is a very active developer community, so if you do run into problems, these can be solved quite quickly."However, he warned that businesses looking to develop on the Facebook platform may need to overcome tricky technical hurdles. "On the negative side of things, Facebook seems very focused on supporting PHP only. So if you are using a different language, such as Python, you sometimes have to create workarounds, or use solutions developed by others in the community, which are of course less well-documented, and help from the Facebook team can be harder to come by."
Hi Mirza,
Thanks for the series it is great.
I had a question on the AS# API, with the FacebookPhoto specifcly.
When I upload a photo It works, if i loop throught the porperties of the event i get the succses andtype, and data. where data is a FacebookPhoto object, but one I try gettin the public properties from the event data ( in this case the FacebookPhoto) it seems to be empty, all properties listed in the documentation for Facebook photo return null.
Let me know if you have any Idea of what is wrong.