Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about GuessNext game, Actionscript 2, Flash, Game development and Monetize.

Time to publish the complete tutorial about the making of GuessNext, a simple card game with highscores.

GuessNext

In order to make an highscore, you must register to Kongregate but you can play even if you don’t register.

It’s not meant to be a good or enjoyable game, it’s simply a programming exercise, so don’t expect the best game ever played before.

Anyway, it’s a good start for developing a complete and interesting card game.

The aim of the game is very simple: from a deck of 52 cards, you have to guess if each card is higher or lower than the previous one. That’s it.

Before we start talking about actionscript, a little information about the graphics.

This is the background

GuessNext

It was made with Photoshop selecting two green colors, one lighter than another, and using a clouds filter. Then, I give the result a light noise filter and the green background was done. The cards on the bottom left side are the same used in the game with a semi-transparent Soft Light blending.

The font is the Death Font you can find on dafont.com at this page.

Now, let’s go with the all-in-one-frame actionscript, just 172 lines to make a complete game

stop();
_root.kongregateServices.connect();
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.filters.DropShadowFilter;
import flash.filters.GlowFilter;
var card_shadow:DropShadowFilter = new DropShadowFilter(4, 45, 0x000000, .5, 4, 4, 1, 3, false, false, false);
var text_glow:GlowFilter = new GlowFilter(0x000000, .6, 4, 4, 2, 3, false, false);
show_splash();
function show_splash() {
	_root.attachMovie("splash","splash",_root.getNextHighestDepth());
	splash.blog_button.onRelease = function() {
		getURL("http://emanueleferonato.com/", "_blank");
	};
	splash.play_button.onRelease = function() {
		play_the_game();
		splash.removeMovieClip();
	};
	splash.how_to_button.onRelease = function() {
		show_info();
		splash.removeMovieClip();
	};
}
function show_info() {
	_root.attachMovie("info","info",_root.getNextHighestDepth());
	info.play_button.onRelease = function() {
		play_the_game();
		info.removeMovieClip();
	};
	info.back_button.onRelease = function() {
		show_splash();
		info.removeMovieClip();
	};
}
function play_the_game() {
	big_picture = BitmapData.loadBitmap("cardz");
	_root.attachMovie("table","table",_root.getNextHighestDepth());
	_root.createEmptyMovieClip("game",_root.getNextHighestDepth());
	game.attachMovie("higher","higher",game.getNextHighestDepth());
	game.attachMovie("lower","lower",game.getNextHighestDepth());
	game.createEmptyMovieClip("big_pic_obj",game.getNextHighestDepth());
	big_pic_obj.attachBitmap(big_picture,game.getNextHighestDepth());
	big_pic_obj._visible = false;
	sequence = new Array();
	Array.prototype.shuffle = function() {
		for (x=0; x<52; x++) {
			var from = Math.floor(Math.random()*52);
			var to = this[x];
			this[x] = this[from];
			this[from] = to;
		}
	};
	for (x=0; x<52; x++) {
		card = game.createEmptyMovieClip("small_pic_obj_"+x, game.getNextHighestDepth());
		sequence[x] = x;
		small_picture = new BitmapData(79, 123);
		card.attachBitmap(small_picture,game.getNextHighestDepth());
		small_picture.copyPixels(big_picture,new Rectangle(0+(x%13)*79, 0+Math.floor(x/13)*123, 79, 123),new Point(0, 0));
		card._visible = false;
		card.filters = new Array(card_shadow);
		card.onEnterFrame = function() {
			switch (this.action) {
				case "come" :
					this._x += 40;
					if (this._x>210) {
						this._x = 210;
						this.action = "stay";
						if (cards_drawn>1) {
							game.ok_ko._visible = true;
						}
					}
					break;
				case "move" :
					this._x += 20;
					if (this._x>310) {
						this._x = 310;
						this.action = "dissolve";
					}
					break;
				case "dissolve" :
					this._alpha -= 4;
					game.lap_score._alpha -= 4;
					if (this._alpha<0) {
						can_draw = true;
						game.ok_ko._visible = false;
						if (cards_drawn == 52) {
							endgame();
						}
						this.removeMovieClip();
					}
					break;
			}
		};
	}
	game.attachMovie("ok_ko","ok_ko",game.getNextHighestDepth(),{_x:250, _y:230, _visible:false});
	game.attachMovie("score","score",game.getNextHighestDepth(),{_x:0, _y:140});
	game.attachMovie("lap_score","lap_score",game.getNextHighestDepth(),{_x:-50, _y:0, _alpha:0});
	game.score.filters = new Array(text_glow);
	game.lap_score.filters = new Array(text_glow);
	sequence.shuffle();
	cards_drawn = 0;
	points = 0;
	can_draw = true;
	draw_card();
	game.higher.onRelease = function() {
		if (can_draw) {
			can_draw = false;
			higher = true;
			draw_card();
		}
	};
	game.lower.onRelease = function() {
		if (can_draw) {
			can_draw = false;
			higher = false;
			draw_card();
		}
	};
}
function draw_card() {
	game.ok_ko.gotoAndStop(2);
	lap = 0;
	if (((sequence[cards_drawn]%13)<=(sequence[cards_drawn-1]%13) and (!higher)) or ((sequence[cards_drawn]%13)>=(sequence[cards_drawn-1]%13) and (higher))) {
		game.ok_ko.gotoAndStop(1);
		game.lap_score.lap_text.textColor = 0x40ff40;
		if (cards_drawn>0) {
			if (!higher) {
				lap = 13-(sequence[cards_drawn-1]%13);
			}
			else {
				lap = sequence[cards_drawn-1]%13+1;
			}
		}
	}
	else {
		lap = -5;
		game.lap_score.lap_text.textColor = 0x900000;
	}
	game.lap_score.lap_text.text = lap;
	if (cards_drawn>0) {
		game.lap_score._alpha = 100;
	}
	points += lap;
	game["small_pic_obj_"+sequence[cards_drawn]]._x = 0;
	game["small_pic_obj_"+sequence[cards_drawn]]._y = 10;
	game["small_pic_obj_"+sequence[cards_drawn]]._visible = true;
	game["small_pic_obj_"+sequence[cards_drawn]].action = "come";
	game["small_pic_obj_"+sequence[cards_drawn-1]].action = "move";
	cards_drawn++;
	game.score.textscore.text = "Cards left: "+(52-cards_drawn)+" - Score: "+points;
}
function endgame() {
	game.removeMovieClip();
	_root.attachMovie("game_over","game_over",_root.getNextHighestDepth());
	game_over.gameovertext.filters = new Array(text_glow);
	game_over.fame.filters = new Array(text_glow);
	_root.game_over.gameovertext.text = "Your score: "+points;
	_root.kongregateScores.submit(points);
	game_over.fame.text = "top five players\n";
	var scoresCallback:Function = function (result:Object) {
		for (var i:Number = 0; i

Line 1: This stop is necessary bacause the game actually is on the second frame. I had to reserve the first frame to MochiAds and MochiBot just in case some day I would decide to monetize the game.

Line 2: connecting to the Kongregate server

Lines 3-7: importing various Flash prebuilt libraries I will use into the game

Lines 8-9: Defining the filter that I will use for the cards and for the texts. I am using a shadow for the cards, and a glow for the texts. For more information about Flash filters, refer to Create a flash draw game like Line Rider or others - part 1

Line 10: Calling the show_splash function. This function will show the game splash screen

Line 11: Beginning of the show_splash function

Line 12: Attaching the splash movieclip. It's this one

GuessNext

and has three transparent buttons in it: one on the "how to play", one on the "play" and one on the url of my blog

Lines 13-15: Managing the click on the button over the url of my blog, and opening the blog on a new page with getURL

LInes 16-19: Managing the click on the play button, calling the play_the_game function that contains the game itself, then removing the splash movieclip

Lines 20-23: Managing the "how to play" button, calling the show_info function that contains the script for the game instructions, the removing the splash movieclip. This concept of managing game status is similar to the one I explained in the post Designing the structure of a Flash game

Line 25: Beginning of the show_info function

Line 26: Attaching the info movieclip. It's this one:

GuessNext

and like the splash one has transparent buttons on the "play" and "back" texts

Lines 27-30: Managing the play button like in lines 16-19

Lines 31-34: Managing the back button calling again the show_splash function and removing the info movieclip

Line 36: Beginning of the play_game function, the core of the game

Line 37: Loading the card deck with BitmapData. More information about BitmapData in the post Shuffle an image with BitmapData

Lines 38-42: Attaching and creating all movieclips used in the game: the background (table), a movieclip where to publish all game elements (game), the buttons to bet on higher or lower cards (higher and lower) and the one to contain the cards (big_pic_obj)

Line 43: Attaching the bitmap as explained in the post Shuffle an image with BitmapData

Line 44: Hiding the movieclip with all cards

Line 45: Declaring the array that will store the sequence of cards that will be drawn during the game

Lines 46-53: Defining the prototype to shuffle the cards as explained in the post Shuffle an image with BitmapData

Line 54: Beginning of the loop that will cycle through all 52 cards

Line 55: Creating the empty movieclip that will host the card

Line 56: Assigning x to the x-th element in the sequence array. I need an ordered sequence (of cards) before I shuffle the deck

Line 57-59: Copying the pixels of each card into the appropriate movieclip as explained in the post Shuffle an image with BitmapData

Line 60: Making the card invisible

Line 61: Adding the shadow filter to the card

Line 62: Beginning of the actions to be executed for each card at every frame

Line 63: Switching among some defined actions the card may execute: come means the card is coming from the left side of the game to the centre of the screen, move means the card is moving from the centre to the right, and dissolve is when the card disappears from the game

Line 64: Beginning of the come case

Line 65: Moving the card to the right by 40 picels

Lines 66-68: If the card x position is greater than 210 (passed the orizontal center of the screen), then set its x position to 210 (place on the horizontal center the screen), set the card action to stay (that does not exist in the switch cases, it's something like "do nothing")

Lines 69-71: If the number of cards drawn is greater than 1 (if it's not the first card, the one you start the game with) then make the ok_ko movieclip visible. The ok_ko movieclip is the movieclip with the green "ok" symbol and the red "wrong" one that will appear when you draw a card. The "ok" is on the first frame while the "wrong" on the second

Line 74: Beginning of the move case

Line 75: Move the card to the right by 20 pixels

Lines 76-79: If the card x position is greater than 310, set the x position to 310 and set the card action to dissolve (it's time to make the card disappear)

Line 81: Beginning of the dissolve case

Line 82: Decrease the alpha of the card by 4 units

Line 83: Decrease the alpha of the lap_score movieclip by 4 units. The lap_score movieclip is the score that will appear on the top left side of the game when you draw a card

Line 84: If the card alpha is less than zero (invisible)...

Line 85: Set the can_draw variable to true. The can_draw variable states if the player can draw the next card or not. I made this variable because I want the player to wait until the previous card disappears. It has only a design purpose, I don't want the player to click randomly across the screen or click twice for an error

Line 86: Set the ok_ko movieclip to invisible

Lines 87-89: If the number of cards drawn is 52 (if the entire deck has been drawn), then call the endgame function

Line 90: Removing the card movieclip

Lines 96-98: Attaching the remaining movieclips being used in the game: ok_ko (the two symbols of right/wrong choice), score (the text with the current score and the cards left) and lap_score (the text with the partial score). This way:

GuessNext

Lines 99-100: Applying the glow filter to score and lap_score texts

Line 101: Shuffling the deck (sequence array)

Line 102: Set the number of cards drawn to zero

Line 103: Setting the points to zero

Line 104: Defining that the player at this time can draw the next card

Line 105: Calling the draw_card function. This function manages the next card to be drawn

Line 106: Beginning of the actions to be executed when the higher button has been released (the button with an up arrow)

Lines 107-111: If the player can draw, then set the can_draw variable to false (he must wait before drawing another card), set the higher variable to true (the variable that holds the choice of the player) and call the draw_card function

Lines 113-120: Same thing with the lower button, with the only difference in line 116 where higher variable is set to false

Line 121: Beginning of the draw_card function

Line 122: Move the ok_ko movieclip to frame 2

Line 123: Setting the lap score (the score for the current hand) to zero

Line 124: Checking if the player did the right choice. It happens when the player pressed higher and the current card is higher (or equal) than the previous one, or if the player pressed lower and the current card is lower (or equal) than the previous one. The %13 in the code is necessary because every suit (or seed) has 13 cards, so if an ace is the xth card, I know next ace will be the (x+13)th one. As you can see, if two cards are equals, the bet is always won, no matter the seeds of the cards.

Line 125: Moving the ok_ko movieclip to frame 1 (the "ok" symbol)

Line 126: Setting the text color of the lap score to a light green

Line 127: Determining if it's not the first card drawn (the one you see when you start the game)

Lines 128-133: Determining the partial score. The game encourages bets again statistics so if you have a ten, you know you have four cards higher (10, J, Q, K) and nine lower (from 1 to 10). So the game will give nine points if you bet (and win) on higher, and four if your bet (and win) to lower

Line 136: Beginning of the code to be executed if you did not bet and win

Line 137: Setting the lap score to -5. If you don't win, you always lose 5 points

Line 138: Setting the text color of the lap score to a dark red

Line 140: Writing the score of the last bet in the lap score text

Lines 141-143: Showing the lap score if the card drawn is not the first one (the one you see when you start the game)

Line 144: Adding the lap score to the total score

Lines 145-149: Assigning properties and actions to the cards involved in the last bet: the last one is placed to (0, 10), made visible and with the come action while the last one is set to move action

Line 150: Increasing the number of cards drawn

Line 151: Updating the score text with the total score and the number of cards left

Line 153: Beginning of the endgame function to be executed when the game ends

Line 154: Removing the game movieclip (with all cards, buttons, scores, and so on)

Line 155: Attaching the game_over movieclip. It's a movieclip showing your score and the top 5 players

Lines 156-157: Applying the glow array to the gameovertext (the text with your final score) and fame (the text with the top five scores) texts

Line 158: Displaying your final score

Line 159: Submitting the score to Kongregate. You are submitting only the score, without your name, because highscores work only if you are a registered user. In that case, the name is the nickname you use in Kongregate.

Lines 160-167: Code to retrieve the top five players. It's the standard code you may find on this page, I just changed line 164 to display the scores in my fame text and remove the trace lines. Notice that I am writing all scores and not just the top five, but the fame text will show only the top five.

Lines 168-172: Managing the play button you can find in the game over screen: it's the same concept as seen in lines 16-19

And that's it!! Hope this will inspire you in a card game creation.

Download the source code and all the Photoshop files and give me feedback!

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.