Author Topic: [Facebook Game] 60 Seconds  (Read 4729 times)

hima

  • Member
  • **
  • Posts: 96
  • Karma: +0/-0
    • View Profile
    • My Dev Blog
[Facebook Game] 60 Seconds
« on: Mon, Jan 18, 2010 »
My first attempt to make a flash game integrating facebook api for leaderboard and stuffs.

http://apps.facebook.com/sixtyseconds/?ref=mf

The game is a your basic bullet hell shmup game. You have to survive for 60 seconds while trying to get as many points as possible. The enemy waves are procedural generated, and will get more and more difficult as time pass. Going up higher on the screen will give you more multiplier. You can also enter slow mode for precise movement by holding left shift, but that will halve down your current multiplier.

This is still beta though. I have yet to implement global ranking and a proper post publish since right now it doesn't look too good. ( I might make just a button for you to click instead. ) Also, I'm thinking about adding MochiAds but with the new flixel I have no idea where to put it. Have to experiment again, I guess.

Anyway, happy gaming! New flixel rocks! The game plays very smoothly on my computer, and I hope it's the same for you guys!

fefranca

  • Guest
Re: [Facebook Game] 60 Seconds
« Reply #1 on: Mon, Jan 18, 2010 »
Hi hima, 60 seconds looks fun and polished. I think the game needs to allow for a bit more skill.. there are certain times where it becomes 100% luck.

Ranking seems to work fine, even shows my scary profile picture there. I'm enjoying my first position on the ranking for now (before anyone else plays it :D)

Oh, love the ellipse / explosion effects :)

Richard Kain

  • Active Member
  • ***
  • Posts: 231
  • Karma: +0/-0
    • View Profile
Re: [Facebook Game] 60 Seconds
« Reply #2 on: Mon, Jan 18, 2010 »
I'm at work at the moment, so I can't log-in to Facebook. I will definitely give this a try when I get home.

Question, how difficult is it to integrate Flash, and in particular Flixel, into the Facebook API? I have been thinking about developing a certain type of game, and was considering the various platforms that I should target. It occured to me that Facebook would probably be one of the very best platforms for this game. I've begun investigating the process, but hearing about the experiences of someone who has already gone through the process would be invaluable.

Rolpege

  • Guest
Re: [Facebook Game] 60 Seconds
« Reply #3 on: Mon, Jan 18, 2010 »
Awesome game! Looks very well.

It cost me to know that they're only my friends scores, but I'm happy because I'm first! I'm waiting for those global scores =D.

bobbybaker82

  • Active Member
  • ***
  • Posts: 155
  • Karma: +0/-0
    • View Profile
Re: [Facebook Game] 60 Seconds
« Reply #4 on: Mon, Jan 18, 2010 »
I can't get it to load, just keeps refreshing the page for me.

hima

  • Member
  • **
  • Posts: 96
  • Karma: +0/-0
    • View Profile
    • My Dev Blog
Re: [Facebook Game] 60 Seconds
« Reply #5 on: Tue, Jan 19, 2010 »
Hi hima, 60 seconds looks fun and polished. I think the game needs to allow for a bit more skill.. there are certain times where it becomes 100% luck.

Ranking seems to work fine, even shows my scary profile picture there. I'm enjoying my first position on the ranking for now (before anyone else plays it :D)

Oh, love the ellipse / explosion effects :)

Thanks! Yeah, many people complain about the too much luck issue. I'll try a fix pattern of waves as well as maybe adding an extra boss for those who get to a certain amount of score. :D

I'm at work at the moment, so I can't log-in to Facebook. I will definitely give this a try when I get home.

Question, how difficult is it to integrate Flash, and in particular Flixel, into the Facebook API? I have been thinking about developing a certain type of game, and was considering the various platforms that I should target. It occured to me that Facebook would probably be one of the very best platforms for this game. I've begun investigating the process, but hearing about the experiences of someone who has already gone through the process would be invaluable.
Well, tutorials on flash game on facebook with ActionScript3 API is very limited at this moment so it might be hard to get start. I've found two or three so far. You can start from here.

Once you know where to start, it isn't that difficult to go on from there. Basically you need to know how to contact between Flash, PHP and MySQL. If you know all these, then it'll be really as easy as learning which facebook function does what you want. Unfortunately, I hate internet programming and never really interested in neither PHP no MySQL so it was uncomfortable for me lol. Debugging is probably the worse part of all, since you have to upload it to facebook and debug from there. Flixel log really helps here, as well as other logging technique if you think FlxLog doesn't do the job.

I wonder if there are other developers who have done this and would like to share their experiences too, since it is now like a voodoo magic that nobody wants to talk about. I'll make a thread in chat and telling more about my experience once I really finish this game ( global ranking, publish post etc. )

One thing I can tell you is I find separating your game into two swf helps a lot and I should have done that. One for your game, another one for leaderboard. You can send messages from one swf to another.

Awesome game! Looks very well.

It cost me to know that they're only my friends scores, but I'm happy because I'm first! I'm waiting for those global scores =D.

I'll get it done ASAP :)

I can't get it to load, just keeps refreshing the page for me.
I'm so sorry about this. Could you please try logging in to your facebook account first then click the game link? Please tell me how this work for you so I can narrow down the problem. Thanks!

bobbybaker82

  • Active Member
  • ***
  • Posts: 155
  • Karma: +0/-0
    • View Profile
Re: [Facebook Game] 60 Seconds
« Reply #6 on: Tue, Jan 19, 2010 »
Logging in first worked, cool game :)

hima

  • Member
  • **
  • Posts: 96
  • Karma: +0/-0
    • View Profile
    • My Dev Blog
Re: [Facebook Game] 60 Seconds
« Reply #7 on: Tue, Jan 19, 2010 »
Logging in first worked, cool game :)
Ok so the problem should be my first page php X(  But I have tried going to that url without logging in and it works fine. Does this happen to anyone else?

Anyway, I have added a global highscore. Should I have a separate list between weekly, monthly and all time highscore?

One problem I found right now is that the profile picture from facebook has to be external loading. I loaded it using Loader class and add it as a child object for the stage. But doing it this way cause it to be on top of the flixel screen. Thus, everything render by flixel is on the back of these profile pictures. If there's a better way to do this then I'd love to know too.

Right I'm working on fullscreen option. I'm sure some people prefer playing shmup fullscreen :)
« Last Edit: Wed, Jan 20, 2010 by hima »

Richard Kain

  • Active Member
  • ***
  • Posts: 231
  • Karma: +0/-0
    • View Profile
Re: [Facebook Game] 60 Seconds
« Reply #8 on: Wed, Jan 20, 2010 »
Hmmmmm...there should be a way to load it dynamically, and then integrate it with Flixel. Even though the general approach for Flixel is to have your files embedded, that is not a hard and fast requirement.

Richard Kain

  • Active Member
  • ***
  • Posts: 231
  • Karma: +0/-0
    • View Profile
Re: [Facebook Game] 60 Seconds
« Reply #9 on: Thu, Jan 21, 2010 »
Whooof! Okay, I did a little research on this one.

Embedded graphic in AS3 are loaded as BitmapAssets. The problem is that the BitmapAssets class belongs to the mx library group, and not the flash library. (so it isn't available by defaut to anyone using the command-line compilers, and/or FlashDevelop)

Of course, that's just part of the problem. Flixel's base classes only have routines for accepting variables of type "Class." If we had easy access to the BitmapAsset class, then it might be able to pass that in as a Class variable.

There might be a faster solution here that I'm just not seeing. But the sure-fire way for this to work would be to extend the FlxG and FlxSprite classes, and add the necessary functions for loading up Bitmap graphic objects. When dynamically loading graphic assets from a folder or specific URL, it is common to create a Bitmap display object using them. In fact, you might be able to just cut out the middle man and allow for the loading of bitmapData directly.

Richard Kain

  • Active Member
  • ***
  • Posts: 231
  • Karma: +0/-0
    • View Profile
Re: [Facebook Game] 60 Seconds
« Reply #10 on: Thu, Jan 21, 2010 »
Okay kids, pull up a chair. It's tutorial time.

For a solution to this problem, I first had to go to the FlxG class. The addBitmap() function in the FlxG class is used in the FlxSprite class everytime graphics are loaded into a new FlxSprite instance. But the addBitmap() function will only accept a Class as it's graphic resource. I went into the FlxG class, and reproduced the function, only this time using a Bitmap for the graphic, instead of a Class.

FlxG.as
Code: [Select]
static public function addLoadedBitmap(Graphic:Bitmap, Reverse:Boolean=false, Unique:Boolean=false):BitmapData
{
var needReverse:Boolean = false;
var key:String = String(Graphic);
if (Unique && (_cache[key] != undefined) && (_cache[key] != null))
{
var inc:uint = 0;
var uKey:String;
do { uKey = key + inc++;
} while ((_cache[uKey] != undefined) && (_cache[uKey] != null));
key = uKey;
}
if ((_cache[key] == undefined) || (_cache[key] == null))
{
_cache[key] = Graphic.bitmapData;
if (Reverse) { needReverse = true; }
}
var pixels:BitmapData = _cache[key];
if (!needReverse && Reverse && (pixels.width == Graphic.bitmapData.width))
{
needReverse = true;
}
if (needReverse)
{
var newPixels:BitmapData = new BitmapData(pixels.width << 1, pixels.height, true, 0x00000000);
newPixels.draw(pixels);
var mtx:Matrix = new Matrix();
mtx.scale(-1, 1);
mtx.translate(newPixels.width, 0);
newPixels.draw(pixels, mtx);
pixels = newPixels;
}
return pixels;
}

On the whole, this is very similar to the addBitmap() function. It's times like these that I wish Actionscript 3 supported function overloading. You'll notice that we pass a Bitmap object in as the argument for the Graphic. The Bitmap object can contain bitmapData, which is what we're really after. The Bitmap class is also very easy to use with Flash's built-in loading features, which we'll get into later.

Code: [Select]
_cache[key] = Graphic.bitmapData;This line is different from the original function. In the original code, we used an instance of the Graphic Class to pass in our bitmapData. Here, we have a Bitmap object, and can pass the bitmapData from it directly.

Code: [Select]
if (!needReverse && Reverse && (pixels.width == Graphic.bitmapData.width))
{
needReverse = true;
}
The same thing happens in this if statement. Where before we had to instance the Class, here we already have an object created.

Now we have a means to use the FlxG class to add a Bitmap object, as opposed to an Embedded Class. Now it's time to move on to the FlxSprite class. For the FlxSprite, I decided to extend the class into a new class. Trying to extend a class like FlxG would have been a pain. But there's no harm in extending FlxSprite to create a new class with just a bit of added functionality. There may be times when we would want to use both FlxSprite and our new class in the same flash file.

FlxLoadSprite.as
Code: [Select]
package org.flixel
{
import flash.display.Bitmap;
public class FlxLoadSprite extends FlxSprite
{

public function FlxLoadSprite(X_pos:uint, Y_pos:uint):void
{
super(X_pos, Y_pos);
}

override public function update():void
{
super.update();
}

public function loadExtGraphic(Graphic:Bitmap,Animated:Boolean=false,Reverse:Boolean=false,Width:uint=0,Height:uint=0,Unique:Boolean=false):FlxSprite
{
_pixels = FlxG.addLoadedBitmap(Graphic, Reverse, Unique);
if (Reverse)
{
_flipped = _pixels.width >> 1;
}
else {
_flipped = 0;
}
if (Width == 0)
{
if (Animated)
{
Width = _pixels.height;
}
else {
Width = _pixels.width;
}
}
width = _bw = Width;
if (Height == 0)
{
if (Animated)
{
Height = width;
}
else {
Height = _pixels.height;
}
}
height = _bh = Height;
resetHelpers();
return this;
}
}
}

This is also fairly straightforward. The class is designed to be packaged with the rest of the flixel library. We need the Bitmap object class, so we have to import that as well. We didn't need this import for the FlxG class, because it already uses it. The beginning of the class should be familiar to anyone who has ever extended a FlxSprite in the past. We pass the X and Y starting positions into the constructor, and then we override the update function. In both, we use the super call to run the functions from the class we are extending from. (if you forget this step, your class won't integrate into Flixel properly)

The meat and potatoes of our new class is the loadExtGraphic() function. Again, this function is intended to mirror the original loadGraphic() function in the FlxSprite class. And again, the only real difference is that we use a Bitmap object instead of an Embedded Class. (check the first argument for the loadExtGraphic() function)

Now that we have done the prep work, we are ready to actually load an external graphic, and create a FlxSprite with it. For this example, I did my loading in an FlxState class. (that I extended)

LoadState.as
Code: [Select]
package
{
import org.flixel.FlxState;
import org.flixel.FlxLoadSprite;

import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.Bitmap;

public class LoadState extends FlxState
{
private var receivingMachine:Loader;
private var freshSprite:FlxLoadSprite;

public function LoadState():void
{
receivingMachine = new Loader();
receivingMachine.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
receivingMachine.load(new URLRequest("your_graphic_here.png"));
}
override public function update():void
{
super.update();
}
private function loadComplete(event_load:Event):void
{
freshSprite = new FlxLoadSprite(10, 10);
freshSprite.loadExtGraphic(new Bitmap(event_load.target.content.bitmapData), false, false, 128, 128);
add(freshSprite);
}
}
}

The class begins simply enough. The FlxState and FlxLoadSprite imports should be obvious. After that we get into new territory. These flash imports are necessary for dynamically loading in external graphics. The Loader class does the loading. The URLRequest class lets us tell the Loader class what we want loaded. The Event class will let us track the progress of the Loader class, and find out when it's finished. And the Bitmap class will give us something to put the loaded graphic into. I've defined two private variables for this class. Having an instance of the Loader class and the FlxLoadSprite class accessible from any of the functions in the LoadState class isn't strictly necessary, but could prove convenient if I actually do something with them later.

Code: [Select]
receivingMachine = new Loader();
receivingMachine.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
receivingMachine.load(new URLRequest("your_graphic_here.png"));

These lines in the constructor are where we instantiate our Loader object, and get down to sucking in our graphic. The first line creates an instance of the Loader. The second line accesses the Loader's contentLoaderInfo property, and assigns an event listener to it. This event listener lets us know when the loading process is complete. The function it specifies is where we'll use the content we've loaded. The third line is where we tell our Loader object to begin doing its thing. We also create a URLRequest here, and pass in the string variable of the graphic we want loaded.

If I may have a quick aside, you'll note that I used the Event.COMPLETE event in the event listener. This is valid, and will work fine, but it isn't the only option. You can also use Event.INIT instead. I used Event.COMPLETE because I only needed a basic loading. If you use Event.INIT, certain variables will be available at the end of the loading process that Event.COMPLETE doesn't provide. One of the most obvious would be the dimensions of the image you are loading. Event.INIT will provide you with the width and height of the image once it is loaded. So always use Event.INIT if you need to know the dimensions of your loaded image.

Back to the point, the string variable you pass into the URLRequest can be a local file, a relative file path, or a full URL. (example: "http://www.google.com/intl/en_ALL/images/logo.gif") Any valid path can be used. Just remember the guidelines for external file loading, and the permissions associated with them.

Code: [Select]
private function loadComplete(event_load:Event):void
{
freshSprite = new FlxLoadSprite(10, 10);
freshSprite.loadExtGraphic(new Bitmap(event_load.target.content.bitmapData), false, false, 128, 128);
add(freshSprite);
}

This final function is what we pointed the event listener at earlier. The name of the Event object that you pass in as an argument can be anything. I named it "event_load" on a whim, it can be whatever you please. On the first line, we create the FlxLoadSprite that will eventually house our loaded graphic, and give it a starting position. The second line is where we do most of the work. This is where we execute the loadExtGraphic() function that we created earlier. We instantiate a Bitmap object, and load the bitmapData from our loaded resource into it. We access this bitmapData using the Event argument. The Event argument provides us with the event's target, which in turn provides us with the content that the event's target loaded. And that is where the bitmapData we need is. On the last line, we add the newly populated FlxLoadSprite to the FlxState-extended class in the normal fashion.

hima

  • Member
  • **
  • Posts: 96
  • Karma: +0/-0
    • View Profile
    • My Dev Blog
Re: [Facebook Game] 60 Seconds
« Reply #11 on: Thu, Jan 21, 2010 »
Richard Kain, thank you SO MUCH! That was a brilliant tutorial! I'll try implement this today and see if there's any problem or is something missing. :D

EDIT : Actually, I've just realized I have asked this question on the help section before giving up and went with the DisplayObject instead of FlxSprite. Maybe it's better if you copy your reply here and post it in the topic below. :)

http://flixel.org/forums/index.php?topic=813.0
« Last Edit: Thu, Jan 21, 2010 by hima »

enpu

  • Guest
Re: [Facebook Game] 60 Seconds
« Reply #12 on: Wed, Jan 27, 2010 »
hima, can you please do a little tutorial on how to make facebook leaderboards on flixel game? :)

hima

  • Member
  • **
  • Posts: 96
  • Karma: +0/-0
    • View Profile
    • My Dev Blog
Re: [Facebook Game] 60 Seconds
« Reply #13 on: Fri, Jan 29, 2010 »
Sure! I'm actually working on that. Should be finished somewhere around next week :)

luc

  • Member
  • **
  • Posts: 97
  • Karma: +0/-0
  • no ablo anything except french
    • View Profile
    • scribbles
Re: [Facebook Game] 60 Seconds
« Reply #14 on: Fri, Jan 29, 2010 »
hooorray ! can't wait for the tutorial.
In the meantime I will work my hiscore on your game. :)
« Last Edit: Fri, Jan 29, 2010 by luc »

enpu

  • Guest
Re: [Facebook Game] 60 Seconds
« Reply #15 on: Sat, Jan 30, 2010 »
wow thanks! im waiting for that ;)

enpu

  • Guest
Re: [Facebook Game] 60 Seconds
« Reply #16 on: Wed, Feb 10, 2010 »
how is the tutorial going? ;)

hima

  • Member
  • **
  • Posts: 96
  • Karma: +0/-0
    • View Profile
    • My Dev Blog
Re: [Facebook Game] 60 Seconds
« Reply #17 on: Mon, Feb 15, 2010 »
Still writing! But now works got in the way :(

The draft is here at my blog
http://hima.gptouch.com/?p=152

I set it password protected because it isn't finished yet, but if you want to take a look at it the password is 'test' :)

I'll have more free time on Wednesday so I'm looking forward to write it more then :D Sorry if this take so long!

Anyway, I've also posted the resources for getting started with Flash Facebook app here >
http://flixel.org/forums/index.php?topic=942.0

Hope that helps!