Talking about Perfectionism game, Flash and Game development.
4th step of the quickest game creation tutorial… in the last step we added elements to the game field… now we have to introduce real clicks
Real clicks
What is a real click? In Perfectionism game you can have only two buttons clicked at once: since it’s basically a “swap some elements” game, you can only click the “from” button and the “to” button.
Moreover, if you click a button on the horizontal row and then roll over a button on the vertical row, the button you clicked must become unclicked, and the same must happen when you click a button on the vertical row and then roll over a button on the horizontal one.
_root.attachMovie("grid","grid",1,{_x:90, _y:90});
_root.createEmptyMovieClip("rays",2);
swapping = false;
horizontal_hover = new Array(0, 0, 0, 0, 0, 0, 0, 0);
vertical_hover = new Array(0, 0, 0, 0, 0, 0, 0, 0);
horizontal_click = new Array(0, 0, 0, 0, 0, 0, 0, 0);
vertical_click = new Array(0, 0, 0, 0, 0, 0, 0, 0);
level = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
for (x=0; x<64; x++) {
if (level[x] == 1) {
grid.attachMovie("cell","cell_"+x,grid.getNextHighestDepth(),{_x:(x%8)*40, _y:Math.floor(x/8)*40});
}
if (level[x] == 2) {
grid.attachMovie("atom","atom"+x,grid.getNextHighestDepth(),{_x:(x%8)*40, _y:Math.floor(x/8)*40});
}
}
for (x=1; x<=8; x++) {
hs = grid.attachMovie("hswapper", "hswapper_"+x, grid.getNextHighestDepth(), {_x:-20, _y:40*x-20});
hs.pos = x;
hs.onEnterFrame = function() {
if (!swapping) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
this.gotoAndStop(2);
horizontal_hover[this.pos-1] = 1;
for (x=0; x<8; x++) {
vertical_click[x] = 0;
}
}
else {
this.gotoAndStop(1);
horizontal_hover[this.pos-1] = 0;
}
if (horizontal_click[this.pos-1] == 1) {
(this.gotoAndStop(3));
}
}
};
vs = grid.attachMovie("vswapper", "vswapper_"+x, grid.getNextHighestDepth(), {_x:40*x-20, _y:-20});
vs.pos = x;
vs.onEnterFrame = function() {
if (!swapping) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
this.gotoAndStop(2);
vertical_hover[this.pos-1] = 1;
for (x=0; x<8; x++) {
horizontal_click[x] = 0;
}
}
else {
this.gotoAndStop(1);
vertical_hover[this.pos-1] = 0;
}
if (vertical_click[this.pos-1] == 1) {
(this.gotoAndStop(3));
}
}
};
}
rays.onEnterFrame = function() {
if (!swapping) {
this.clear();
clicks = 0;
this.lineStyle(2,0x00ff00);
for (x=0; x<8; x++) {
if ((horizontal_hover[x] == 1) or (horizontal_click[x] == 1)) {
this.moveTo(90,x*40+110);
this.lineTo(410,x*40+110);
if (horizontal_click[x] == 1) {
clicks++;
}
}
if ((vertical_hover[x] == 1) or (vertical_click[x] == 1)) {
this.moveTo(x*40+110,90);
this.lineTo(x*40+110,410);
if (vertical_click[x] == 1) {
clicks++;
}
}
}
if (clicks == 2) {
swapping = true;
}
}
};
_root.onMouseDown = function() {
for (x=0; x<8; x++) {
if (horizontal_hover[x] == 1) {
horizontal_click[x] = 1-horizontal_click[x];
}
if (vertical_hover[x] == 1) {
vertical_click[x] = 1-vertical_click[x];
}
}
};
Line 3: Creating a boolean variable called swapping
that will be true
if we are ready to swap elements (two buttons on the same row or column have been clicked) or false
otherwise
Line 21: Now all operations on the horizontal buttons are performed only if we aren't swapping elements
Lines 25-27: If we are rolling over an horizontal button, then set all vertical buttons to unclicked
Line 41: Now all operations on the vertical buttons are performed only if we aren't swapping elements
Lines 45-47: If we are rolling over an vertical button, then set all horizontal buttons to unclicked
Line 60: Now all operations on rays are performed only if we aren't swapping elements
Line 62: Setting a variable called clicks
, that will store the number of buttons clicked, to zero
Lines 68-70: If the x-th
element of the horizontal_click
array is set to 1
(the button is clicked), then increment clicks
value
Lines 75-77: Same thing with the vertical_click
array
Line 80: If we have two buttons clicked (and we know they will be two horizontal buttons or two vertical buttons), then set swapping
to true. We are now ready to swap elements
And here it is:
Now if you click an horizontal button and then roll over a vertical one, you will lose the clicked status on the horizontal button, and the same thing will happen if you click on the vertical one and then roll over an horizontal button
If you click two horizontal buttons, you're ready to swap elements! The game freezes at this point, because there is no swapping code, but it's exactly what we are going to make
Swapping elements
This is the hardest part of the game... once you click two horizontal or vertical buttons, we have to swap elements. Remember that only the squares can be moved, while the rings have to remain in the same position even if I try to swap them
_root.attachMovie("grid", "grid", 1, {_x:90, _y:90});
_root.createEmptyMovieClip("rays", 2);
swapping = false;
from = -1;
to = -1;
horizontal_swap = false;
vertical_swap = false;
horizontal_hover = new Array(0, 0, 0, 0, 0, 0, 0, 0);
vertical_hover = new Array(0, 0, 0, 0, 0, 0, 0, 0);
horizontal_click = new Array(0, 0, 0, 0, 0, 0, 0, 0);
vertical_click = new Array(0, 0, 0, 0, 0, 0, 0, 0);
level = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
for (x=0; x<64; x++) {
if (level[x] == 1) {
grid.attachMovie("cell", "cell_"+x, grid.getNextHighestDepth(), {_x:(x%8)*40, _y:Math.floor(x/8)*40});
}
if (level[x] == 2) {
at = grid.attachMovie("atom", "atom_"+x, grid.getNextHighestDepth(), {_x:(x%8)*40, _y:Math.floor(x/8)*40});
at.pos = x;
at.moving = 0;
at.onEnterFrame = function() {
if (this.moving == 0) {
if (swapping) {
if (horizontal_swap) {
if ((this.pos>=from*8) and (this.pos<=from*8+7)) {
this.moving = (to-from)*40;
}
if ((this.pos>=to*8) and (this.pos<=to*8+7)) {
this.moving = (from-to)*40;
}
}
if (vertical_swap) {
for (x=0; x<8; x++) {
if (this.pos == x*8+from) {
this.moving = (to-from)*40;
}
}
for (x=0; x<8; x++) {
if (this.pos == x*8+to) {
this.moving = (from-to)*40;
}
}
}
}
} else {
if (this.moving>0) {
if (horizontal_swap) {
this._y += 10;
}
if (vertical_swap) {
this._x += 10;
}
this.moving -= 10;
}
if (this.moving<0) {
if (horizontal_swap) {
this._y -= 10;
}
if (vertical_swap) {
this._x -= 10;
}
this.moving += 10;
}
if (this.moving == 0) {
this.pos = Math.round(this._x/40)+Math.round(this._y/40)*8;
for (x=0; x<8; x++) {
horizontal_click[x] = 0;
vertical_click[x] = 0;
swapping = false;
}
}
}
};
}
}
for (x=1; x<=8; x++) {
hs = grid.attachMovie("hswapper", "hswapper_"+x, grid.getNextHighestDepth(), {_x:-20, _y:40*x-20});
hs.pos = x;
hs.onEnterFrame = function() {
if (!swapping) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
this.gotoAndStop(2);
horizontal_hover[this.pos-1] = 1;
for (x=0; x<8; x++) {
vertical_click[x] = 0;
}
} else {
this.gotoAndStop(1);
horizontal_hover[this.pos-1] = 0;
}
if (horizontal_click[this.pos-1] == 1) {
(this.gotoAndStop(3));
}
}
};
vs = grid.attachMovie("vswapper", "vswapper_"+x, grid.getNextHighestDepth(), {_x:40*x-20, _y:-20});
vs.pos = x;
vs.onEnterFrame = function() {
if (!swapping) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
this.gotoAndStop(2);
vertical_hover[this.pos-1] = 1;
for (x=0; x<8; x++) {
horizontal_click[x] = 0;
}
} else {
this.gotoAndStop(1);
vertical_hover[this.pos-1] = 0;
}
if (vertical_click[this.pos-1] == 1) {
(this.gotoAndStop(3));
}
}
};
}
rays.onEnterFrame = function() {
if (!swapping) {
horizontal_swap = false;
vertical_swap = false;
this.clear();
clicks = 0;
this.lineStyle(2, 0x00ff00);
for (x=0; x<8; x++) {
if ((horizontal_hover[x] == 1) or (horizontal_click[x] == 1)) {
this.moveTo(90, x*40+110);
this.lineTo(410, x*40+110);
if (horizontal_click[x] == 1) {
clicks++;
horizontal_swap = true;
}
}
if ((vertical_hover[x] == 1) or (vertical_click[x] == 1)) {
this.moveTo(x*40+110, 90);
this.lineTo(x*40+110, 410);
if (vertical_click[x] == 1) {
clicks++;
vertical_swap = true;
}
}
}
if (clicks == 2) {
from = -1;
to = -1;
swapping = true;
if (horizontal_swap) {
for (x=0; x<8; x++) {
if (horizontal_click[x] == 1) {
if (from == -1) {
from = x;
} else {
to = x;
}
}
}
}
if (vertical_swap) {
for (x=0; x<8; x++) {
if (vertical_click[x] == 1) {
if (from == -1) {
from = x;
} else {
to = x;
}
}
}
}
}
}
};
_root.onMouseDown = function() {
for (x=0; x<8; x++) {
if (horizontal_hover[x] == 1) {
horizontal_click[x] = 1-horizontal_click[x];
}
if (vertical_hover[x] == 1) {
vertical_click[x] = 1-vertical_click[x];
}
}
};
Line 4: Declaring a from
variable that will store the row (or column) to be swapped. -1 means no columns (or rows) to swap
Line 5: Same thing with the destination row (or column)
Line 6: Boolean flag that tells me if I should make an horizontal swap
Line 7: Boolean flag that tells me if I should make a vertical swap
Line 20: When I create the square movieclip, I assign it a moving
variable that will tell me how many pixel the square has to move.
Line 22: If the square is not moving...
Line 23: If we must swap rows (or columns)...
Line 24: If we must perform an horizontal swap (we'll see later in this code how to determine if it's an horizontal or verticals swap)...
Line 25: If the square is in the starting row (we'll see later in this code how to determine which row is the starting one)...
Line 26: Calculating the number of pixels the square has to move. This number is determined multiplying 40 (the side of one cell of the game field) by the difference between the ending and the starting rows
Lines 28-30: Same thing as lines 25-27, but I am checking if the square is on the destination row
Lines 32-43: Same thing as lines 24-31, just applied to vertical swapping
In a brief summary, if the square is not already moving and I know I have to swap two rows (or columns), first I check if I am going to swap rows or columns, then I check if the square lies on one of the rows (or columns) to be swapped and in this case I determine how many pixels the square has to move up/down/left/right according to its position in the swapping row/column
Line 45: If the square is moving...
Line 46: If the amount of pixels the square has to move is greater than zero (the square moves from left to right or from up to down)
Line 47: If it's an horizontal swap...
Line 48: Move the square down by 10 pixels (an arbitrary speed I set)
Lines 50-52: Same thing for the vertical swap, just moving the square to the right by 10 pixels
Line 53: Since the square has moved by 10 pixels (no matter in which direction), I subtract 10 to moving
variable
Lines 55-63: Same thing as lines 46-64, just managing movements when moving
is less than zero
In a brief summary, if the square is moving, I determine the direction I will move the square, and move it by 10 pixels per frame, until I moved it for the same amount of pixels calculated at lines 26 or 29 or 35 or 40
Line 64: If moving
is equal to zero
(I just moved the square for the last 10 pixels step)
Line 65: Update pos
value according to the physical position of the square in the stage
Lines 66-70: Now that columns/rows have been swapped, it's time to clear the click status of all buttons. I don't really know why I included line 69 inside the cycle... oh well...
Line 129: Setting horizontal_swap to true if an horizontal button has been clicked
Line 137: Same thing for the vertical_swap variable
Line 142: Now we have to manage the game when the player clicks on two buttons... first resetting from
to -1
...
Line 143: Then doing the same thing with to
Line 144: Set swapping to true, now we only need to know the couple of rows/columns to swap
Line 145: If it's an horizontal swap...
Line 146: Cycle scanning all horizontal_click
array elements
Line 147: If the x-th
element is equal to 1
(the button has been clicked)...
Lines 148-152: I have to assign the from
and the to
variables. I want the from
variable to store the upper (or leftmost) position on the field where the player clicked the button and the the to
variable to store the lower (or rightmost) one. So, if from
is at -1
, it means this is the first clicked button I found, so I assign x
value to from
. If from
is not -1
, it means I already found a clicked button so this must be the second button, so I store x
value to to
variable
Lines 156-166: Same thing as lines 145-155, but for vertical swapping
And that's it!! Now you can swap rows and columns, but the game still crashes if you try to swap empty rows/columns
Don't be afraid of the complexity of this code because this was the hardest part.
You'll see in next tutorial how things will get easier and easier now that the game is ready to be published
Download source codes and prepare yourself for next step
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.