Do you like my tutorials?

Then consider supporting me on Ko-fi

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

As promised, after the Flash 3D Sokoban prototype with Flare3D, here comes the Away3D version.

The code needs to be optimized and above all I want to make Away3D and Flare3D codes as similar as possible so I will be able to compare them and show you the differences.

This is the Away3D source code:

package {
	// required flash classes
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.geom.Vector3D;
	// required awayed classes
	import away3d.containers.*;
	import away3d.primitives.*;
	import away3d.cameras.*;
	import away3d.core.render.*;
	import away3d.materials.*;
	public class Main extends Sprite {
		// 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;
		// away3d variables
		private var view:View3D;// View3D represent the canvas
		private var theCamera:SpringCam;// custom camera to manage 1st or 3rd person camera
		private var player:Cube;// the player
		private var movingCrate:Cube;// the crate which will be pushed
		// some materials
		private var floorMaterial:WireColorMaterial=new WireColorMaterial(0x888888,{wireColor:0x484848});
		private var wallMaterial:WireColorMaterial=new WireColorMaterial(0x880088,{wireColor:0x480048});
		private var goalMaterial:WireColorMaterial=new WireColorMaterial(0x00ff00,{wireColor:0x00bb00});
		private var crateMaterial:WireColorMaterial=new WireColorMaterial(0xff0000,{wireColor:0xbb0000});
		private var playerMaterial:WireColorMaterial=new WireColorMaterial(0x0000ff,{wireColor:0x0000bb});
		function Main() {
			// scene setup
			view=new View3D({x:320,y:240});
			addChild(view);
			theCamera= new SpringCam();
			view.camera=theCamera;
			var cube=Cube;
			// level construction
			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({material:floorMaterial,depth:50,width:50,height:10,x:50*i,y:-25,z:50*j});
							view.scene.addChild(cube);
							break;
						case 1 :
							cube=new Cube({material:floorMaterial,depth:50,width:50,height:10,x:50*i,y:-25,z:50*j});
							view.scene.addChild(cube);
							cube=new Cube({material:wallMaterial,depth:50,width:50,height:50,x:50*i,y:0,z:50*j});
							view.scene.addChild(cube);
							break;
						case 2 :
							cube=new Cube({material:goalMaterial,depth:50,width:50,height:10,x:50*i,y:-25,z:50*j});
							view.scene.addChild(cube);
							break;
						case 3 :
							cube=new Cube({material:floorMaterial,depth:50,width:50,height:10,x:50*i,y:-25,z:50*j});
							view.scene.addChild(cube);
							cube=new Cube({material:crateMaterial,depth:50,width:50,height:50,x:50*i,y:0,z:50*j});
							cube.name="crate_"+i+"_"+j;
							view.scene.addChild(cube);
							break;
						case 4 :
							cube=new Cube({material:floorMaterial,depth:50,width:50,height:10,x:50*i,y:-25,z:50*j});
							view.scene.addChild(cube);
							player=new Cube({material:playerMaterial,depth:50,width:50,height:50,x:50*i,y:0,z:50*j});
							view.scene.addChild(player);
							playerCol=j;
							playerRow=i;
							theCamera.target=player;
							theCamera.positionOffset=new Vector3D(0,500,150);
							theCamera.lookOffset=new Vector3D(0,0,-100);
							theCamera.damping=20;
							break;
					}
				}
			}
			// listeners
			addEventListener(Event.ENTER_FRAME,onEnterFrm);
			stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDwn);
		}
		private function onKeyDwn(e:KeyboardEvent):void {
			if (playerRotation==0&&playerMovement==0) {
				switch (e.keyCode) {
					case 37 :
						playerRotation=-9;
						break;
					case 38 :
						var playerAngle:Number=Math.round(player.rotationY)%360;
						if (playerAngle<0) {
							playerAngle+=360;
						}
						// 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 (levels[playerRow+dRow][playerCol+dCol]==0||levels[playerRow+dRow][playerCol+dCol]==2) {
							// the player can move
							playerMovement=-5;
						} 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=view.scene.getChildByName("crate_"+(playerRow+dRow)+"_"+(playerCol+dCol))as Cube;
									playerMovement=-5;
								}
							}
						}
						break;
					case 39 :
						playerRotation=9;
						break;
				}
			}
		}
		private function onEnterFrm(e:Event):void {
			var playerAngle:Number;
			if (playerRotation) {
				// this is how away3d rotates an object
				player.rotationY+=playerRotation;
				playerAngle=Math.round(player.rotationY);
				if (playerAngle%90==0) {
					playerRotation=0;
				}
			}
			if (playerMovement) {
				// this is how away3d moves an object
				player.moveForward(playerMovement);
				if (movingCrate) {
					playerAngle=Math.round(player.rotationY)%360;
					if (playerAngle<0) {
						playerAngle+=360;
					}
					switch (playerAngle) {
						case 0 :
							movingCrate.moveForward(playerMovement);
							break;
						case 90 :
							movingCrate.moveRight(playerMovement);
							break;
						case 180 :
							movingCrate.moveBackward(playerMovement);
							break;
						case 270 :
							movingCrate.moveLeft(playerMovement);
							break;
					}
				}
				// we need this to know if the player stopped on the destination tile
				if (Math.round(player.rotationY)%180==0) {
					if (Math.round(player.z)%50==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) {
								// changing materials on the fly
								movingCrate.material=goalMaterial;
							} else {
								movingCrate.material=crateMaterial;
							}
							levels[playerRow+dRow][playerCol+dCol]-=3;
							movingCrate.name="crate_"+(playerRow+2*dRow)+"_"+(playerCol+2*dCol);
							movingCrate=null;
						}
						playerRow+=dRow;
						playerCol+=dCol;
					}
				} else {
					if (Math.round(player.x)%50==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) {
								movingCrate.material=goalMaterial;
							} else {
								movingCrate.material=crateMaterial;
							}
							levels[playerRow+dRow][playerCol+dCol]-=3;
							movingCrate.name="crate_"+(playerRow+2*dRow)+"_"+(playerCol+2*dCol);
							movingCrate=null;
						}
						playerRow+=dRow;
						playerCol+=dCol;
					}
				}
			}
			// camera management
			theCamera.view;
			view.render();

		}
	}
}

and this is the result:

rotate the player with LEFT and RIGHT arrow keys, and move it with UP.

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.