Here are some button images you can download. We have buttons for
fans, and buttons for developers that have been featured on the site.
|
|
|  |
Now it’s time to make bricks disappear if they group in a 2×2 square.
Read part 1 and 2 if you did not already.
It’s not difficult to check if bricks form a 2×2 square… and it’s not difficult to remove them from the stage.
The tricky part is making bricks fill the empty spaces left by disappeared bricks and managing combos (fallen bricks can make another 2×2 square, generating more falling bricks, and so on).
I preferred not to have an onEnterFrame on every brick to check if it’s over an empty space and eventually move it, so I created another array called bricks_in_field saving the depth of the brick in that position, so when I remove some bricks I just have to put in the moveable_bricks the depth found in the bricks_in_field array and the “engine” does the rest.
Here it is the actionscript:
ACTIONSCRIPT:
-
// declaring some setup variables
-
// number of horizontal cells
-
grid_width = 16;
-
// number of vertical cells
-
grid_height = 10;
-
// size of the cell
-
tile_size = 30;
-
// offset in pixels fron the left side of the stage
-
x_offset = 10;
-
// offset in pixels from the top side of the stage
-
y_offset = 10;
-
// number of different colors that can be displayed in a brick
-
different_colors = 3;
-
// boolean values saying if I should wait for the left (or right, up…) key to be released
-
// this is used to make the player move bricks tapping arrow keys instead of just pressing them
-
wait_left = false;
-
wait_right = false;
-
wait_up = false;
-
wait_down = false;
-
// flag indicating if blocks are falling
-
falling = false;
-
// array containing the game field data
-
field = new Array();
-
// array containing bricks position
-
bricks_in_field = new Array();
-
// array containing the bricks I can move
-
moveable_bricks = new Array();
-
// initializing and drawing the play field and the bricks position fields
-
for (x=0; x<grid_width; x++) {
-
field[x] = new Array();
-
bricks_in_field[x] = new Array();
-
for (y=0; y<grid_height; y++) {
-
field[x][y] = 0;
-
bricks_in_field[x][y] = 0;
-
// look how I det ermine cells position according to tile size and offsets
-
cell = _root.attachMovie(“brick”, “brick_”+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:x*tile_size+x_offset, _y:(y+2)*tile_size+y_offset});
-
// first frame = empty cell
-
cell.gotoAndStop(1);
-
}
-
}
-
// calling the function that will place four bricks on the stage
-
place_bricks();
-
// main function, to be executed at every frame
-
_root.onEnterFrame = function() {
-
// if blocks aren’t falling
-
if (!falling) {
-
// checking if a block is the upper left one of a four block square
-
for (x=0; x<grid_width; x++) {
-
for (y=0; y<grid_height; y++) {
-
if (field[x][y] != 0 and field[x][y] == field[x+1][y] and field[x][y] == field[x+1][y+1] and field[x][y] == field[x][y+1]) {
-
// physically removing the bricks
-
_root[“brick_”+bricks_in_field[x][y+1]].removeMovieClip();
-
_root[“brick_”+bricks_in_field[x][y+2]].removeMovieClip();
-
_root[“brick_”+bricks_in_field[x+1][y+1]].removeMovieClip();
-
_root[“brick_”+bricks_in_field[x+1][y+2]].removeMovieClip();
-
// updating field array
-
field[x][y] = 0;
-
field[x][y+1] = 0;
-
field[x+1][y+1] = 0;
-
field[x+1][y] = 0;
-
// checking upper bricks to make them fall
-
start_y = y-1;
-
while (field[x][start_y]>0) {
-
moveable_bricks.push(bricks_in_field[x][start_y+1]);
-
start_y–;
-
}
-
start_y = y-1;
-
while (field[x+1][start_y]>0) {
-
moveable_bricks.push(bricks_in_field[x+1][start_y+1]);
-
start_y–;
-
}
-
falling = true;
-
}
-
}
-
}
-
// place new bricks only if no bricks are falling
-
if (!falling and moveable_bricks.length == 0) {
-
place_bricks();
-
}
-
// this is how I detect if a key was tapped:
-
// when it’s pressed, I wait for it to be released (in this case: not pressed)
-
// thanks to the wait_<direction> variable
-
if (Key.isDown(Key.LEFT)) {
-
wait_left = true;
-
} else {
-
if (wait_left) {
-
// if the left key has been tapped, move the four bricks on the left
-
for (x=0; x<4; x++) {
-
// this "if" is used to determine if the bricks are still inside the game field
-
if ((_root[“brick_”+moveable_bricks[x]]._x-x_offset)/tile_size-_root[“brick_”+moveable_bricks[x]].pos%2>0) {
-
_root[“brick_”+moveable_bricks[x]]._x -= tile_size;
-
}
-
}
-
// reset variable, now I must wait again for a key to be pressed
-
wait_left = false;
-
}
-
}
-
// same routine for the right key
-
if (Key.isDown(Key.RIGHT)) {
-
wait_right = true;
-
} else {
-
if (wait_right) {
-
for (x=0; x<4; x++) {
-
if ((_root[“brick_”+moveable_bricks[x]]._x-x_offset)/tile_size-_root[“brick_”+moveable_bricks[x]].pos%2<14) {
-
_root[“brick_”+moveable_bricks[x]]._x += tile_size;
-
}
-
}
-
wait_right = false;
-
}
-
}
-
// when the DOWN arrow is pressed, I must rotate the bricks clockwise
-
// block 0: moves to the right and becomes block 1
-
// block 1: moves down and becomes block 3
-
// block 2: moves up and becomes block 0
-
// block 3: moves to the left and becomes block 2
-
if (Key.isDown(Key.DOWN)) {
-
wait_down = true;
-
} else {
-
if (wait_down) {
-
for (x=0; x<4; x++) {
-
switch (_root[“brick_”+moveable_bricks[x]].pos) {
-
case 0 :
-
_root[“brick_”+moveable_bricks[x]].pos = 1;
-
_root[“brick_”+moveable_bricks[x]]._x += tile_size;
-
break;
-
case 1 :
-
_root[“brick_”+moveable_bricks[x]].pos = 3;
-
_root[“brick_”+moveable_bricks[x]]._y += tile_size;
-
break;
-
case 2 :
-
_root[“brick_”+moveable_bricks[x]].pos = 0;
-
_root[“brick_”+moveable_bricks[x]]._y -= tile_size;
-
break;
-
case 3 :
-
_root[“brick_”+moveable_bricks[x]].pos = 2;
-
_root[“brick_”+moveable_bricks[x]]._x -= tile_size;
-
break;
-
}
-
}
-
wait_down = false;
-
}
-
}
-
// when the UP arrow is pressed, I must rotate the bricks counter-clockwise
-
// block 0: moves down the right and becomes block 2
-
// block 1: moves to the left and becomes block 0
-
// block 2: moves to the right and becomes block 3
-
// block 3: moves up and becomes block 1
-
if (Key.isDown(Key.UP)) {
-
wait_up = true;
-
} else {
-
if (wait_up) {
-
for (x=0; x<4; x++) {
-
switch (_root[“brick_”+moveable_bricks[x]].pos) {
-
case 0 :
-
_root[“brick_”+moveable_bricks[x]].pos = 2;
-
_root[“brick_”+moveable_bricks[x]]._y += tile_size;
-
break;
-
case 1 :
-
_root[“brick_”+moveable_bricks[x]].pos = 0;
-
_root[“brick_”+moveable_bricks[x]]._x -= tile_size;
-
break;
-
case 2 :
-
_root[“brick_”+moveable_bricks[x]].pos = 3;
-
_root[“brick_”+moveable_bricks[x]]._x += tile_size;
-
break;
-
case 3 :
-
_root[“brick_”+moveable_bricks[x]].pos = 1;
-
_root[“brick_”+moveable_bricks[x]]._y -= tile_size;
-
break;
-
}
-
}
-
wait_up = false;
-
}
-
}
-
// when SPACE key is pressed, I don’t wait for its release but I detect the key at once
-
if (Key.isDown(Key.SPACE)) {
-
// letìs made bricks fall…
-
falling = true;
-
}
-
} else {
-
//if the blocks are falling
-
// blocks_landed variable will count the number of bricks that already touched the ground
-
// or that cannot fall anymore because they are over other bricks
-
blocks_landed = 0;
-
for (x=0; x<moveable_bricks.length; x++) {
-
// calculating x and y position of the brick in the array
-
x_pos = (_root[“brick_”+moveable_bricks[x]]._x-x_offset)/tile_size;
-
y_pos = (_root[“brick_”+moveable_bricks[x]]._y-y_offset)/tile_size-1;
-
// determining if the block can fall. There are two conditions:
-
// 1: its position is less than zero. It means the block is outside the grid, in its starting position
-
// 2: its position is lower than the grid height and the tile under the block is empty
-
if ((y_pos<0) or ((y_pos<grid_height) and (field[x_pos][y_pos] == 0))) {
-
// updating field array
-
field[x_pos][y_pos] = _root[“brick_”+moveable_bricks[x]]._currentframe;
-
field[x_pos][y_pos-1] = 0;
-
// physically moving the brick
-
_root[“brick_”+moveable_bricks[x]]._y += tile_size;
-
} else {
-
// if the brick cannot move down, increase the number of blocks landed
-
blocks_landed++;
-
}
-
}
-
// if all four bricks landed successfully…
-
if (blocks_landed == moveable_bricks.length) {
-
for (x=0; x<moveable_bricks.length; x++) {
-
x_pos = (_root[“brick_”+moveable_bricks[x]]._x-x_offset)/tile_size;
-
y_pos = (_root[“brick_”+moveable_bricks[x]]._y-y_offset)/tile_size-1;
-
// saving in the brick array the name of the brick landed on (x_pos,y_pos)
-
bricks_in_field[x_pos][y_pos] = moveable_bricks[x];
-
}
-
// reset variable to false
-
falling = false;
-
// reset moveable_bricks array
-
moveable_bricks = new Array();
-
}
-
}
-
};
-
// function to place four bricks on the stage
-
function place_bricks() {
-
// placing the four bricks
-
for (x=0; x<4; x++) {
-
// again, look how I determine bricks position according to tile size and offsets
-
brk = _root.attachMovie(“brick”, “brick_”+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:(grid_width/2+(x%2))*tile_size+x_offset, _y:y_offset+tile_size*Math.floor(x/2)});
-
// setting a random color for the brick (frames 2 to different_colors+1)
-
brk.gotoAndStop(Math.floor(Math.random()*different_colors)+2);
-
// saving brick position
-
// 0: up left
-
// 1: up right
-
// 2: bottom left
-
// 3: bottom right
-
brk.pos = x;
-
// saving the depth of the brick into the moveable_bricks array
-
// if you look how did I assign brick names, you’ll see that I can determine a brick name
-
// starting from its depth. It’s simply "brick_"+<the_depth>
-
moveable_bricks[x] = brk.getDepth();
-
}
-
}
And this is the result:
Now wait for the next step to handle timing events.
Download the source.
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
Today WordPress.org team released version 2.6 with these notes:
I’m happy to announce that version 2.6 of WordPress.org is now available, almost a month ahead schedule. Version 2.6 “Tyner,” named for jazz pianist McCoy Tyner, contains a number of new features that make WordPress a more powerful CMS: you can now track changes to every post and page and easily post from wherever you are on the web, plus there are dozens of incremental improvements to the features introduced in version 2.5.
If you are the kind of blogger that waits for others to install latest releases before upgrading his own blog… well, I installed it and everything is working great.
You can check new features in this video:
I am finding really useful theme previews, because I am going to revamp the theme and keep new look secret until it’s finished.
Have no fear and install it.
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
|
|  |
In the 1st part I showed you how to make a deflection engine starting from an old tutorial, now it’s time to let the player draw walls.
The idea comes from Srdjan Susnic, a reader who runs the blog Ask For Game Task.
The main task Srdjan accomplished was to add a mouse control so a player can draw lines from which the ball will bounce.
After collision between the ball and a line drawn by mouse, that line must be removed
The code is clear and well commented, but it seems to suffer a bug if the player just clicks the mouse without drawing.
It’s just a minor issue I fixed in a moment, and if you already read the original post, I just added the control if the player drew a line when he releases the mouse button with player_drew variable.
Anyway, this is the actionscript:
ACTIONSCRIPT:
-
// create game object
-
game = {gravity:0, dragging:false, clip:_root.game_mc, stageW:500, stageH:400, maxV:20};
-
// create object
-
// point p0 is its starting point in the coordinates x/y
-
_root.attachMovie(“ball”, “ball”, 1);
-
game.myOb = {clip:ball, airf:1, b:1, f:1, r:20, lastTime:getTimer()};
-
game.myOb.p0 = {x:150, y:80};
-
// vectors x/y components
-
game.myOb.vx = 8;
-
game.myOb.vy = 12;
-
// create first vector
-
// point p0 is its starting point in the coordinates x/y
-
// point p1 is its end point in the coordinates x/y
-
game.v = new Array();
-
game.v[0] = {p0:{x:50, y:40}, p1:{x:450, y:40}, b:1, f:1};
-
game.v[1] = {p0:{x:50, y:40}, p1:{x:50, y:360}, b:1, f:1};
-
game.v[2] = {p0:{x:50, y:360}, p1:{x:450, y:360}, b:1, f:1};
-
game.v[3] = {p0:{x:100, y:80}, p1:{x:400, y:320}, b:1, f:1};
-
_root.createEmptyMovieClip(“lines”, 2);
-
lines.lineStyle(1, 0xff0000);
-
// draw and calculate all parameters for the wall vectors
-
for (x=0; x<game.v.length; x++) {
-
lines.moveTo(game.v[x].p0.x, game.v[x].p0.y);
-
lines.lineTo(game.v[x].p1.x, game.v[x].p1.y);
-
updateVector(game.v[x], true);
-
}
-
_root.onEnterFrame = function() {
-
_root.runMe();
-
};
-
// function to draw the points, lines and show text
-
function drawAll(v) {
-
// place ob mc
-
v.clip._x = v.p1.x;
-
v.clip._y = v.p1.y;
-
}
-
// main function
-
function runMe() {
-
// start to calculate movement
-
var ob = game.myOb;
-
// add air resistance
-
ob.vx *= ob.airf;
-
ob.vy *= ob.airf;
-
// dont let it go over max speed
-
if (ob.vx>game.maxV) {
-
ob.vx = game.maxV;
-
} else if (ob.vx<-game.maxV) {
-
ob.vx = -game.maxV;
-
}
-
if (ob.vy>game.maxV) {
-
ob.vy = game.maxV;
-
} else if (ob.vy<-game.maxV) {
-
ob.vy = -game.maxV;
-
}
-
// update the vector parameters
-
updateObject(ob);
-
// check the walls for collisions
-
for (x=0; x<game.v.length; x++) {
-
var w = game.v[x];
-
var v = findIntersection(ob, w);
-
v = updateVector(v, false);
-
var pen = ob.r-v.len;
-
// if we have hit the wall
-
if (pen>=0) {
-
// move object away from the wall
-
ob.p1.x += v.dx*pen;
-
ob.p1.y += v.dy*pen;
-
// change movement, bounce off from the normal of v
-
var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
-
var vb = bounce(ob, vbounce);
-
ob.vx = vb.vx;
-
ob.vy = vb.vy;
-
}
-
}
-
/********************************************************************/
-
// CODE ADDED BY SRDJAN SUSNIC
-
// check the lines created by mouse for collisions
-
x = 0;
-
while (x<game.mouseV.length) {
-
var w = game.mouseV[x];
-
var v = findIntersection(ob, w);
-
v = updateVector(v, false);
-
var pen = ob.r-v.len;
-
// if we have hit the wall
-
if (pen>=0) {
-
// move object away from the wall
-
ob.p1.x += v.dx*pen;
-
ob.p1.y += v.dy*pen;
-
// change movement, bounce off from the normal of v
-
var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
-
var vb = bounce(ob, vbounce);
-
ob.vx = vb.vx;
-
ob.vy = vb.vy;
-
// remove the clip and vector array of the collided line
-
game.mouseV[x].lineClip.removeMovieClip();
-
game.mouseV.splice(x, 1);
-
} else {
-
x++;
-
}
-
}
-
// END OF CODE ADDED BY SRDJAN SUSNIC
-
/********************************************************************/
-
// reset object to other side if gone out of stage
-
if (ob.p1.x>game.stageW+ob.r) {
-
ob.p1.x = -ob.r;
-
} else if (ob.p1.x<-ob.r) {
-
ob.p1.x = game.stageW+ob.r;
-
}
-
if (ob.p1.y>game.stageH+ob.r) {
-
ob.p1.y = -ob.r;
-
} else if (ob.p1.y<-ob.r) {
-
ob.p1.y = game.stageH+ob.r;
-
}
-
// draw it
-
drawAll(ob);
-
// make end point equal to starting point for next cycle
-
ob.p0 = ob.p1;
-
// save the movement without time
-
ob.vx = ob.vx/ob.timeFrame;
-
ob.vy = ob.vy/ob.timeFrame;
-
}
-
// function to find all parameters for the vector
-
function updateVector(v, frompoints) {
-
// x and y components
-
if (frompoints) {
-
v.vx = v.p1.x-v.p0.x;
-
v.vy = v.p1.y-v.p0.y;
-
} else {
-
v.p1.x = v.p0.x+v.vx;
-
v.p1.y = v.p0.y+v.vy;
-
}
-
// length of vector
-
v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
-
// normalized unti-sized components
-
if (v.len>0) {
-
v.dx = v.vx/v.len;
-
v.dy = v.vy/v.len;
-
} else {
-
v.dx = 0;
-
v.dy = 0;
-
}
-
// right hand normal
-
v.rx = -v.dy;
-
v.ry = v.dx;
-
// left hand normal
-
v.lx = v.dy;
-
v.ly = -v.dx;
-
return v;
-
}
-
function updateObject(v) {
-
// find time passed from last update
-
var thisTime = getTimer();
-
var time = (thisTime-v.lastTime)/100;
-
// we use time, not frames to move so multiply movement vector with time passed
-
v.vx *= time;
-
v.vy *= time;
-
// add gravity, also based on time
-
v.vy = v.vy+time*game.gravity;
-
v.p1 = {};
-
// find end point coordinates
-
v.p1.x = v.p0.x+v.vx;
-
v.p1.y = v.p0.y+v.vy;
-
// length of vector
-
v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
-
// normalized unti-sized components
-
v.dx = v.vx/v.len;
-
v.dy = v.vy/v.len;
-
// right hand normal
-
v.rx = -v.vy;
-
v.ry = v.vx;
-
// left hand normal
-
v.lx = v.vy;
-
v.ly = -v.vx;
-
// save the current time
-
v.lastTime = thisTime;
-
// save time passed
-
v.timeFrame = time;
-
}
-
// find intersection point of 2 vectors
-
function findIntersection(v1, v2) {
-
// vector between center of ball and starting point of wall
-
var v3 = {};
-
v3.vx = v1.p1.x-v2.p0.x;
-
v3.vy = v1.p1.y-v2.p0.y;
-
// check if we have hit starting point
-
var dp = v3.vx*v2.dx+v3.vy*v2.dy;
-
if (dp<0) {
-
// hits starting point
-
var v = v3;
-
} else {
-
var v4 = {};
-
v4.vx = v1.p1.x-v2.p1.x;
-
v4.vy = v1.p1.y-v2.p1.y;
-
// check if we have hit side or endpoint
-
var dp = v4.vx*v2.dx+v4.vy*v2.dy;
-
if (dp>0) {
-
// hits ending point
-
var v = v4;
-
} else {
-
// it hits the wall
-
// project this vector on the normal of the wall
-
var v = projectVector(v3, v2.lx, v2.ly);
-
}
-
}
-
return v;
-
}
-
// find new vector bouncing from v2
-
function bounce(v1, v2) {
-
// projection of v1 on v2
-
var proj1 = projectVector(v1, v2.dx, v2.dy);
-
// projection of v1 on v2 normal
-
var proj2 = projectVector(v1, v2.lx, v2.ly);
-
var proj = {};
-
// reverse projection on v2 normal
-
proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
-
proj2.vx = v2.lx*proj2.len;
-
proj2.vy = v2.ly*proj2.len;
-
// add the projections
-
proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
-
proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
-
return proj;
-
}
-
// project vector v1 on unit-sized vector dx/dy
-
function projectVector(v1, dx, dy) {
-
// find dot product
-
var dp = v1.vx*dx+v1.vy*dy;
-
var proj = {};
-
// projection components
-
proj.vx = dp*dx;
-
proj.vy = dp*dy;
-
return proj;
-
}
-
/********************************************************************/
-
// CODE ADDED BY SRDJAN SUSNIC
-
// declare starting point of the current drawing line
-
var lineX1, lineY1;
-
// declare ending point of the current drawing line
-
var lineX2, lineY2;
-
// flag that states if we can draw line or not
-
can_draw = false;
-
// flag that states if the player drew a line
-
player_drew = false;
-
// next movie depth for the current drawing line
-
nextLineDepth = 0;
-
// create array for vectors of lines drawn by mouse
-
game.mouseV = new Array();
-
// create a movie which represents a line drawn by mouse
-
_root.createEmptyMovieClip(“mouseLine”, 3);
-
// when we click…
-
onMouseDown = function () {
-
// get starting point of line according to current mouse position
-
lineX1 = _root._xmouse;
-
lineY1 = _root._ymouse;
-
// set drawing flag so we can draw a line when mouse is moved
-
can_draw = true;
-
};
-
// when we move mouse…
-
onMouseMove = function () {
-
if (can_draw) {
-
// the player is drawing!
-
player_drew = true;
-
// get ending point of line according to current mouse position
-
lineX2 = _root._xmouse;
-
lineY2 = _root._ymouse;
-
// clear the previous line drawn by mouse
-
mouseLine.clear();
-
// set the drawing style
-
mouseLine.lineStyle(2, 0×00dd00);
-
// move the pen to the starting position
-
mouseLine.moveTo(lineX1, lineY1);
-
// draw the line to the ending position
-
mouseLine.lineTo(lineX2, lineY2);
-
}
-
};
-
// when we release…
-
onMouseUp = function () {
-
if (player_drew) {
-
// clear the line drawn by mouse
-
mouseLine.clear();
-
// create a new movie clip which contains the line previously drawn by mouse
-
var tmp = createEmptyMovieClip(“newLine”, 10+nextLineDepth);
-
tmp.lineStyle(5, 0×0000ff);
-
tmp.moveTo(lineX1, lineY1);
-
tmp.lineTo(lineX2, lineY2);
-
// increase movie depth for the next line
-
nextLineDepth++;
-
// add the parameters of previously created line to the end of line vectors array
-
// lineClip parameter is used to store previously created line movie clip
-
// so we can remove it when ball bounces from it
-
index = game.mouseV.length;
-
game.mouseV[index] = {p0:{x:lineX1, y:lineY1}, p1:{x:lineX2, y:lineY2}, b:1, f:1, lineClip:tmp};
-
// calculate all parameters for the created line vector
-
updateVector(game.mouseV[index], true);
-
// set drawing flag so we can’t draw a line when mouse is moved
-
player_drew = false;
-
}
-
can_draw = false;
-
};
-
// END OF CODE ADDED BY SRDJAN SUSNIC
-
/********************************************************************/
And this is the result:
Now you can draw lines with the mouse and the only thing we need in order to have a complete game engine is handling the exit.
Any idea?
Download the source code and play.
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
|
|  |
You know Flash content is invisible to search engines. In order to have your Flash page (or game) indexed, you have to create an HTML page with some keywords, and pray.
Until yesterday.
Today, something is changing in Search Engines Optimization (SEO) techniques.
Look what Google and Adobe have to say
From Adobe
Adobe is providing optimized Adobe Flash Player technology to Google and Yahoo! to enhance search engine indexing of the Flash file format (SWF) and uncover information that is currently undiscoverable by search engines. This will provide more relevant automatic search rankings of the millions of dynamic content that run in Adobe Flash Player.
Without additional changes to content, developers can continue to provide experiences that are possible only with Adobe Flash technology without the trade-off of a loss in search indexing.
It will also positively affect the Search Engine Optimization community, which will develop best practices for building content utilizing Adobe Flash technologies, and enhance the ability to find and monetize SWF content.
Source: SWF searchability FAQ
From Google
Q: What do I need to do to get Google to index the text in my Flash files?
Basically, you don’t need to do anything. The improvements that we have made do not require any special action on the part of web designers or webmasters. If you have Flash content on your website, we will automatically begin to index it, up to the limits of our current technical ability.
That said, you should be aware that Google is now able to see the text that appears to visitors of your website. If you prefer Google to ignore your less informative content, such as a “copyright” or “loading” message, consider replacing the text within an image, which will make it effectively invisible to us.
Source: Improved Flash indexing
How can I get benefits from that?
If a successful SWF file will link to some external sites, maybe this will affect PageRank or at least help sites ranking.
A link to a sponsor in a successful game probably will get more valuable, and maybe people that look for your game will be able to find it in the official page and not in one portal with better ranking than your one.
Just rambling of course, but I am very very interested in it…
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
|
|  |
In the 1st part I showed you how to make a deflection engine starting from an old tutorial, now it’s time to let the player draw walls.
The idea comes from Srdjan Susnic, a reader who runs the blog Ask For Game Task.
The main task Srdjan accomplished was to add a mouse control so a player can draw lines from which the ball will bounce.
After collision between the ball and a line drawn by mouse, that line must be removed
The code is clear and well commented, but it seems to suffer a bug if the player just clicks the mouse without drawing.
It’s just a minor issue I fixed in a moment, and if you already read the original post, I just added the control if the player drew a line when he releases the mouse button with player_drew variable.
Anyway, this is the actionscript:
ACTIONSCRIPT:
-
// create game object
-
game = {gravity:0, dragging:false, clip:_root.game_mc, stageW:500, stageH:400, maxV:20};
-
// create object
-
// point p0 is its starting point in the coordinates x/y
-
_root.attachMovie(“ball”, “ball”, 1);
-
game.myOb = {clip:ball, airf:1, b:1, f:1, r:20, lastTime:getTimer()};
-
game.myOb.p0 = {x:150, y:80};
-
// vectors x/y components
-
game.myOb.vx = 8;
-
game.myOb.vy = 12;
-
// create first vector
-
// point p0 is its starting point in the coordinates x/y
-
// point p1 is its end point in the coordinates x/y
-
game.v = new Array();
-
game.v[0] = {p0:{x:50, y:40}, p1:{x:450, y:40}, b:1, f:1};
-
game.v[1] = {p0:{x:50, y:40}, p1:{x:50, y:360}, b:1, f:1};
-
game.v[2] = {p0:{x:50, y:360}, p1:{x:450, y:360}, b:1, f:1};
-
game.v[3] = {p0:{x:100, y:80}, p1:{x:400, y:320}, b:1, f:1};
-
_root.createEmptyMovieClip(“lines”, 2);
-
lines.lineStyle(1, 0xff0000);
-
// draw and calculate all parameters for the wall vectors
-
for (x=0; x<game.v.length; x++) {
-
lines.moveTo(game.v[x].p0.x, game.v[x].p0.y);
-
lines.lineTo(game.v[x].p1.x, game.v[x].p1.y);
-
updateVector(game.v[x], true);
-
}
-
_root.onEnterFrame = function() {
-
_root.runMe();
-
};
-
// function to draw the points, lines and show text
-
function drawAll(v) {
-
// place ob mc
-
v.clip._x = v.p1.x;
-
v.clip._y = v.p1.y;
-
}
-
// main function
-
function runMe() {
-
// start to calculate movement
-
var ob = game.myOb;
-
// add air resistance
-
ob.vx *= ob.airf;
-
ob.vy *= ob.airf;
-
// dont let it go over max speed
-
if (ob.vx>game.maxV) {
-
ob.vx = game.maxV;
-
} else if (ob.vx<-game.maxV) {
-
ob.vx = -game.maxV;
-
}
-
if (ob.vy>game.maxV) {
-
ob.vy = game.maxV;
-
} else if (ob.vy<-game.maxV) {
-
ob.vy = -game.maxV;
-
}
-
// update the vector parameters
-
updateObject(ob);
-
// check the walls for collisions
-
for (x=0; x<game.v.length; x++) {
-
var w = game.v[x];
-
var v = findIntersection(ob, w);
-
v = updateVector(v, false);
-
var pen = ob.r-v.len;
-
// if we have hit the wall
-
if (pen>=0) {
-
// move object away from the wall
-
ob.p1.x += v.dx*pen;
-
ob.p1.y += v.dy*pen;
-
// change movement, bounce off from the normal of v
-
var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
-
var vb = bounce(ob, vbounce);
-
ob.vx = vb.vx;
-
ob.vy = vb.vy;
-
}
-
}
-
/********************************************************************/
-
// CODE ADDED BY SRDJAN SUSNIC
-
// check the lines created by mouse for collisions
-
x = 0;
-
while (x<game.mouseV.length) {
-
var w = game.mouseV[x];
-
var v = findIntersection(ob, w);
-
v = updateVector(v, false);
-
var pen = ob.r-v.len;
-
// if we have hit the wall
-
if (pen>=0) {
-
// move object away from the wall
-
ob.p1.x += v.dx*pen;
-
ob.p1.y += v.dy*pen;
-
// change movement, bounce off from the normal of v
-
var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
-
var vb = bounce(ob, vbounce);
-
ob.vx = vb.vx;
-
ob.vy = vb.vy;
-
// remove the clip and vector array of the collided line
-
game.mouseV[x].lineClip.removeMovieClip();
-
game.mouseV.splice(x, 1);
-
} else {
-
x++;
-
}
-
}
-
// END OF CODE ADDED BY SRDJAN SUSNIC
-
/********************************************************************/
-
// reset object to other side if gone out of stage
-
if (ob.p1.x>game.stageW+ob.r) {
-
ob.p1.x = -ob.r;
-
} else if (ob.p1.x<-ob.r) {
-
ob.p1.x = game.stageW+ob.r;
-
}
-
if (ob.p1.y>game.stageH+ob.r) {
-
ob.p1.y = -ob.r;
-
} else if (ob.p1.y<-ob.r) {
-
ob.p1.y = game.stageH+ob.r;
-
}
-
// draw it
-
drawAll(ob);
-
// make end point equal to starting point for next cycle
-
ob.p0 = ob.p1;
-
// save the movement without time
-
ob.vx = ob.vx/ob.timeFrame;
-
ob.vy = ob.vy/ob.timeFrame;
-
}
-
// function to find all parameters for the vector
-
function updateVector(v, frompoints) {
-
// x and y components
-
if (frompoints) {
-
v.vx = v.p1.x-v.p0.x;
-
v.vy = v.p1.y-v.p0.y;
-
} else {
-
v.p1.x = v.p0.x+v.vx;
-
v.p1.y = v.p0.y+v.vy;
-
}
-
// length of vector
-
v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
-
// normalized unti-sized components
-
if (v.len>0) {
-
v.dx = v.vx/v.len;
-
v.dy = v.vy/v.len;
-
} else {
-
v.dx = 0;
-
v.dy = 0;
-
}
-
// right hand normal
-
v.rx = -v.dy;
-
v.ry = v.dx;
-
// left hand normal
-
v.lx = v.dy;
-
v.ly = -v.dx;
-
return v;
-
}
-
function updateObject(v) {
-
// find time passed from last update
-
var thisTime = getTimer();
-
var time = (thisTime-v.lastTime)/100;
-
// we use time, not frames to move so multiply movement vector with time passed
-
v.vx *= time;
-
v.vy *= time;
-
// add gravity, also based on time
-
v.vy = v.vy+time*game.gravity;
-
v.p1 = {};
-
// find end point coordinates
-
v.p1.x = v.p0.x+v.vx;
-
v.p1.y = v.p0.y+v.vy;
-
// length of vector
-
v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
-
// normalized unti-sized components
-
v.dx = v.vx/v.len;
-
v.dy = v.vy/v.len;
-
// right hand normal
-
v.rx = -v.vy;
-
v.ry = v.vx;
-
// left hand normal
-
v.lx = v.vy;
-
v.ly = -v.vx;
-
// save the current time
-
v.lastTime = thisTime;
-
// save time passed
-
v.timeFrame = time;
-
}
-
// find intersection point of 2 vectors
-
function findIntersection(v1, v2) {
-
// vector between center of ball and starting point of wall
-
var v3 = {};
-
v3.vx = v1.p1.x-v2.p0.x;
-
v3.vy = v1.p1.y-v2.p0.y;
-
// check if we have hit starting point
-
var dp = v3.vx*v2.dx+v3.vy*v2.dy;
-
if (dp<0) {
-
// hits starting point
-
var v = v3;
-
} else {
-
var v4 = {};
-
v4.vx = v1.p1.x-v2.p1.x;
-
v4.vy = v1.p1.y-v2.p1.y;
-
// check if we have hit side or endpoint
-
var dp = v4.vx*v2.dx+v4.vy*v2.dy;
-
if (dp>0) {
-
// hits ending point
-
var v = v4;
-
} else {
-
// it hits the wall
-
// project this vector on the normal of the wall
-
var v = projectVector(v3, v2.lx, v2.ly);
-
}
-
}
-
return v;
-
}
-
// find new vector bouncing from v2
-
function bounce(v1, v2) {
-
// projection of v1 on v2
-
var proj1 = projectVector(v1, v2.dx, v2.dy);
-
// projection of v1 on v2 normal
-
var proj2 = projectVector(v1, v2.lx, v2.ly);
-
var proj = {};
-
// reverse projection on v2 normal
-
proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
-
proj2.vx = v2.lx*proj2.len;
-
proj2.vy = v2.ly*proj2.len;
-
// add the projections
-
proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
-
proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
-
return proj;
-
}
-
// project vector v1 on unit-sized vector dx/dy
-
function projectVector(v1, dx, dy) {
-
// find dot product
-
var dp = v1.vx*dx+v1.vy*dy;
-
var proj = {};
-
// projection components
-
proj.vx = dp*dx;
-
proj.vy = dp*dy;
-
return proj;
-
}
-
/********************************************************************/
-
// CODE ADDED BY SRDJAN SUSNIC
-
// declare starting point of the current drawing line
-
var lineX1, lineY1;
-
// declare ending point of the current drawing line
-
var lineX2, lineY2;
-
// flag that states if we can draw line or not
-
can_draw = false;
-
// flag that states if the player drew a line
-
player_drew = false;
-
// next movie depth for the current drawing line
-
nextLineDepth = 0;
-
// create array for vectors of lines drawn by mouse
-
game.mouseV = new Array();
-
// create a movie which represents a line drawn by mouse
-
_root.createEmptyMovieClip(“mouseLine”, 3);
-
// when we click…
-
onMouseDown = function () {
-
// get starting point of line according to current mouse position
-
lineX1 = _root._xmouse;
-
lineY1 = _root._ymouse;
-
// set drawing flag so we can draw a line when mouse is moved
-
can_draw = true;
-
};
-
// when we move mouse…
-
onMouseMove = function () {
-
if (can_draw) {
-
// the player is drawing!
-
player_drew = true;
-
// get ending point of line according to current mouse position
-
lineX2 = _root._xmouse;
-
lineY2 = _root._ymouse;
-
// clear the previous line drawn by mouse
-
mouseLine.clear();
-
// set the drawing style
-
mouseLine.lineStyle(2, 0×00dd00);
-
// move the pen to the starting position
-
mouseLine.moveTo(lineX1, lineY1);
-
// draw the line to the ending position
-
mouseLine.lineTo(lineX2, lineY2);
-
}
-
};
-
// when we release…
-
onMouseUp = function () {
-
if (player_drew) {
-
// clear the line drawn by mouse
-
mouseLine.clear();
-
// create a new movie clip which contains the line previously drawn by mouse
-
var tmp = createEmptyMovieClip(“newLine”, 10+nextLineDepth);
-
tmp.lineStyle(5, 0×0000ff);
-
tmp.moveTo(lineX1, lineY1);
-
tmp.lineTo(lineX2, lineY2);
-
// increase movie depth for the next line
-
nextLineDepth++;
-
// add the parameters of previously created line to the end of line vectors array
-
// lineClip parameter is used to store previously created line movie clip
-
// so we can remove it when ball bounces from it
-
index = game.mouseV.length;
-
game.mouseV[index] = {p0:{x:lineX1, y:lineY1}, p1:{x:lineX2, y:lineY2}, b:1, f:1, lineClip:tmp};
-
// calculate all parameters for the created line vector
-
updateVector(game.mouseV[index], true);
-
// set drawing flag so we can’t draw a line when mouse is moved
-
player_drew = false;
-
}
-
can_draw = false;
-
};
-
// END OF CODE ADDED BY SRDJAN SUSNIC
-
/********************************************************************/
And this is the result:
Now you can draw lines with the mouse and the only thing we need in order to have a complete game engine is handling the exit.
Any idea?
Download the source code and play.
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
|
|  |
Today I spent some time with a game called Deflection.

According to his author, it’s an addictive physics based game where the objective is to deflect the ball into the goal by creating deflection walls.
I bet I scared most of you with the word “physics”. This means a physics engine, massive AS3 coding, and so on.
Although I am seriously determined to start a tutorial series about latest physics engines, I played a bit with Deflection and I noticed the only physics involved in the game is used to determine the bounce of a regular shape (a circle - the ball) when collides with a line.
So I thought there was another way to create an engine like this one without using physics libraries.
The answer lies in an old vector tutorial made by Tony Pa called Ball in the corner.
I suggest you to read all Tony’s vector tutorials to understand the math behind the engine.
I made some changes to the tutorial in order to make it more “AS2 like” (it’s an old AS1 tutorial) and to manage an arbitrary number of lines.
In this step you will only see the engine working with 4 lines and no user interaction, but it’s really easy to add lines at runtime with the mouse (I’ll cover it in the next step).
Moreover, this is another good example about how to use a Flash game tutorial to make your own game.
Ok, now it’s time to show you the modified actionscript:
ACTIONSCRIPT:
-
// create game object
-
game = {gravity:0, dragging:false, clip:_root.game_mc, stageW:500, stageH:400, maxV:20};
-
// create object
-
// point p0 is its starting point in the coordinates x/y
-
_root.attachMovie(“ball”, “ball”, 1);
-
game.myOb = {clip:ball, airf:1, b:1, f:1, r:20, lastTime:getTimer()};
-
game.myOb.p0 = {x:150, y:80};
-
// vectors x/y components
-
game.myOb.vx = 8;
-
game.myOb.vy = 12;
-
// create first vector
-
// point p0 is its starting point in the coordinates x/y
-
// point p1 is its end point in the coordinates x/y
-
game.v = new Array();
-
game.v[0] = {p0:{x:50, y:40}, p1:{x:450, y:40}, b:1, f:1};
-
game.v[1] = {p0:{x:50, y:40}, p1:{x:50, y:360}, b:1, f:1};
-
game.v[2] = {p0:{x:50, y:360}, p1:{x:450, y:360}, b:1, f:1};
-
game.v[3] = {p0:{x:100, y:80}, p1:{x:400, y:320}, b:1, f:1};
-
_root.createEmptyMovieClip(“lines”, 2);
-
lines.lineStyle(1, 0xff0000);
-
// draw and calculate all parameters for the wall vectors
-
for (x=0; x<game.v.length; x++) {
-
lines.moveTo(game.v[x].p0.x, game.v[x].p0.y);
-
lines.lineTo(game.v[x].p1.x, game.v[x].p1.y);
-
updateVector(game.v[x], true);
-
}
-
_root.onEnterFrame = function() {
-
_root.runMe();
-
};
-
// function to draw the points, lines and show text
-
function drawAll(v) {
-
// place ob mc
-
v.clip._x = v.p1.x;
-
v.clip._y = v.p1.y;
-
}
-
// main function
-
function runMe() {
-
// start to calculate movement
-
var ob = game.myOb;
-
// add air resistance
-
ob.vx *= ob.airf;
-
ob.vy *= ob.airf;
-
// dont let it go over max speed
-
if (ob.vx>game.maxV) {
-
ob.vx = game.maxV;
-
} else if (ob.vx<-game.maxV) {
-
ob.vx = -game.maxV;
-
}
-
if (ob.vy>game.maxV) {
-
ob.vy = game.maxV;
-
} else if (ob.vy<-game.maxV) {
-
ob.vy = -game.maxV;
-
}
-
// update the vector parameters
-
updateObject(ob);
-
// check the walls for collisions
-
for (x=0; x<game.v.length; x++) {
-
var w = game.v[x];
-
var v = findIntersection(ob, w);
-
v = updateVector(v, false);
-
var pen = ob.r-v.len;
-
// if we have hit the wall
-
if (pen>=0) {
-
// move object away from the wall
-
ob.p1.x += v.dx*pen;
-
ob.p1.y += v.dy*pen;
-
// change movement, bounce off from the normal of v
-
var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
-
var vb = bounce(ob, vbounce);
-
ob.vx = vb.vx;
-
ob.vy = vb.vy;
-
}
-
}
-
// reset object to other side if gone out of stage
-
if (ob.p1.x>game.stageW+ob.r) {
-
ob.p1.x = -ob.r;
-
} else if (ob.p1.x<-ob.r) {
-
ob.p1.x = game.stageW+ob.r;
-
}
-
if (ob.p1.y>game.stageH+ob.r) {
-
ob.p1.y = -ob.r;
-
} else if (ob.p1.y<-ob.r) {
-
ob.p1.y = game.stageH+ob.r;
-
}
-
// draw it
-
drawAll(ob);
-
// make end point equal to starting point for next cycle
-
ob.p0 = ob.p1;
-
// save the movement without time
-
ob.vx = ob.vx/ob.timeFrame;
-
ob.vy = ob.vy/ob.timeFrame;
-
}
-
// function to find all parameters for the vector
-
function updateVector(v, frompoints) {
-
// x and y components
-
if (frompoints) {
-
v.vx = v.p1.x-v.p0.x;
-
v.vy = v.p1.y-v.p0.y;
-
} else {
-
v.p1.x = v.p0.x+v.vx;
-
v.p1.y = v.p0.y+v.vy;
-
}
-
// length of vector
-
v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
-
// normalized unti-sized components
-
if (v.len>0) {
-
v.dx = v.vx/v.len;
-
v.dy = v.vy/v.len;
-
} else {
-
v.dx = 0;
-
v.dy = 0;
-
}
-
// right hand normal
-
v.rx = -v.dy;
-
v.ry = v.dx;
-
// left hand normal
-
v.lx = v.dy;
-
v.ly = -v.dx;
-
return v;
-
}
-
function updateObject(v) {
-
// find time passed from last update
-
var thisTime = getTimer();
-
var time = (thisTime-v.lastTime)/100;
-
// we use time, not frames to move so multiply movement vector with time passed
-
v.vx *= time;
-
v.vy *= time;
-
// add gravity, also based on time
-
v.vy = v.vy+time*game.gravity;
-
v.p1 = {};
-
// find end point coordinates
-
v.p1.x = v.p0.x+v.vx;
-
v.p1.y = v.p0.y+v.vy;
-
// length of vector
-
v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
-
// normalized unti-sized components
-
v.dx = v.vx/v.len;
-
v.dy = v.vy/v.len;
-
// right hand normal
-
v.rx = -v.vy;
-
v.ry = v.vx;
-
// left hand normal
-
v.lx = v.vy;
-
v.ly = -v.vx;
-
// save the current time
-
v.lastTime = thisTime;
-
// save time passed
-
v.timeFrame = time;
-
}
-
// find intersection point of 2 vectors
-
function findIntersection(v1, v2) {
-
// vector between center of ball and starting point of wall
-
var v3 = {};
-
v3.vx = v1.p1.x-v2.p0.x;
-
v3.vy = v1.p1.y-v2.p0.y;
-
// check if we have hit starting point
-
var dp = v3.vx*v2.dx+v3.vy*v2.dy;
-
if (dp<0) {
-
// hits starting point
-
var v = v3;
-
} else {
-
var v4 = {};
-
v4.vx = v1.p1.x-v2.p1.x;
-
v4.vy = v1.p1.y-v2.p1.y;
-
// check if we have hit side or endpoint
-
var dp = v4.vx*v2.dx+v4.vy*v2.dy;
-
if (dp>0) {
-
// hits ending point
-
var v = v4;
-
} else {
-
// it hits the wall
-
// project this vector on the normal of the wall
-
var v = projectVector(v3, v2.lx, v2.ly);
-
}
-
}
-
return v;
-
}
-
// find new vector bouncing from v2
-
function bounce(v1, v2) {
-
// projection of v1 on v2
-
var proj1 = projectVector(v1, v2.dx, v2.dy);
-
// projection of v1 on v2 normal
-
var proj2 = projectVector(v1, v2.lx, v2.ly);
-
var proj = {};
-
// reverse projection on v2 normal
-
proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
-
proj2.vx = v2.lx*proj2.len;
-
proj2.vy = v2.ly*proj2.len;
-
// add the projections
-
proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
-
proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
-
return proj;
-
}
-
// project vector v1 on unit-sized vector dx/dy
-
function projectVector(v1, dx, dy) {
-
// find dot product
-
var dp = v1.vx*dx+v1.vy*dy;
-
var proj = {};
-
// projection components
-
proj.vx = dp*dx;
-
proj.vy = dp*dy;
-
return proj;
-
}
and this is the result… your own AS2 deflection engine ready for you to create a game.
If you want to write the code for player interaction, I will be happy to publish it, otherwise wait for me to do it.
Download the source code and enjoy.
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
|
|  |
“How do I make my game better?” is the number one question Flash developers ask. Perhaps you’ve finished the game and think you’re done… but no sponsors are interested. Or perhaps you have a rough version of the game finished but have no idea how to turn it into a polished gem of a game. How do you improve your game?
First Impressions are the answer! We ask arbitrary users with wildly different gaming backgrounds to play your game for 5 minutes and give you their first impressions. They each write a paragraph of comments, along with some ratings on things like graphics quality and intuitiveness. Once you’ve gotten ten or twenty fresh opinions about your game, you’re bound to have a better idea of what to do next. And once you’ve made improvements, you can get more first impressions to see how people reacted to your changes.
First Impressions
With these words FlashGameLicense crew introduce their new service, called First Impressions (FI from now on).
If you don’t know what is FlashGameLicense (FGL from now on…), it’s a marketplace where Flash game developers and sponsor can meet. Read my review about it.
But now we are talking about the FI service. Basically, you are paying for people to play and review your game.
At this time, you may wonder why should you pay for a review when you can freely submit your game to a portal that allows people to review games and get reviews for free.
While it’s true that you could have some reviews at no cost, remember once your game is published, it’s not an unreleased game anymore… and this is important when you are looking for a sponsorship.
Also, most of the reviews people leave on portals are something like “Awesome! I enjoyed a lot! Thanx mate!” or “Boring. 2/5″… after playing your game for less than 30 seconds.
So, if you are looking to keep your game unreleased and have good quality reviews, you should consider purchasing the FI service.
Let’s make a test drive
You know I like to try and test everything… so I ordered 20 reviews for an one-week game that is about to be released.
Once you purchase your reviews, people start reviewing it very quickly… you will suffer the so-called “refresh syndrome” because you will find yourself reloading the page again and again just to see another review.
FI reviewers are paid to play and review, and this is the reason why reviews are always appropriate.
While I cannot show you all the reviews because most of them contain descriptions and spoilers about the game (that’s not already published), I want to show you a couple of screens where you will see how players reviewed the game.
I blurred off descriptions and comments


Only you can read these First Impressions and see the scores that reviewers give you. They are entirely private.
Final considerations
At $1 per review, it may seem a bit expensive, but you can fine-tune and polish a complex game with no more than 20 or 30 reviews, that will cost you less than a paid API integration or less than 100,000 plays if you will embed MochiAds ads.
So it’s definitively a good buy, expect an high return of investment from this feature.
To start ordering reviews and make your game better, just sign in to FlashGameLicense and you’re ready to make better games.
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
|
|  |
Today I spent some time with a game called Deflection.

According to his author, it’s an addictive physics based game where the objective is to deflect the ball into the goal by creating deflection walls.
I bet I scared most of you with the word “physics”. This means a physics engine, massive AS3 coding, and so on.
Although I am seriously determined to start a tutorial series about latest physics engines, I played a bit with Deflection and I noticed the only physics involved in the game is used to determine the bounce of a regular shape (a circle - the ball) when collides with a line.
So I thought there was another way to create an engine like this one without using physics libraries.
The answer lies in an old vector tutorial made by Tony Pa called Ball in the corner.
I suggest you to read all Tony’s vector tutorials to understand the math behind the engine.
I made some changes to the tutorial in order to make it more “AS2 like” (it’s an old AS1 tutorial) and to manage an arbitrary number of lines.
In this step you will only see the engine working with 4 lines and no user interaction, but it’s really easy to add lines at runtime with the mouse (I’ll cover it in the next step).
Moreover, this is another good example about how to use a Flash game tutorial to make your own game.
Ok, now it’s time to show you the modified actionscript:
ACTIONSCRIPT:
-
// create game object
-
game = {gravity:0, dragging:false, clip:_root.game_mc, stageW:500, stageH:400, maxV:20};
-
// create object
-
// point p0 is its starting point in the coordinates x/y
-
_root.attachMovie(“ball”, “ball”, 1);
-
game.myOb = {clip:ball, airf:1, b:1, f:1, r:20, lastTime:getTimer()};
-
game.myOb.p0 = {x:150, y:80};
-
// vectors x/y components
-
game.myOb.vx = 8;
-
game.myOb.vy = 12;
-
// create first vector
-
// point p0 is its starting point in the coordinates x/y
-
// point p1 is its end point in the coordinates x/y
-
game.v = new Array();
-
game.v[0] = {p0:{x:50, y:40}, p1:{x:450, y:40}, b:1, f:1};
-
game.v[1] = {p0:{x:50, y:40}, p1:{x:50, y:360}, b:1, f:1};
-
game.v[2] = {p0:{x:50, y:360}, p1:{x:450, y:360}, b:1, f:1};
-
game.v[3] = {p0:{x:100, y:80}, p1:{x:400, y:320}, b:1, f:1};
-
_root.createEmptyMovieClip(“lines”, 2);
-
lines.lineStyle(1, 0xff0000);
-
// draw and calculate all parameters for the wall vectors
-
for (x=0; x<game.v.length; x++) {
-
lines.moveTo(game.v[x].p0.x, game.v[x].p0.y);
-
lines.lineTo(game.v[x].p1.x, game.v[x].p1.y);
-
updateVector(game.v[x], true);
-
}
-
_root.onEnterFrame = function() {
-
_root.runMe();
-
};
-
// function to draw the points, lines and show text
-
function drawAll(v) {
-
// place ob mc
-
v.clip._x = v.p1.x;
-
v.clip._y = v.p1.y;
-
}
-
// main function
-
function runMe() {
-
// start to calculate movement
-
var ob = game.myOb;
-
// add air resistance
-
ob.vx *= ob.airf;
-
ob.vy *= ob.airf;
-
// dont let it go over max speed
-
if (ob.vx>game.maxV) {
-
ob.vx = game.maxV;
-
} else if (ob.vx<-game.maxV) {
-
ob.vx = -game.maxV;
-
}
-
if (ob.vy>game.maxV) {
-
ob.vy = game.maxV;
-
} else if (ob.vy<-game.maxV) {
-
ob.vy = -game.maxV;
-
}
-
// update the vector parameters
-
updateObject(ob);
-
// check the walls for collisions
-
for (x=0; x<game.v.length; x++) {
-
var w = game.v[x];
-
var v = findIntersection(ob, w);
-
v = updateVector(v, false);
-
var pen = ob.r-v.len;
-
// if we have hit the wall
-
if (pen>=0) {
-
// move object away from the wall
-
ob.p1.x += v.dx*pen;
-
ob.p1.y += v.dy*pen;
-
// change movement, bounce off from the normal of v
-
var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
-
var vb = bounce(ob, vbounce);
-
ob.vx = vb.vx;
-
ob.vy = vb.vy;
-
}
-
}
-
// reset object to other side if gone out of stage
-
if (ob.p1.x>game.stageW+ob.r) {
-
ob.p1.x = -ob.r;
-
} else if (ob.p1.x<-ob.r) {
-
ob.p1.x = game.stageW+ob.r;
-
}
-
if (ob.p1.y>game.stageH+ob.r) {
-
ob.p1.y = -ob.r;
-
} else if (ob.p1.y<-ob.r) {
-
ob.p1.y = game.stageH+ob.r;
-
}
-
// draw it
-
drawAll(ob);
-
// make end point equal to starting point for next cycle
-
ob.p0 = ob.p1;
-
// save the movement without time
-
ob.vx = ob.vx/ob.timeFrame;
-
ob.vy = ob.vy/ob.timeFrame;
-
}
-
// function to find all parameters for the vector
-
function updateVector(v, frompoints) {
-
// x and y components
-
if (frompoints) {
-
v.vx = v.p1.x-v.p0.x;
-
v.vy = v.p1.y-v.p0.y;
-
} else {
-
v.p1.x = v.p0.x+v.vx;
-
v.p1.y = v.p0.y+v.vy;
-
}
-
// length of vector
-
v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
-
// normalized unti-sized components
-
if (v.len>0) {
-
v.dx = v.vx/v.len;
-
v.dy = v.vy/v.len;
-
} else {
-
v.dx = 0;
-
v.dy = 0;
-
}
-
// right hand normal
-
v.rx = -v.dy;
-
v.ry = v.dx;
-
// left hand normal
-
v.lx = v.dy;
-
v.ly = -v.dx;
-
return v;
-
}
-
function updateObject(v) {
-
// find time passed from last update
-
var thisTime = getTimer();
-
var time = (thisTime-v.lastTime)/100;
-
// we use time, not frames to move so multiply movement vector with time passed
-
v.vx *= time;
-
v.vy *= time;
-
// add gravity, also based on time
-
v.vy = v.vy+time*game.gravity;
-
v.p1 = {};
-
// find end point coordinates
-
v.p1.x = v.p0.x+v.vx;
-
v.p1.y = v.p0.y+v.vy;
-
// length of vector
-
v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
-
// normalized unti-sized components
-
v.dx = v.vx/v.len;
-
v.dy = v.vy/v.len;
-
// right hand normal
-
v.rx = -v.vy;
-
v.ry = v.vx;
-
// left hand normal
-
v.lx = v.vy;
-
v.ly = -v.vx;
-
// save the current time
-
v.lastTime = thisTime;
-
// save time passed
-
v.timeFrame = time;
-
}
-
// find intersection point of 2 vectors
-
function findIntersection(v1, v2) {
-
// vector between center of ball and starting point of wall
-
var v3 = {};
-
v3.vx = v1.p1.x-v2.p0.x;
-
v3.vy = v1.p1.y-v2.p0.y;
-
// check if we have hit starting point
-
var dp = v3.vx*v2.dx+v3.vy*v2.dy;
-
if (dp<0) {
-
// hits starting point
-
var v = v3;
-
} else {
-
var v4 = {};
-
v4.vx = v1.p1.x-v2.p1.x;
-
v4.vy = v1.p1.y-v2.p1.y;
-
// check if we have hit side or endpoint
-
var dp = v4.vx*v2.dx+v4.vy*v2.dy;
-
if (dp>0) {
-
// hits ending point
-
var v = v4;
-
} else {
-
// it hits the wall
-
// project this vector on the normal of the wall
-
var v = projectVector(v3, v2.lx, v2.ly);
-
}
-
}
-
return v;
-
}
-
// find new vector bouncing from v2
-
function bounce(v1, v2) {
-
// projection of v1 on v2
-
var proj1 = projectVector(v1, v2.dx, v2.dy);
-
// projection of v1 on v2 normal
-
var proj2 = projectVector(v1, v2.lx, v2.ly);
-
var proj = {};
-
// reverse projection on v2 normal
-
proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
-
proj2.vx = v2.lx*proj2.len;
-
proj2.vy = v2.ly*proj2.len;
-
// add the projections
-
proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
-
proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
-
return proj;
-
}
-
// project vector v1 on unit-sized vector dx/dy
-
function projectVector(v1, dx, dy) {
-
// find dot product
-
var dp = v1.vx*dx+v1.vy*dy;
-
var proj = {};
-
// projection components
-
proj.vx = dp*dx;
-
proj.vy = dp*dy;
-
return proj;
-
}
and this is the result… your own AS2 deflection engine ready for you to create a game.
If you want to write the code for player interaction, I will be happy to publish it, otherwise wait for me to do it.
Download the source code and enjoy.
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
|
|  |
In the last 2 parts we covered simple classes using object and static methods. Today I’m going to go over class extensions.Extending classes is really useful when you want to make a bunch of classes that have independent functionality but also share a lot of common functions.
One of the most useful ways to use class extensions in game development is to extend the MovieClip class, and that’s just what we’re going to do now!
MovieClips are a built in class type, so you can add all sorts of custom functionality to them.
To start, open up a new Flash Movie and just make a circle about 100 pixels wide/tall.
Select the circle then press F8 to bring up the ‘convert to symbol’ panel. Call the symbol ‘ball’ and select ‘MovieClip’. Press the ‘Advanced’ button, then check ‘Export for ActionScript.
In the AS 2.0 class box, type ‘BouncingClip’ and hit OK.
If you test your movie now you will get an error: “The class or interface ‘BouncingClip’ could not be loaded.”
I guess we better create the class then.
Save your Flash Movie somewhere like C:\flash_tutorial\bouncing_ball.fla
Open up a new ActionScript File, and put the following code in:
class BouncingClip extends MovieClip {
var gravity:Number = 10;
var velocity:Number = 0;
var terminal_velocity:Number = 100;
var friction = 90;
function onEnterFrame()
{
this._y += this.velocity
if (this._y + (this._height/2) > Stage.height) {
this._y = Stage.height - (this._height/2);
this.velocity *= -(this.friction/100);
}
this.velocity += this.gravity;
if (this.velocity > this.terminal_velocity) {
this.velocity = this.terminal_velocity;
}
}
}
As you see in the first line, we are extending the MovieClip class. All of the properties of movieclip can be accessed by our new class, but for this example all we are using is _y. We can also override any of the built-in methods. In this case we are overriding onEnterFrame, the function that is called on every frame of a movieclip.
Looking at the code you have probably figured out that we are telling this movieclip to fall and bounce when it hits the bottom of the stage.
Save the file in the same folder as your FLA and call it BouncingClip.as (C:\flash_tutorial\BouncingClip.as in this example).
Now when you test your movie, your ball will bounce.
For shits and giggle, go ahead and drag some more balls from your library.. maybe scale them do different sizes…. put them at different heights on the stage… then test again.
All the balls just work with that one common class!
So now that you have extended the MovieClip Class, let’s kick things up a notch.
In your Flash Movie, make a new circle, preferable a different color. Select it and hit F8… do the whole instance name deal again… hit advanced… etc etc…
This time, make the ActionScript 2.0 class “FlyingClip”.
Save your file, then open a new ActionScript File.
In the AS file, put the following code:
class FlyingClip extends BouncingClip {
var propulsion:Number = 12;
function onEnterFrame()
{
if (Key.isDown(Key.SPACE)) {
this.velocity -= this.propulsion;
}
}
}
Now we are extending the BouncingClip class. This means FlyingClip will have the same properties (velocity, gravity etc..) as BouncingClip, and will have access to all the MovieClip properties as well.
In this class we are overriding the onEnterFrame function again. In this function we are having the ball’s velocity decrease when the space bar is pressed making it go up.
Test your movie… you will see the ball does go up when you press space, but that’s all it does. This is because we overwrote the onEnterFrame function. Fortunately, this doesn’t completely eliminate the onEnterFrame function from the BouncingClip class, we can still call that using ’super’.
If you update your code to look like:
class FlyingClip extends BouncingClip {
var propulsion:Number = 12;
function onEnterFrame()
{
if (Key.isDown(Key.SPACE)) {
this.velocity -= this.propulsion;
}
super.onEnterFrame();
}
}
Now we are telling the clip to run the onEnterFrame function from the super class (the class that this class is extending), BouncingClip.
Test your movie now, and the new ball will fly when you press space, and will fall and bounce when you let go.
As you can imagine, extending classes this way can be very useful for developing game sprites that share common functionality such as collision detection, hit points, etc…, while having the freedom to add custom AI and user input as needed.
So there is your primer on using AS2 classes. As you can see, they are very useful in expanding the functionality of Flash, keeping your work organized and avoiding redundant and bloated code in your timelines.
Here’s the sample files, Enjoy!
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
|
|  |
In the last lesson we went over what a class is, touched on the types of functions you can do and created a static class with some commonly used math routines.
This time we’ll get into object based classes.
Object based classes are built the same way as any class. The main difference is in the way you declare and call their functions.
Here is an example of an object class:
class StopWatch {
var brand:String = ‘Timex’;
private var startTime:Number;
private var stopTime:Number;
private var displayTime:String;
private var memory:Number;
function StopWatch()
{
resetTimer();
}
function startTimer()
{
var date:Date = new Date();
if (!this.startTime and !this.stopTime) {
this.startTime = date.getTime();
} else if (this.stopTime) {
this.startTime = date.getTime()-this.memory;
this.stopTime = null;
}
}
function stopTimer()
{
if (!this.stopTime) {
var date:Date = new Date();
this.stopTime = date.getTime();
this.memory = this.stopTime-this.startTime;
}
}
function resetTimer()
{
this.displayTime = “00:00:00.00″;
this.startTime = null;
this.stopTime = null;
}
function readTimer()
{
var total_time:Number;
if (this.startTime) {
if (this.stopTime) {
total_time = this.stopTime - this.startTime;
} else {
var date:Date = new Date();
total_time = date.getTime() - this.startTime;
}
var seconds:Number = total_time/1000;
total_time = (total_time/1000)-seconds;
// round decimals to 2 places
seconds = Math.round(seconds*100)/100;
var minutes:Number = total_time%60;
total_time = (total_time-minutes)/60;
var hours:Number = total_time;
var secondparts:Array = String(seconds).split(”.”);
if (!secondparts[1]) {
secondparts[1] = “00″;
}
var s_seconds:String = formatNumber(secondparts[0])+”.”+formatNumber(secondparts[1]);
var s_minutes:String = formatNumber(minutes);
var s_hours:String = formatNumber(hours);
this.displayTime = s_hours+”:”+s_minutes+”:”+s_seconds;
}
return (this.displayTime);
}
private function formatNumber(number)
{
var string:String = String(number);
while (string.length < 2) {
string = ‘0′+string;
}
return(string);
}
}
This class is the brains of a stopwatch. If you save this into your classpath folder as StopWatch.as you can use it as an object on your timeline (or in other classes ).
Open up a new Flash Movie and put this code on your timeline:
watch = new StopWatch();
Now, anytime you use the variable ‘watch’ on this part of your movie, it will have all the methods and properties of your class.
To see what brand the watch is, run this code:
watch = new StopWatch();
trace(”my watch is a “+watch.brand);
At the start of the StopWatch class you see we have “var brand:String = ‘Timex’;”. Because we didn’t define it as a private var (yes, vars can be private just like functions!), we are able to access it from outside of the class.
The next few lines are our private vars. These keep track of all the timestamps the watch uses to get the nice readable display.
After our variable declarations, we have a function called StopWatch. This function has the same name as the class and it is called a constructor. Constructor functions automatically run whenever you make an instance of the class.
So, when we put “watch = new StopWatch();”, the StopWatch class runs the resetTimer() function, which sets the display time to “00:00:00.00″.
So we now have our var defs and our constructor, the rest of the class contains our methods. You will notice none of the functions have the word ’static’ in them.
Static functions could be thought of as global functions. No matter where in your movie you are, or what variable you are using, they run from the base class and will always behave the same.
Non-static functions are carbon copied for each instance. If you were to add “clock = new StopWatch();”, for example, it would be able to run without effecting any of the settings in ‘watch’.
Additionally, you can’t call non static functions directly through the class; StopWatch.startTimer() would do nothing.
So, lets try this code out on our timeline:
watch = new StopWatch();
trace(”I am starting my “+watch.brand+” watch”);
watch.startTimer();
Key.addListener(this);
onKeyDown = function() {
if (Key.getCode() == Key.SPACE) {
watch.stopTimer();
trace(”You stopped the watch at “+watch.readTimer());
trace(”restarting the timer…”);
watch.resetTimer();
watch.startTimer();
}
}
When you test your movie, an instance of the stopwatch class gets created, it tells you what brand the watch is, and it starts the timer.
When you hit space, the timer is stopped and you are told how much time has passed. Then the timer is reset and started again.
If we change the code to look like this:
watch = new StopWatch();
trace(”I am starting my “+watch.brand+” watch”);
watch.startTimer();
clock = new StopWatch();
trace(”I am starting my “+clock.brand+” clock”);
clock.startTimer();
Key.addListener(this);
onKeyDown = function() {
if (Key.getCode() == Key.SPACE) {
watch.stopTimer();
trace(”You stopped the watch at “+watch.readTimer());
trace(”restarting the watch…”);
watch.resetTimer();
watch.startTimer();
}
if (Key.getCode() == Key.SHIFT) {
clock.stopTimer();
trace(”You stopped the clock at “+clock.readTimer());
trace(”restarting the clock…”);
clock.resetTimer();
clock.startTimer();
}
}
Now we have the same setup, but we have added an instance of StopWatch called ‘clock’, and can control it with the SHIFT key. Testing this script will show you how object based classes use a common rule-set, but run independently.
Grab the sample file for this tutorial and you can see this class in a more practical application.
In the next lesson, we’ll get into extending classes!
Bookmark this page on Digg, Kinja, FURL, Redit & other sites
« Previous Entries
|