Talking about Bejeweled game, Actionscript 3, Flash and Game development.
I wanted to have a look at a Bejeweled game featuring the 90 degrees array rotation I explained yesterday.
So I took the script made by Brook Jordan in the complete Bejeweled game in less than 2KB – legible version and added some quick and dirty code to make it work:
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.text.TextField;
public class Main extends Sprite {
private var gems_array:Array=new Array();
private var aGem:Sprite;
private var selectorBox:Sprite=new Sprite();
private var selectorRow:int=-10;
private var selectorColumn:int=-10;
private var red:uint = 0xFF0000;
private var green:uint = 0xFF00;
private var blue:uint = 0xFF;
private var yellow:uint = 0xFFFF00;
private var cyan:uint = 0xFFFF;
private var magenta:uint = 0xFF00FF;
private var white:uint = 0xFFFFFF;
private var colours_array:Array=new Array(red,green,blue,yellow,cyan,magenta,white);
private var clickPossible:Boolean=false;
private var score_txt:TextField=new TextField();
private var hint_txt:TextField=new TextField();
private var score:uint=0;
private var inaRow:uint=0;
private var match:Boolean = true;
private var rotate:Boolean=false;
private var gemCanvas:Sprite=new Sprite();
public function Main() {
// Game initiation
// Create and style score text
addChild(score_txt);
score_txt.textColor=0xFFFFFF;
score_txt.x=500;
// Create and style hint text
addChild(hint_txt);
hint_txt.textColor=0xFFFFFF;
hint_txt.x=550;
// Create Gems in rows and columns
addChild(gemCanvas);
gemCanvas.x=240;
gemCanvas.y=240;
for (var i:uint=0; i<8; i++) {
gems_array[i]=new Array();
for (var j:uint=0; j<8; j++) {
do {
gems_array[i][j]=Math.floor(Math.random()*7);
}
while (rowLineLength(i,j)>2 || columnLineLength(i,j)>2);
aGem=new Sprite();
aGem.graphics.beginFill(colours_array[gems_array[i][j]]);
aGem.graphics.drawCircle(30,30,29);
aGem.graphics.endFill();
aGem.name=i+"_"+j;
aGem.x=j*60-240;
aGem.y=i*60-240;
gemCanvas.addChild(aGem);
}
}
// Create and style selector box
addChild(selectorBox);
selectorBox.graphics.lineStyle(2,red,1);
selectorBox.graphics.drawRect(0,0,60,60);
selectorBox.visible=false;
// Listen for user input
stage.addEventListener(MouseEvent.CLICK,onClick);
addEventListener(Event.ENTER_FRAME,everyFrame);
}
// Every frame...
private function everyFrame(e:Event):void {
//Assume that gems are not falling
var gemsAreFalling:Boolean=false;
// Check each gem for space below it
for (var i:int=6; i>=0; i--) {
for (var j:uint=0; j<8; j++) {
// If a spot contains a gem, and has an empty space below...
if (gems_array[i][j] != -1 && gems_array[i+1][j]==-1) {
// Set gems falling
gemsAreFalling=true;
gems_array[i+1][j]=gems_array[i][j];
gems_array[i][j]=-1;
gemCanvas.getChildByName(i+"_"+j).y+=60;
gemCanvas.getChildByName(i+"_"+j).name=(i+1)+"_"+j;
break;
}
}
// If a gem is falling
if (gemsAreFalling) {
// don't allow any more to start falling
break;
}
}
// If no gems are falling
if (! gemsAreFalling) {
// Assume no new gems are needed
var needNewGem:Boolean=false;
// but check all spaces...
for (i=7; i>=0; i--) {
for (j=0; j<8; j++) {
// and if a spot is empty
if (gems_array[i][j]==-1) {
// now we know we need a new gem
needNewGem=true;
// pick a random color for the gem
gems_array[0][j]=Math.floor(Math.random()*7);
// create the gem
aGem=new Sprite();
aGem.graphics.beginFill(colours_array[gems_array[0][j]]);
aGem.graphics.drawCircle(30,30,29);
aGem.graphics.endFill();
// ID it
aGem.name="0_"+j;
// position it
aGem.x=j*60-240;
aGem.y=-240;
// show it
gemCanvas.addChild(aGem);
// stop creating new gems
break;
}
}
// if a new gem was created, stop checking
if (needNewGem) {
break;
}
}
// If no new gems were needed...
if (! needNewGem) {
// assume no more/new lines are on the board
var moreLinesAvailable:Boolean=false;
// check all gems
for (i=7; i>=0; i--) {
for (j=0; j<8; j++) {
// if a line is found
if (rowLineLength(i,j)>2 || columnLineLength(i,j)>2) {
// then we know more lines are available
moreLinesAvailable=true;
// creat a new array, set the gem type of the line, and where it is
var lineGems:Array=[i+"_"+j];
var gemType:uint=gems_array[i][j];
var linePosition:int;
// check t's a horizontal line...
if (rowLineLength(i,j)>2) {
// if so, find our how long it is and put all the line's gems into the array
linePosition=j;
while (sameGemIsHere(gemType,i,linePosition-1)) {
linePosition--;
lineGems.push(i+"_"+linePosition);
}
linePosition=j;
while (sameGemIsHere(gemType,i,linePosition+1)) {
linePosition++;
lineGems.push(i+"_"+linePosition);
}
}
// check t's a vertical line...
if (columnLineLength(i,j)>2) {
// if so, find our how long it is and put all the line's gems into the array
linePosition=i;
while (sameGemIsHere(gemType,linePosition-1,j)) {
linePosition--;
lineGems.push(linePosition+"_"+j);
}
linePosition=i;
while (sameGemIsHere(gemType,linePosition+1,j)) {
linePosition++;
lineGems.push(linePosition+"_"+j);
}
}
// for all gems in the line...
for (i=0; i0){
gemCanvas.removeChildAt(0);
}
for (i=0; i<8; i++) {
for (j=0; j<8; j++) {
aGem=new Sprite();
aGem.graphics.beginFill(colours_array[gems_array[i][j]]);
aGem.graphics.drawCircle(30,30,29);
aGem.graphics.endFill();
aGem.name=i+"_"+j;
aGem.x=j*60-240;
aGem.y=i*60-240;
gemCanvas.addChild(aGem);
}
}
}
}
else{
// allow new moves to be made
clickPossible=true;
// remove score multiplier
inaRow=0;
}
}
}
}
// display new score
score_txt.text=score.toString();
}
// When the user clicks
private function onClick(e:MouseEvent):void {
// If a click is allowed
if (clickPossible) {
// If the click is within the game area...
if (mouseX<480&&mouseX>0&&mouseY<480&&mouseY>0) {
// Find which row and column were clicked
var clickedRow:uint=Math.floor(mouseY/60);
var clickedColumn:uint=Math.floor(mouseX/60);
// Check if the clicked gem is adjacent to the selector
// If not...
if (!(((clickedRow==selectorRow+1 || clickedRow==selectorRow-1)&&clickedColumn==selectorColumn)||((clickedColumn==selectorColumn+1 || clickedColumn==selectorColumn-1) && clickedRow==selectorRow))) {
// Find row and colum the selector should move to
selectorRow=clickedRow;
selectorColumn=clickedColumn;
// Move it to the chosen position
selectorBox.x=60*selectorColumn;
selectorBox.y=60*selectorRow;
// If hidden, show it.
selectorBox.visible=true;
}
// If it is not next to it...
else {
// Swap the gems;
swapGems(selectorRow,selectorColumn,clickedRow,clickedColumn);
// If they make a line...
if (rowLineLength(selectorRow,selectorColumn)>2 || columnLineLength(selectorRow,selectorColumn)>2||rowLineLength(clickedRow,clickedColumn)>2 || columnLineLength(clickedRow,clickedColumn)>2) {
// remove the hint text
hint_txt.text="";
// dis-allow a new move until cascade has ended (removes glitches)
clickPossible=false;
// move and rename the gems
gemCanvas.getChildByName(selectorRow+"_"+selectorColumn).x=clickedColumn*60-240;
gemCanvas.getChildByName(selectorRow+"_"+selectorColumn).y=clickedRow*60-240;
gemCanvas.getChildByName(selectorRow+"_"+selectorColumn).name="t";
gemCanvas.getChildByName(clickedRow+"_"+clickedColumn).x=selectorColumn*60-240;
gemCanvas.getChildByName(clickedRow+"_"+clickedColumn).y=selectorRow*60-240;
gemCanvas.getChildByName(clickedRow+"_"+clickedColumn).name=selectorRow+"_"+selectorColumn;
gemCanvas.getChildByName("t").name=clickedRow+"_"+clickedColumn;
match = true;
rotate = true;
}
// If not...
else {
// Switch them back
swapGems(selectorRow,selectorColumn,clickedRow,clickedColumn);
match = false;
}
if (match) {
// Move the selector position to default
selectorRow=-10;
selectorColumn=-10;
// and hide it
selectorBox.visible=false;
}
else {
// Set the selector position
selectorRow=clickedRow;
selectorColumn=clickedColumn;
// Move the box into position
selectorBox.x=60*selectorColumn;
selectorBox.y=60*selectorRow;
match = false;
// If hidden, show it.
selectorBox.visible=true;
}
}
}
// If the click is outside the game area
else {
// For gems in all rows...
for (var i:uint=0; i<8; i++) {
// and columns...
for (var j:uint=0; j<8; j++) {
// if they're not too close to the side...
if (i<7) {
// swap them horizontally
swapGems(i,j,i+1,j);
// check if they form a line
if ((rowLineLength(i,j)>2||columnLineLength(i,j)>2||rowLineLength(i+1,j)>2||columnLineLength(i+1,j)>2)) {
// if so, name the move made
selectorBox.x = j*60;
selectorBox.y = i*60;
selectorBox.visible = true;
hint_txt.text = (i+1).toString()+","+(j+1).toString()+"->"+(i+2).toString()+","+(j+1).toString();
}
// swap the gems back
swapGems(i,j,i+1,j);
}
// then if they're not to close to the bottom...
if (j<7) {
// swap it vertically
swapGems(i,j,i,j+1);
// check if it forms a line
if ((rowLineLength(i,j)>2||columnLineLength(i,j)>2||rowLineLength(i,j+1)>2||columnLineLength(i,j+1)>2) ) {
// if so, name it
selectorBox.x = j*60;
selectorBox.y = i*60;
selectorBox.visible = true;
hint_txt.text = (i+1).toString()+","+(j+1).toString()+"->"+(i+1).toString()+","+(j+2).toString();
}
// swap the gems back
swapGems(i,j,i,j+1);
}
}
}
}
}
}
//Swap given gems
private function swapGems(fromRow:uint,fromColumn:uint,toRow:uint,toColumn:uint):void {
//Save the original position
var originalPosition:uint=gems_array[fromRow][fromColumn];
//Move original gem to new position
gems_array[fromRow][fromColumn]=gems_array[toRow][toColumn];
//move second gem to saved, original gem's position
gems_array[toRow][toColumn]=originalPosition;
}
//Find out if there us a horizontal line
private function rowLineLength(row:uint,column:uint):uint {
var gemType:uint=gems_array[row][column];
var lineLength:uint=1;
var checkColumn:int=column;
//check how far left it extends
while (sameGemIsHere(gemType,row,checkColumn-1)) {
checkColumn--;
lineLength++;
}
checkColumn=column;
//check how far right it extends
while (sameGemIsHere(gemType,row,checkColumn+1)) {
checkColumn++;
lineLength++;
}
// return total line length
return (lineLength);
}
//Find out if there us a vertical line
private function columnLineLength(row:uint,column:uint):uint {
var gemType:uint=gems_array[row][column];
var lineLength:uint=1;
var checkRow:int=row;
//check how low it extends
while (sameGemIsHere(gemType,checkRow-1,column)) {
checkRow--;
lineLength++;
}
//check how high it extends
checkRow=row;
while (sameGemIsHere(gemType,checkRow+1,column)) {
checkRow++;
lineLength++;
}
// return total line length
return (lineLength);
}
private function sameGemIsHere(gemType:uint,row:int,column:int):Boolean {
//Check there are gems in the chosen row
if (gems_array[row]==null) {
return false;
}
//If there are, check if there is a gem in the chosen slot
if (gems_array[row][column]==null) {
return false;
}
//If there is, check if it's the same as the chosen gem type
return gemType==gems_array[row][column];
}
private function rotateClockwise(a:Array):void {
var n:int=a.length;
for (var i:int=0; i
My code is written mainly at lines 197-218
gemCanvas.rotation+=5;
if(gemCanvas.rotation%90==0){
rotate=false;
gemCanvas.rotation=0;
rotateClockwise(gems_array);
while(gemCanvas.numChildren>0){
gemCanvas.removeChildAt(0);
}
for (i=0; i<8; i++) {
for (j=0; j<8; j++) {
aGem=new Sprite();
aGem.graphics.beginFill(colours_array[gems_array[i][j]]);
aGem.graphics.drawCircle(30,30,29);
aGem.graphics.endFill();
aGem.name=i+"_"+j;
aGem.x=j*60-240;
aGem.y=i*60-240;
gemCanvas.addChild(aGem);
}
}
}
To save coding time, I only rotate the two-dimensional array, then remove all jewels and recreate them in their new position.
This is the result:
I wonder if it could be interesting to create a real game out of it. Any idea?
No need to download anything, replace the source code of the original prototype with the one on this page.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.