• (2 Pages)
  • +
  • 1
  • 2

Create a Memory game with ActionScript Flash MX 2004 - advanced ActionScript Rate Topic: -----

#1 Broly  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 16-December 04

Posted 24 January 2005 - 07:44 AM

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.

Posted 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

// 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 :)

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 :)

// 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 ;)
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...

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? :)

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

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.

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...

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 :-)

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 :)

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

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

This post has been edited by pioSko: 07 December 2006 - 02:44 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Create a Memory game with ActionScript

#2 mukraker  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 20-October 05

Posted 20 October 2005 - 01:19 PM

hey where can i DL the fla?, pls contact me via links-center(at)web.de
Was This Post Helpful? 0
  • +
  • -

#3 Broly  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 16-December 04

Posted 31 October 2005 - 04:54 AM

Hello, sorry for the late :(
I've not the .fla for this tutorial yet :(, but is a simple copy&paste of code, you shouldn't have problems to recreate the fla :)
Was This Post Helpful? 0
  • +
  • -

#4 Breed  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 14-November 05

Posted 14 November 2005 - 07:43 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 ! ;) Genuine !
Was This Post Helpful? 0
  • +
  • -

#5 Broly  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 16-December 04

Posted 15 November 2005 - 02:54 AM

Breed, on 14 Nov, 2005 - 08:40 AM, said:

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 ! ;) 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 :)
Was This Post Helpful? 0
  • +
  • -

#6 John_Doe  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 17-November 05

Posted 17 November 2005 - 02:00 AM

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?
Was This Post Helpful? 0
  • +
  • -

#7 meshorer  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 02-December 05

Post icon  Posted 02 December 2005 - 08:20 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:

Attached File(s)


Was This Post Helpful? 0
  • +
  • -

#8 Breed  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 14-November 05

Posted 04 December 2005 - 07:00 AM

Broly, on 15 Nov, 2005 - 03:51 AM, said:

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 :)

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 ?
Was This Post Helpful? 0
  • +
  • -

#9 Jimbo_Jones  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 06-December 05

Posted 06 December 2005 - 11:37 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
Was This Post Helpful? 0
  • +
  • -

#10 Blokhut  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 05-January 06

Posted 05 January 2006 - 07:21 AM

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?
Was This Post Helpful? 0
  • +
  • -

#11 vectaman  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 06-February 06

Posted 06 February 2006 - 05:42 PM

How do you make it so that the game resets automatically after it has been completed?
Was This Post Helpful? 0
  • +
  • -

#12 ivana  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 17-February 06

Posted 17 February 2006 - 02:12 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!
Was This Post Helpful? 0
  • +
  • -

#13 Broly  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 16-December 04

Posted 18 April 2006 - 02:09 AM

Breed, on 4 Dec, 2005 - 05:52 AM, said:

Broly, on 15 Nov, 2005 - 03:51 AM, said:

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 :)

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 :)
Was This Post Helpful? 0
  • +
  • -

#14 Broly  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 16-December 04

Posted 18 April 2006 - 02:11 AM

meshorer, on 2 Dec, 2005 - 07:12 AM, said:

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:

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 :)
Was This Post Helpful? 0
  • +
  • -

#15 Broly  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 16-December 04

Posted 18 April 2006 - 02:13 AM

Jimbo_Jones, on 6 Dec, 2005 - 10:29 AM, said:

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 :)
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2