Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Sokoban game, 3D, Actionscript 3, Flash and Game development.

The Flash 3D Sokoban prototype with Flare3D is growing, and this time I applied some textures to game elements.

The following script, which will be explained after I’ll made the same thing with Away3D, show three interesting Flare3D features:

* Applying textures on a Cube.
* Applying textures only on some faces of a Cube.
* Applying different materials to the same Cube, then apply filters on them

here it is the source code:

package {
	// required flash classes
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.filters.*
	// required flare3d classes
	import flare.basic.*;
	import flare.materials.*;
	import flare.primitives.*;
	import flare.system.*;
	import flare.utils.*;
	import flare.core.*;
	public class Main extends Sprite {
		private const CUBESIZE:Number=10;
		// sokobal demo level and player position
		private var levels:Array=[[1,1,1,1,0,0,0,0],[1,0,0,1,1,1,1,1],[1,0,2,0,0,3,0,1],[1,0,3,0,0,2,4,1],[1,1,1,0,0,1,1,1],[0,0,1,1,1,1,0,0]];
		private var playerCol:uint;
		private var playerRow:uint;
		private var playerRotation:Number=0;
		private var playerAngle:Number=0;
		private var playerMovement:Number=0;
		private var dRow:int;
		private var dCol:int;
		// flare3d variables
		private var scene:Scene3D;// scene3D is the canvas of the flare3d environment
		private var player:Cube;// cube primitive representing the player
		private var movingCrate:Cube;// cube primitive representing the moving crate
		// bitmap datas
		private var crateBitmap:BitmapData=new BitmapData(256,256);
		private var cratetopBitmap:BitmapData=new BitmapData(256,256);
		private var floorBitmap:BitmapData=new BitmapData(256,256);
		private var wallBitmap:BitmapData=new BitmapData(256,256);
		// textures
		private var crateTexture:Texture3D;
		private var cratetopTexture:Texture3D;
		private var floorTexture:Texture3D=new Texture3D("",floorBitmap);
		private var wallTexture:Texture3D;
		// materials
		private var floorMaterial:TextureMaterial=new TextureMaterial("",floorTexture);
		private var goalMaterial:ShadedColorMaterial=new ShadedColorMaterial("",0x000000,0x00ff00);
		private var playerMaterial:ShadedColorMaterial=new ShadedColorMaterial("",0x000000,0x0000ff);
		// multi materials
		private var wallMaterial:MultiMaterial = new MultiMaterial();
		private var crateMaterial:MultiMaterial = new MultiMaterial();
		private var cratetopMaterial:MultiMaterial = new MultiMaterial();
		public function Main() {
			floorBitmap.draw(new floorPic(256,256));
			//
			wallBitmap.draw(new wallPic(256,256));
			wallTexture=new Texture3D("",wallBitmap);
			wallMaterial.setTextureChannel(0,wallTexture);
			wallMaterial.setShadedColorChannel(1);
			wallMaterial.setBlendMode(BlendMode.MULTIPLY);
			//
			crateBitmap.draw(new cratePic(256,256));
			crateTexture=new Texture3D("",crateBitmap);
			crateMaterial.setTextureChannel(0,crateTexture);
			crateMaterial.setShadedColorChannel(1);
			crateMaterial.setBlendMode(BlendMode.MULTIPLY);
			//
			cratetopBitmap.draw(new cratetopPic(256,256));
			cratetopTexture=new Texture3D("",cratetopBitmap);
			cratetopMaterial.setTextureChannel(0,cratetopTexture);
			cratetopMaterial.setShadedColorChannel(1);
			cratetopMaterial.setBlendMode(BlendMode.MULTIPLY);
			// scene setup
			scene=new Viewer3D(this,"",0,0);
			// level construction
			var cube:Cube;
			for (var i:uint=0; i<6; i++) {
				for (var j:uint=0; j<8; j++) {
					switch (levels[i][j]) {
						case 0 :
							cube=new Cube("",CUBESIZE,CUBESIZE/2,CUBESIZE,1,floorMaterial);
							cube.setPosition(CUBESIZE*j,0,CUBESIZE*i);
							scene.addChild(cube);
							break;
						case 1 :
							cube=new Cube("",CUBESIZE,CUBESIZE/2,CUBESIZE,1,floorMaterial);
							cube.setPosition(CUBESIZE*j,0,CUBESIZE*i);
							scene.addChild(cube);
							cube=new Cube("",CUBESIZE,CUBESIZE,CUBESIZE,1,wallMaterial);
							cube.setPosition(CUBESIZE*j,CUBESIZE*3/4,CUBESIZE*i);
							scene.addChild(cube);
							break;
						case 2 :
							cube=new Cube("",CUBESIZE,CUBESIZE/2,CUBESIZE,1,goalMaterial);
							cube.setPosition(CUBESIZE*j,0,CUBESIZE*i);
							scene.addChild(cube);
							break;
						case 3 :
							cube=new Cube("",CUBESIZE,CUBESIZE/2,CUBESIZE,1,floorMaterial);
							cube.setPosition(CUBESIZE*j,0,CUBESIZE*i);
							scene.addChild(cube);
							cube=new Cube("crate_"+i+"_"+j,CUBESIZE,CUBESIZE,CUBESIZE,1,crateMaterial);
							cube.setPosition(CUBESIZE*j,CUBESIZE*3/4,CUBESIZE*i);
							scene.addChild(cube);
							// top of the crate
							var polyVec:Vector.=cube.polys;
							polyVec[4].material=cratetopMaterial;
							polyVec[5].material=cratetopMaterial;
							break;
						case 4 :
							cube=new Cube("",CUBESIZE,CUBESIZE/2,CUBESIZE,1,floorMaterial);
							cube.setPosition(CUBESIZE*j,0,CUBESIZE*i);
							scene.addChild(cube);
							player=new Cube("player",CUBESIZE,CUBESIZE,CUBESIZE,1,playerMaterial);
							player.setPosition(CUBESIZE*j,CUBESIZE*3/4,CUBESIZE*i);
							scene.addChild(player);
							playerCol=j;
							playerRow=i;
							break;
					}
				}
			}
			// listener to handle the 3D engine
			scene.addEventListener(Scene3D.UPDATE_EVENT,updateEvent);
		}
		private function updateEvent(e:Event):void {
			var currentRotation:Number=0;
			// we have to determine the difference between current row and column
			// and the new row and column according to player heading
			switch (playerAngle) {
				case 0 :
					dRow=0;
					dCol=-1;
					break;
				case 90 :
					dRow=1;
					dCol=0;
					break;
				case 180 :
					dRow=0;
					dCol=1;
					break;
				case 270 :
					dRow=-1;
					dCol=0;
					break;
			}
			if (playerRotation==0&&playerMovement==0) {
				// look how does flare3D listens for key pressed
				if (Input3D.keyDown(Input3D.RIGHT)) {
					playerRotation=9;
					playerAngle+=90;
				}
				if (Input3D.keyDown(Input3D.LEFT)) {
					playerRotation=-9;
					playerAngle-=90;
				}
				if (Input3D.keyDown(Input3D.UP)) {
					movingCrate=null;
					if (levels[playerRow+dRow][playerCol+dCol]==0||levels[playerRow+dRow][playerCol+dCol]==2) {
						// the player can move
						playerMovement=- CUBESIZE/10;
					} else {
						if (levels[playerRow+dRow][playerCol+dCol]==3||levels[playerRow+dRow][playerCol+dCol]==5) {
							if (levels[playerRow+2*dRow][playerCol+2*dCol]==0||levels[playerRow+2*dRow][playerCol+2*dCol]==2) {
								// the player can move and can push a crate
								movingCrate=scene.getChildByName("crate_"+(playerRow+dRow)+"_"+(playerCol+dCol))as Cube;
								playerMovement=- CUBESIZE/10;
							}
						}
					}
				}
				if (playerAngle<0) {
					playerAngle+=360;
				}
				if (playerAngle==360) {
					playerAngle=0;
				}
			} else {
				if (playerRotation) {
					// this is how flare3D rotates an object
					player.rotateY(playerRotation);
					if (Math.abs(Math.round(player.getRotation().y))%90==0) {
						playerRotation=0;
					}
				}
				if (playerMovement) {
					// this is how flare3D moves an object
					player.translateX(playerMovement);
					if (movingCrate) {
						switch (playerAngle) {
							case 0 :
								movingCrate.translateX(playerMovement);
								break;
							case 90 :
								movingCrate.translateZ(-playerMovement);
								break;
							case 180 :
								movingCrate.translateX(-playerMovement);
								break;
							case 270 :
								movingCrate.translateZ(playerMovement);
								break;
						}
					}
					// we need this to know if the player stopped on the destination tile
					if ((playerAngle%180==0&&(Math.round(player.getPosition().x*10)/10)%CUBESIZE==0)||(playerAngle%180!=0&&(Math.round(player.getPosition().z*10)/10)%CUBESIZE==0)) {
						playerMovement=0;
						levels[playerRow+dRow][playerCol+dCol]+=4;
						levels[playerRow][playerCol]-=4;
						if (movingCrate) {
							levels[playerRow+2*dRow][playerCol+2*dCol]+=3;
							if (levels[playerRow+2*dRow][playerCol+2*dCol]==5) {
								// crate on goal
							} else {
								// crate not on goal
							}
							levels[playerRow+dRow][playerCol+dCol]-=3;
							movingCrate.name="crate_"+(playerRow+2*dRow)+"_"+(playerCol+2*dCol);
						}
						playerCol+=dCol;
						playerRow+=dRow;
					}
				}
			}
			// camera management
			Pivot3DUtils.setPositionWithReference(scene.camera,CUBESIZE*3,CUBESIZE*6,0,player,0.1);
			Pivot3DUtils.lookAtWithReference(scene.camera,-CUBESIZE*2,-CUBESIZE*3,0,player);
		}
	}
}

and this is the result:

Move use LEFT, RIGHT and UP arrow keys to move the player. As you can see, the player and the crate goals aren't textured, moreover the crates do not change texture when over the crate goals. This happens because I plan to add new features to such elements.

Download the source code.

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