Flash 3D Sokoban prototype with Flare3D – Textures

Read all posts about "" game

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.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers