School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become an Expert!

Join 307,084 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 2,263 people online right now. Registration is fast and FREE... Join Now!




Create a Memory game with ActionScript

2 Pages V  1 2 >  
Reply to this topicStart new topic

> Create a Memory game with ActionScript, Flash MX 2004 - advanced ActionScript

Broly
Group Icon



post 24 Jan, 2005 - 06:44 AM
Post #1


Create a Memory game... in less than 2kb!

See you again friends :-)
Well, this time we’re going to create a little memory game... it can be a stand-alone game but also, especially thanks to his small dimensions ( < 2 kb!) it can also be an "interactive preloader" for bigger movies... and I think that this is his ideal use :-)
But stop talk... let’s go!

1 – The concept

First of all, we must establish what the player can or can’t do during the game, and how the game will interact with the user and his input. The general lines, and the general concept of this game, is simple

1) user click on a card
2) the card turn and show her symbol
3) user click on the 2nd card
4) the 2nd card show her symbol

Here the game must execute a control... if the cards are equals, the score must increase and the two cards must disappear, otherwise the score doesn’t increase and the cards turn again on their "backface". We must also put some "limitations" to the player... more specifically

- Once selected the 1st card, user can’t click again on it before next turn
- User can’t click on the 2nd card before the 1st has turned
- User must wait the control between 2 cards, he can’t discover more then 2 cards for turn

Those limitations are useful especially for avoid some "mistakes" or problems during the game... we’ll see more in detail during this tutorial.

Well, now we’ve established the general points, inputs and limitations of the game... it’s time to create it, come on!

2 – Setting up, what we need


All we need is love... ops... no, not for this game... now we need

- Flash
- A graphic program (for the "cards contents" creation)

Before start coding (yes, just coding... I haven’t yet told you that the game will be entirely in actionscript ? ;-)), we must create the cards images. In this example, I used 80x90 cards, with 70x80 images... you can make cards at every size you want... in fact the game will be entirely dynamic! It will automatic establish how many cards can be placed on the playground following the size we’ll specify in the code... it’s nice, isn’t it? :-)

Now place the images in "imgs" folder, at the same level of the .fla... the image can explain better the directory and file structure.

IPB Image


Well, in the "imgs" folder we have all the necessary images... now we can pass to flash... we’ve a lot to do with actionscript this time, are you ready? ;-)

3 – Flash and actionscript, the hearth of our game

As I said before, this game will be entirely made in actionscript... all the game will be composed of 130-140 lines of code. In fact, it’s a simple game with a simple structure and interaction... I’ll try to explain why we must put some limitations in this game (seen at point 1), also if the code tells almost all :-)
Let’s start!
First of all, set the canvas size at 550x400, and the framerate at 25 fps.
NOTE: When you test this movie, DON’T show the bandwidth profiler, because when it’s shown in the "test movie" window, the Stage.height action return wrong values (eg 300 instead 400, in our situation).

On the first (and only!) frame, start with this code

CODE
// Gamefield settings

// EDIT HERE
card_w = 70;
card_h = 90;
card_wdistance = 10;
card_hdistance = 10;

// STOP EDIT
card_dw = card_w + card_wdistance;
card_dh = card_h + card_hdistance;
row_card = Math.floor((Stage.width - card_wdistance) / card_dw);
col_card = Math.floor((Stage.height - card_hdistance) / card_dh);
n_card = col_card * row_card % 2 == 0 ? col_card * row_card : (col_card - 1) * row_card;
imgs_n = n_card / 2;


What it do? Well, see in detail.
With the "editable lines" we establish
Card width (card_w)
Card height (card_h)
Distance between cols (card_wdistance)
Distance between rows (card_hdistance)

Other lines simply calculate the number of cards that can be placed on the gamefield... with the calculation that you can see in the code smile.gif

N_card and imgs_n are the final count of cards on the gamefield and the number of images that we need (obviously images are n_card/2 before we must have couple of cards with the same image ;-))

Now, the code that will generate the gamefield... it’s not too hard to comprise, also if it has some points that will require some explanations.

Here ALL the code for the gamefield generation... and also a little more smile.gif

CODE
// CENTER THE IMAGE IN THE CARD
centerImage = function(target){
    target.front._visible = false
    target.front.container._x -= target.front.container._width / 2
    target.front.container._y -= target.front.container._height / 2
}
// ---------------------------------------------
  
empty = new Array();
function createCard(n, w, h) {
    empty.push(n);
    this.createEmptyMovieClip('card' + n, n);
    with (this['card' + n]) {
        lineStyle(0, 0x000000, 100);
        beginFill(0x000099, 60);
        moveTo(w / 2, 0);
        lineTo(w / 2, h / 2);
        lineTo(-w / 2, h / 2);
        lineTo(-w / 2, -h / 2);
        lineTo(w / 2, -h / 2);
        lineTo(w / 2, 0);
        endFill();
        createEmptyMovieClip('front', 1);
        front.createEmptyMovieClip('container', 2);
        front.createEmptyMovieClip('backgr', 1);
        with (front.backgr) {
            moveTo(-w / 2, -h / 2);
            lineStyle(0, 0x000000, 0);
            beginFill(0x333333, 100);
            lineTo(w / 2, -h / 2);
            lineTo(w / 2, h / 2);
            lineTo(-w / 2, h / 2);
            lineTo(-w / 2, -h / 2);
            endFill();
        }
        front.onEnterFrame = function() {
            tot = this.container.getBytesTotal();
            car = this.container.getBytesLoaded();
            if (tot == car && tot > 200) {
                this._parent._parent.centerImage(this._parent);
                delete this.onEnterFrame;
            }
        };
    }
}
selcards = [];
function placeImages() {
    act_img = 0;
    for (img = 0; img < imgs_n; img++) {
        for (k = 0; k < 2; k++) {
            act = Math.round(Math.random() * (empty.length - 1));
            this['card' + empty[act]].img_id = act_img;
            this['card' + empty[act]].front.container.loadMovie("imgs/img" + act_img + ".jpg");
            this['card' + empty[act]].onRelease = function() {
                this.rotateCard(0, 0);
                this.enabled = false;
                MovieClip.prototype.enabled = false;
            };
            empty.splice(act, 1);
        }
        act_img++;
    }
}
MovieClip.prototype.rotateCard = function(v, i) {
    this.operazione = v == 0 ? +0.1 : -0.1;
    this.incremento = i == 0 ? 100 : 10;
    selcards.push(this._name);
    this.onEnterFrame = function() {
        this.incremento += this.operazione;
        this._xscale = (100 * Math.sin(this.incremento));
        if (this._xscale > 0) {
            this.front._visible = v == 1 ? false : true;
        }
        if (this._xscale >= 99) {
            delete this.onEnterFrame;
            selcards.length < 2 ? MovieClip.prototype.enabled = true : null;
            v == 0 && selcards.length > 1 ? checkCards() : null;
        }
    };
};
function generateGameField(cards, distance, hdistance) {
    Ypos = card_h / 2 + hdistance;
    Xpos = card_w / 2 + distance;
    for (c = 0; c < cards; c++) {
        createCard(c, card_w, card_h);
        if (c % row_card == 0 && c > 0) {
            Ypos += this['card' + c]._height + hdistance;
            Xpos = card_w / 2 + distance;
        }
        this['card' + c]._x = Xpos;
        this['card' + c]._y = Ypos;
        Xpos += this['card' + c]._width + distance;
    }
    placeImages();
}
generateGameField(n_card, card_wdistance, card_hdistance);


Ok ok don’t escape... now we’ll see it in smart pieces wink2.gif
First of all, the generateGameField() function also if it’s the last function in the code, it’s the "main function", in fact is the only that we call directly... here the same code with some comment for explain better...

CODE
function generateGameField(cards, distance, hdistance) {
    Ypos = card_h / 2 + hdistance;
    Xpos = card_w / 2 + distance;
    for (c = 0; c < cards; c++) {
        createCard(c, card_w, card_h);
        if (c % row_card == 0 && c > 0) {
            Ypos += this['card' + c]._height + hdistance;
            Xpos = card_w / 2 + distance;
        }
        this['card' + c]._x = Xpos;
        this['card' + c]._y = Ypos;
        Xpos += this['card' + c]._width + distance;
    }
    placeImages();
}


It establish the X and Y position of the first card. Then, using a for() loop, it create (calling the createCard() function) all the cards, and place it on the gamefield... then it call the placeImages() function. Not hard, really? smile.gif

Now the real core of the gamefield generation... createCard() and placeImages() functions.

CODE
function createCard(n, w, h) {
    empty.push(n);
    this.createEmptyMovieClip('card' + n, n);
    with (this['card' + n]) {
        lineStyle(0, 0x000000, 100);
        beginFill(0x000099, 60);
        moveTo(w / 2, 0);
        lineTo(w / 2, h / 2);
        lineTo(-w / 2, h / 2);
        lineTo(-w / 2, -h / 2);
        lineTo(w / 2, -h / 2);
        lineTo(w / 2, 0);
        endFill();
        createEmptyMovieClip('front', 1);
        front.createEmptyMovieClip('container', 2);
        front.createEmptyMovieClip('backgr', 1);
        with (front.backgr) {
            moveTo(-w / 2, -h / 2);
            lineStyle(0, 0x000000, 0);
            beginFill(0x333333, 100);
            lineTo(w / 2, -h / 2);
            lineTo(w / 2, h / 2);
            lineTo(-w / 2, h / 2);
            lineTo(-w / 2, -h / 2);
            endFill();
        }
    }
}


Excluding the first line ( empty.push(n) ), that simply add at the "empty" array a number, that will be useful for the images placing (see it later), this function draw a card... We can’t use 4 simple lineTo(), because in that mode the movieclip center will be at the corner high left... while we want the center... at the center! (it’s necessary for the right card rotation). Than we use a more complex structure. Every card is structured as

- card
- front
- background
- container

Card is the movieclip the user will click and see at the start of the game... the "backface", we can call. While front has background (the "frontface" background) and container (where we’ll load the image). At the end, this function is simple... it create the backface and the frontface of every card... I think it isn’t useful explain every line, because they’re simply lineTo()... you can imagine what they do :-)

As we seen, the generateGameField() function calls the placeImages() function once the cards are created... as the name says, this function put the images into cards....we use the empty array (into we inserted data in the createCard() function, as said before) for know how cards are yet "empty".
The "mechanism" is simple. We take a number (eg 1), and put the image in "imgs/img"+n+".jpg" (eg imgs/img1.jpg) into two cards... and remove that cards from the "empty" array.

CODE
function placeImages() {
    act_img = 0;
    for (img = 0; img < imgs_n; img++) {
        for (k = 0; k < 2; k++) {
            act = Math.round(Math.random() * (empty.length - 1));
            this['card' + empty[act]].img_id = act_img;
            this['card' + empty[act]].front.container.loadMovie("imgs/img" + act_img + ".jpg");
            this['card' + empty[act]].front.onEnterFrame = function() {
                tot = this.container.getBytesTotal();
                car = this.container.getBytesLoaded();
                if (tot == car && tot > 200) {
                    this._parent._parent.centerImage(this._parent);
                    delete this.onEnterFrame;
                }
            };
            this['card' + empty[act]].onRelease = function() {
                this.rotateCard(0, 0);
                this.enabled = false;
                MovieClip.prototype.enabled = false;
            };
            empty.splice(act, 1);
        }
        act_img++;
    }
}


Act_img establish what image load... we start from img0.jpg, and go on since img is < imgs_n (that, as saw, it’s the number of images we need).

The loop for(k=0;k<2;k++) is useful for full TWO cards...it select a random card from that avaibles (empty.length tell us how many cards are avaible yet), than assign img_id at the card, and load the image into cardN.front.container.
The enterFrame() tell us when the image is loaded, then we can center the image in the card (see centerImage() function)
The onRelease() function is what the card will do once clicked by the user... and what it do? It call another function... rotateCard, then disable all the movieclips on the scene (in fact we said that once a card is clicked, the user must wait that it’s turned on her frontface before he can click the 2nd card). Well... see the rotateCard function...

CODE
MovieClip.prototype.rotateCard = function(v, i) {
    this.operazione = v == 0 ? +0.1 : -0.1;
    this.incremento = i == 0 ? 100 : 10;
    selcards.push(this._name);
    this.onEnterFrame = function() {
        this.incremento += this.operazione;
        this._xscale = (100 * Math.sin(this.incremento));
        if (this._xscale > 0) {
            this.front._visible = v == 1 ? false : true;
        }
        if (this._xscale >= 99) {
            delete this.onEnterFrame;
            selcards.length < 2 ? MovieClip.prototype.enabled = true : null;
            v == 0 && selcards.length > 1 ? checkCards() : null;
        }
    };
};


How to explain it... hmm... simpy tell that when we pass 0,0 at the function, the image turn on her frontface, while we pass 1,1 she turn on her backface (we’ll pass 1,1 if the 2 cards selected by the user won’t be equals). At the end of the turning, all movieclips on the stage are enabled (then the user can select other cards).

Last (but absolutely not least!) function is checkCards(), that we call when selected.length > 1 (it simply means that the checkCards() function is called when the user has selected the 2 cards).
NOTE : this function wasn’t in the "big amount" of code before, you must paste it after the generateGameField() function :-)

CODE
score = 0;
this.createTextField('punti', -1, 500, 380, 0, 0);
punti.autoSize = true;
punti.text = 0;
function checkCards() {
    if (this[selcards[0]].img_id == this[selcards[1]].img_id) {
        score++;
        punti.text = score;
        eval(selcards[0])._visible = eval(selcards[1])._visible = false;
    } else {
        eval(selcards[0]).rotateCard(1, 1);
        eval(selcards[1]).rotateCard(1, 1);
        eval(selcards[0]).enabled = eval(selcards[1]).enabled = true;
    }
    selcards = [];
    MovieClip.prototype.enabled = true;
}


It’s very simple... it check if the img_id of the 2 selected cards are equal. If true, it means that two cards contain the same image, then they can became invisible and the score must increase. Otherwise, the cards are different, then they must turn on their backface (in fact we call rotateCard with 1,1) and come back enabled.
In both situations, the array "selcards" (that must always contains only the names of the 2 selected card) is re-setted and all movieclips are enabled.
"punti" is a text field (created using createTextField()) that show the user score.

Well... we created a simple small game... .I haven’t inserted a "game over "events or similar, because I think that this game, for his weight less than 2 kb, is useful as "interactive preloader"... also because if we’d like to create a "standalone" memory we’d use a more beautiful graphics and other elements that will make the movie less light but more attractive smile.gif

I hope you liked this small tutorial... and I also hope you understood the explanation, even if the code wasn’t too complex smile.gif
See you next time... byez ;-)

[edit: Changed to UTF-8 and reformatted - pioSko]

This post has been edited by pioSko: 7 Dec, 2006 - 01:44 AM
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!

mukraker
*



post 20 Oct, 2005 - 12:19 PM
Post #2
hey where can i DL the fla?, pls contact me via links-center(at)web.de
Go to the top of the page
+Quote Post

Broly
Group Icon



post 31 Oct, 2005 - 03:54 AM
Post #3
Hello, sorry for the late sad.gif
I've not the .fla for this tutorial yet sad.gif, but is a simple copy&paste of code, you shouldn't have problems to recreate the fla smile.gif
Go to the top of the page
+Quote Post

Breed
*



post 14 Nov, 2005 - 06:43 AM
Post #4
Hi Broly. One lame question - which function should be called in the end to start the game from the beggining ?


I'm a REAL newbie ! wink2.gif Genuine !
Go to the top of the page
+Quote Post

Broly
Group Icon



post 15 Nov, 2005 - 01:54 AM
Post #5
QUOTE(Breed @ 14 Nov, 2005 - 08:40 AM)
Hi Broly. One lame question - which function should be called in the end to start the game from the beggining ?


I'm a REAL newbie ! wink2.gif Genuine !

Hi Breed, the function that generate the game is

generateGameField(n_card,card_wdistance,card_hdistance)

In fact, as you can see in the code I posted, I create all the functions and at last I call generateGameField...because she's the "hearth" of the game smile.gif
Go to the top of the page
+Quote Post

John_Doe
*



post 17 Nov, 2005 - 01:00 AM
Post #6
Hi Broly. Great code at all but i tried to delay the "rotateCard" function and it doesnt works.
I think its more comfortable to see the images a few seconds longer if these doesnt match.
Any ideas?
Go to the top of the page
+Quote Post

meshorer
*



post 2 Dec, 2005 - 07:20 AM
Post #7
Hi Guys,

well i'm quite new to flash and to Action Scripts.
i try this code of the memory game with my macromedia flash 8 and it doesn't work (attached is what i tried to do).

can someone please send me a working fla file of this game.

thanks in advance

meshorer.

hameshorer@gmail.com blink.gif


Attached File(s)
Attached File  memory_game.zip ( 24.74k ) Number of downloads: 1851
Go to the top of the page
+Quote Post

Breed
*



post 4 Dec, 2005 - 06:00 AM
Post #8
QUOTE(Broly @ 15 Nov, 2005 - 03:51 AM)

Hi Breed, the function that generate the game is

generateGameField(n_card,card_wdistance,card_hdistance)

In fact, as you can see in the code I posted, I create all the functions and at last I call generateGameField...because she's the "hearth" of the game smile.gif

OK I see that, but how can I create a loop with generateGameField function so when there are no cards on the screen it starts again ?
Go to the top of the page
+Quote Post

Jimbo_Jones
*



post 6 Dec, 2005 - 10:37 AM
Post #9
Hello Broly,
Excellent code very clean and compact. However, I am having a little trouble with the rotateCard method. I have noticed within the game, when I click on more than two cards consecutively, one of the cards will often get stuck face up. I can't figure out what is causing this but, I think it is in the rotateCard method. Thank you in advance for you time and I really appreciate you posting the code for the game.
-Jimbo
Go to the top of the page
+Quote Post

Blokhut
*



post 5 Jan, 2006 - 06:21 AM
Post #10
Broly thanks for the great tut!

But i was wondering if its posible to show a text line when two cards match, on a simple manner for each pair a different line? And to set a limitation on the numbers of turns?
Go to the top of the page
+Quote Post

vectaman
*



post 6 Feb, 2006 - 04:42 PM
Post #11
How do you make it so that the game resets automatically after it has been completed?
Go to the top of the page
+Quote Post

ivana
*



post 17 Feb, 2006 - 01:12 AM
Post #12
Hi!

How can I place some image on background of each card (when I create a card, I would like to place some image, not only colour. I would like to place the same image of each card, before I open that cards)?


Thank you!
Go to the top of the page
+Quote Post

Broly
Group Icon



post 18 Apr, 2006 - 01:09 AM
Post #13
QUOTE(Breed @ 4 Dec, 2005 - 05:52 AM)
QUOTE(Broly @ 15 Nov, 2005 - 03:51 AM)

Hi Breed, the function that generate the game is

generateGameField(n_card,card_wdistance,card_hdistance)

In fact, as you can see in the code I posted, I create all the functions and at last I call generateGameField...because she's the "hearth" of the game smile.gif

OK I see that, but how can I create a loop with generateGameField function so when there are no cards on the screen it starts again ?

Hi Breed, you can control the cards on the field and the number of couples: when you have found all cards, with a simple "if" statement you can start the game again calling the GenerateGameField function and setting all the vars to their initial state smile.gif
Go to the top of the page
+Quote Post

Broly
Group Icon



post 18 Apr, 2006 - 01:11 AM
Post #14
QUOTE(meshorer @ 2 Dec, 2005 - 07:12 AM)
Hi Guys,

well i'm quite new to flash and to Action Scripts.
i try this code of the memory game with my macromedia flash 8 and it doesn't work (attached is what i tried to do).

can someone please send me a working fla file of this game.

thanks in advance

meshorer.

hameshorer@gmail.com blink.gif

Hi meshorer, the game is create with Flash Mx2004 and unluckly there are some differences between two versions in actionscript so the game probably doesn't work correctly in Flash 8.
Actually I'm very busy (in fact I'm replying with an huge late and I'm very sorry) but in future I'd try to re-create the game with Flash 8 smile.gif
Go to the top of the page
+Quote Post

Broly
Group Icon



post 18 Apr, 2006 - 01:13 AM
Post #15
QUOTE(Jimbo_Jones @ 6 Dec, 2005 - 10:29 AM)
Hello Broly,
Excellent code very clean and compact. However, I am having a little trouble with the rotateCard method. I have noticed within the game, when I click on more than two cards consecutively, one of the cards will often get stuck face up. I can't figure out what is causing this but, I think it is in the rotateCard method. Thank you in advance for you time and I really appreciate you posting the code for the game.
-Jimbo

You're right Jimbo, unluckly the rotateCard method is not perfect and has some problem, so in some situation it show something wrong.
As I wrote before, actually I'm very busy but in next future I should try to recreate the game improving it and making it compatible with Flash 8, then I'd post the new code smile.gif
Go to the top of the page
+Quote Post

Broly
Group Icon



post 18 Apr, 2006 - 01:17 AM
Post #16
QUOTE(ivana @ 17 Feb, 2006 - 01:04 AM)
Hi!

How can I place some image on background of each card (when I create a card, I would like to place some image, not only colour. I would like to place the same image of each card, before I open that cards)?


Thank you!

Hi ivana, unluckly the "scope" of the tutorial was to create a small game interally with AS, so the card are created dinamically.
Everyway you can place an image on the back of the cards or loading it with loadMovie, and showing it insted the color, or creating manually a card then using duplicateMovieClip to create other ones, but you should make some change on the code smile.gif
In next "version" on the game I'll consider also this aspect smile.gif
Go to the top of the page
+Quote Post

Broly
Group Icon



post 18 Apr, 2006 - 01:18 AM
Post #17
Ok friends I hope I replied all, I'm very sorry for this HUGE late, I hope that you will forgive me when I'll post the new version of the game and maybe some new tutorial, even if I'm busy now so I can't guarantee WHEN I'll do it...but I promise I'll do wink2.gif
Go to the top of the page
+Quote Post

surfergirl1
*



post 24 Jul, 2006 - 09:24 PM
Post #18
I tried out the code & everything worked great but the game doesn't work after turning over two cards. I'm using Flash MX 2004.

I really wanted to get this to work but I don't know enough about coding in actionscript. Can you please repost a revised version? I know people are asking for Flash 8 but if you could post both versions, that would be great.

This post has been edited by surfergirl1: 24 Jul, 2006 - 09:25 PM
Go to the top of the page
+Quote Post

twinstars_08
*



post 3 Nov, 2006 - 09:23 PM
Post #19
Hi I have tried using the codes for the memory games. Its great and it works. =) but i am wondering how can I do pop ups after every successful match. i have no idea how to start n modify it. blink.gif

any guide? as i am quite new to action script thanks.
Go to the top of the page
+Quote Post

azuuh
*



post 12 Mar, 2007 - 03:41 AM
Post #20
nice code. i still have one problem, when i play the movie i only get two cards to turn around and then they get stuck, i cant choose any cards after the two first ones.
Anybody who knows how to solve the problem?
im running flash 8 with as.2.0, i tryed to change the publish settings to flash 6 and tryed it with as.1.0 and as.2.0 but still wont work.
Go to the top of the page
+Quote Post


2 Pages V  1 2 >
Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 


Lo-Fi Version Time is now: 11/21/09 10:42AM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month