Talking about Rebuild Chile game, Actionscript 3, Flash and Game development.
Time to see the feature that will allow you to complete a level: removing debris.
Debris can be removed in two ways:
1) Pushing them off the stage through an hole in the border walls
2) Calling an helicopter and removing them on the fly
Obviously pro players will prefer the first option.
First, we need two new tile types: border wall and hole in border wall. The border wall is unwalkable, while the hole in the border wall is still unwalkable but debris can be pushed on it. Once on this tile, the debris disappear.
Also, pressing “H” you can call an helicopter, select a debris with arrow keys and removing pressin SPACEBAR or trying to make it without the helicopter pressing “H” again.
This is the complete, fully commented code:
package {
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.Event;
public class rebuild extends Sprite {
// array to store the map
public var map:Array=new Array();
// array to store bulldozer position
public var bulldozer_pos:Array= new Array();
// tree movieclip
public var tree:tree_mc;
// debris movieclip
public var debris:debris_mc;
// bulldozer movieclip
public var bulldozer:bulldozer_mc;
// external wall movieclip
public var ext_wall:ext_wall_mc;
// helicopter movieclip
public var heli:heli_mc;
// variable to store the last key pressed
public var key_pressed:int=0;
// flag to determine if the bulldozer is moving or not
public var bulldozer_is_moving:Boolean=false;
// bulldozer x and y direction
public var bulldozer_x_dir:int=0;
public var bulldozer_y_dir:int=0;
// variable to determine which debris the helicopter is going to pick up
public var heli_on_debris:int=1;
// number of debris left to clear the screen
public var debris_left:int=0;
// variable to store the name of the debris we will move
public var debris_to_move:String="";
// main function
public function rebuild():void {
// initializing the map
// 0: empty space (walkable)
// 1: tree (unmovable object)
// 2: debris (movable object)
// 9: external wall (unmovable object)
// 10: hole in external wall (unwalkable, but debris can be pushed on it)
map=[[9,9,9,9,9,9,9,10,9,9,9],[9,0,0,2,0,0,0,0,0,0,9],[9,0,0,0,0,0,0,0,0,0,9],[9,1,1,1,1,1,0,1,0,0,9],[9,1,0,0,2,0,0,1,0,0,9],[9,1,0,0,0,0,0,1,0,0,9],[9,1,1,1,1,1,1,1,0,0,9],[9,0,0,0,0,2,0,0,0,0,9],[9,0,0,0,0,0,0,0,0,0,9],[9,0,0,0,0,0,0,0,0,0,9],[9,9,9,9,9,9,9,9,9,9,9]];
// initializing bulldozer starting position
bulldozer_pos=[7,3];
// calling main functions
draw_map();
place_bulldozer();
// adding listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN, on_key_down);
stage.addEventListener(KeyboardEvent.KEY_UP, on_key_up);
addEventListener(Event.ENTER_FRAME,on_enter_frame);
}
// function to draw the map
public function draw_map():void {
// looping though all map. What's that "11"? it's the map width/height
for (var i:int=0; i<11; i++) {
for (var j:int=0; j<11; j++) {
switch (map[j][i]) {
// I found a tree
case 1 :
// placing the tree
tree = new tree_mc();
// What's that "50"? it's the tile width/height
// And the "25"? It's half a tile width/height
// the whole game area is shifted by half a tile up and left
// so that the external wall is only displayed at a half
tree.x=i*50-25;
tree.y=j*50-25;
addChild(tree);
break;
case 2 :
// placing a debris, same way as the tree
debris=new debris_mc();
debris.name="debris_"+j+"_"+i;
debris.x=i*50-25;
debris.y=j*50-25;
addChild(debris);
debris_left++;
break;
case 9 :
// placing an external wall, same way as the tree
ext_wall = new ext_wall_mc();
ext_wall.x=i*50-25;
ext_wall.y=j*50-25;
addChild(ext_wall);
break;
}
}
}
}
// function to place the bulldozer, in the same way as the tree
public function place_bulldozer():void {
bulldozer = new bulldozer_mc();
bulldozer.x=50*(bulldozer_pos[1])-25;
bulldozer.y=50*(bulldozer_pos[0])-25;
addChild(bulldozer);
}
// function to be executed every time a key is down
public function on_key_down(e:KeyboardEvent):void {
// storing key_pressed variable the keyCode of the latest key pressed
key_pressed=e.keyCode;
}
// function to be executed every time a key is released
public function on_key_up(e:KeyboardEvent):void {
// if we are releasing the same key we pressed last time, then reset key_pressed variable
// this way we allow to press only one key at time
if (e.keyCode==key_pressed) {
key_pressed=0;
}
}
// function to be executed at every frame
public function on_enter_frame(e:Event):void {
// I am checking for keyboard input only if the bulldozer is not already moving
// and there is at least one debris to remove
if (! bulldozer_is_moving&&debris_left>0) {
switch (key_pressed) {
// right
case 37 :
walk(-1,0);
break;
case 38 :
// up
walk(0,-1);
break;
case 39 :
//left
walk(1,0);
break;
case 40 :
//down
walk(0,1);
break;
case 72 :
// "H", calling the helicopter
// resetting key_pressed
key_pressed=0;
// if the helicopter in not on stage...
if (heli==null) {
// place the helicopter on the first debris and don't remove the debris
heli=new heli_mc();
addChild(heli);
place_heli(heli_on_debris,false);
} else {
// if the helicopter is already on stage, remove it and set the debris
// to be picked up as the first one
removeChild(heli);
heli=null;
heli_on_debris=1;
}
break;
case 32 :
// SPACEBAR, to remove selected debris
// if the helicopter is on stage...
if (heli!=null) {
// remove the debris under the helicopter
place_heli(heli_on_debris,true);
// remove the helicopter itself
removeChild(heli);
heli=null;
// set the debris to be picked up as the first one
heli_on_debris=1;
}
break;
}
}
// if the bulldozer is moving...
if (bulldozer_is_moving) {
// move the bulldozer one more step. One step = 10 pixels = 1/5 a tile
bulldozer.x+=10*bulldozer_x_dir;
bulldozer.y+=10*bulldozer_y_dir;
// if there is a debris to move...
if (debris_to_move!="") {
// move the debris one more step
with (getChildByName(debris_to_move)) {
x+=10*bulldozer_x_dir;
y+=10*bulldozer_y_dir;
}
}
// if the bulldozer is completely on a tile...
if ((bulldozer.x+bulldozer.y)%50==0) {
// stop moving the bulldozer
bulldozer_is_moving=false;
// update bulldozer position
bulldozer_pos[0]+=bulldozer_y_dir;
bulldozer_pos[1]+=bulldozer_x_dir;
// if there is a debris to move...
if (debris_to_move!="") {
// set the tile occupied by the debris BEFORE it moved to "0" (walkable)
map[bulldozer_pos[0]][bulldozer_pos[1]]=0;
// if the debris is on the map tile marked as "10" (hole in external wall)...
if (map[bulldozer_pos[0]+bulldozer_y_dir][bulldozer_pos[1]+bulldozer_x_dir]==10) {
// remove the debris
removeChild(getChildByName(debris_to_move));
// decrease number of remaining debris
debris_left--;
} else {
// if it's not on a "10" map, then simply update debris name and the map
getChildByName(debris_to_move).name="debris_"+(bulldozer_pos[0]+1*bulldozer_y_dir)+"_"+(bulldozer_pos[1]+1*bulldozer_x_dir);
map[bulldozer_pos[0]+bulldozer_y_dir][bulldozer_pos[1]+bulldozer_x_dir]=2;
}
// set the debris_to_move variable as "no debris to move"
debris_to_move="";
}
}
}
}
// Function to move the bulldozer or the helicopter. px and py are the amount of tiles we want to move the bulldozer
// Possible values passed:
// 1,0: right
// -1,0: left
// 0,1: down
// 0,-1: up
public function walk(px:int,py:int):void {
// if the helicopter is not on stage...
if (heli==null) {
// setting a "moved" flag as "false". It says the bulldozer did not move
var moved:Boolean=false;
// if the tile that the bulldozer should walk on is walkable...
if (map[bulldozer_pos[0]+py][bulldozer_pos[1]+px]==0) {
// the bulldozer moved
moved=true;
} else {
// else, if the tile that the bulldozer should walk on is occupied by a debris and
// the next one is a walkable tile or an hole in external wall...
if (map[bulldozer_pos[0]+py][bulldozer_pos[1]+px]==2&&(map[bulldozer_pos[0]+2*py][bulldozer_pos[1]+2*px]==0||map[bulldozer_pos[0]+2*py][bulldozer_pos[1]+2*px]==10)) {
// set which debris has to move
debris_to_move=getChildByName("debris_"+(bulldozer_pos[0]+py)+"_"+(bulldozer_pos[1]+px)).name;
// the bulldozer moved
moved=true;
}
}
// if the bulldozer moved...
if (moved) {
// setting variables to let it move and the direction it has to move
bulldozer_is_moving=true;
bulldozer_x_dir=px;
bulldozer_y_dir=py;
}
} else {
// if the helicopter is on stage...
// reset key_pressed variable
key_pressed=0;
// increase heli_on_debris value by 1 if the direction is "down" or "right"
// decrease it by 1 if the direction is "left" or "up"
heli_on_debris+=px+py;
// checking if we completely cycled through debris
if (heli_on_debris<1) {
heli_on_debris=debris_left;
}
if (heli_on_debris>debris_left) {
heli_on_debris=1;
}
// place the helicopter on the selected debris and don't remove it
place_heli(heli_on_debris,false);
}
}
// function to place the helicopter on a debris and eventually remove it
// n: n-th debris, starting from the upper left corner
// del: if true, remove the debris
public function place_heli(n:int,del:Boolean):void {
// debris already found on the map
var debris_found=0;
// scanning the map...
for (var i:int=1; i<10; i++) {
for (var j:int=1; j<10; j++) {
// if I found a debris...
if (map[i][j]==2) {
// increasing the number of debris I found
debris_found++;
// if I am on the right debris...
if (debris_found==n) {
// place the helicopter on the debris
heli.x=j*50-25;
heli.y=i*50-25;
// if I have to remove the debris...
if (del) {
// update the map
map[i][j]=0;
// remove the debris
removeChild(getChildByName("debris_"+i+"_"+j));
// update remaining debris
debris_left--;
}
// exit the cycle
j=10;
i=10;
}
}
}
}
}
}
}
And this is the result:
Play just like you were playing the original game.
I enjoyed the making of this prototype so much that I am planning a game based on it, maybe with more options such as more ways to remove debris, and a different theme.
Any idea?
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.