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.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.