package
{
import
alternativa.engine3d.containers.*;
import
alternativa.engine3d.controllers.*;
import
alternativa.engine3d.core.Camera3D;
import
alternativa.engine3d.core.Clipping;
import
alternativa.engine3d.core.Debug;
import
alternativa.engine3d.core.MipMapping;
import
alternativa.engine3d.core.MouseEvent3D;
import
alternativa.engine3d.core.Object3D;
import
alternativa.engine3d.core.Sorting;
import
alternativa.engine3d.core.View;
import
alternativa.engine3d.materials.FillMaterial;
import
alternativa.engine3d.materials.TextureMaterial;
import
alternativa.engine3d.objects.Sprite3D;
import
alternativa.engine3d.primitives.Box;
import
alternativa.engine3d.primitives.Plane;
import
flash.display.BitmapData;
import
flash.display.BlendMode;
import
flash.display.Sprite;
import
flash.display.StageAlign;
import
flash.display.StageQuality;
import
flash.display.StageScaleMode;
import
flash.events.Event;
import
flash.events.KeyboardEvent;
import
flash.filters.GlowFilter;
import
flash.geom.ColorTransform;
import
flash.geom.Vector3D;
import
flash.sampler.NewObjectSample;
import
flash.system.Capabilities;
import
flash.ui.Keyboard;
[SWF(backgroundColor=
"#000000"
, frameRate=
"100"
, width=
"640"
, height=
"480"
)]
public
class
alternativa3dSokoban
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
;
// alternativa3d engine variables
private
var
camera:Camera3D;
private
var
controller:SimpleObjectController;
private
var
container:ConflictContainer;
private
var
frame:Sprite =
new
Sprite();
public
var
player:Box;
// cube primitive representing the player
public
var
cplayer:SimpleObjectController;
private
var
movingCrate:Box;
// cube primitive representing the moving crate
// some materials
private
var
wallMaterial:FillMaterial =
new
FillMaterial(
0x880088
,
1
,
1
);
private
var
crateMaterial:FillMaterial =
new
FillMaterial(
0xff0000
,
1
,
1
);
private
var
playerMaterial:FillMaterial =
new
FillMaterial(
0x0000ff
,
1
,
1
);
private
var
floorMaterial:FillMaterial =
new
FillMaterial(
0x888888
,
1
,
1
);
private
var
goalMaterial:FillMaterial =
new
FillMaterial(
0x00ff00
,
1
,
1
);
public
function
alternativa3dSokoban()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.BEST;
// Camera
camera =
new
Camera3D();
camera.view =
new
View(
800
,
600
);
addChild(camera.view);
// Camera controller
controller =
new
SimpleObjectController(stage, camera,
200
,
3
);
// Root object
container =
new
ConflictContainer();
container.resolveByAABB =
true
;
container.resolveByOOBB =
true
;
//Player controller
cplayer =
new
SimpleObjectController(stage, player,
3
);
var
box:Box;
/*
[[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]];
*/
// level construction
for
(
var
i:
uint
=
0
; i<
6
; i++)
{
for
(
var
j:
uint
=
0
; j<
8
; j++)
{
switch
(levels[i][j])
{
case
0
:
box =
new
Box(
3
,
1
,
3
,
1
,
1
);
box.setMaterialToAllFaces(floorMaterial);
box.x =
3
*j;
box.y =
2
;
box.z =
3
*i;
container.addChild(box);
break
;
case
1
:
box =
new
Box(
3
,
1
,
3
,
1
);
box.setMaterialToAllFaces(floorMaterial);
box.x =
3
*j;
box.y =
2
;
box.z =
3
*i;
container.addChild(box);
box =
new
Box(
3
,
3
,
3
,
1
);
box.setMaterialToAllFaces(wallMaterial);
box.x =
3
*j;
box.y =
4
;
box.z =
3
*i;
container.addChild(box);
break
;
case
2
:
box =
new
Box(
3
,
1
,
3
,
1
);
box.setMaterialToAllFaces(goalMaterial);
box.x =
3
*j;
box.y =
2
;
box.z =
3
*i;
container.addChild(box);
break
;
case
3
:
box =
new
Box(
3
,
1
,
3
,
1
);
box.setMaterialToAllFaces(floorMaterial);
box.x =
3
*j;
box.y =
2
;
box.z =
3
*i;
container.addChild(box);
box =
new
Box(
3
,
3
,
3
,
1
);
box.name =
"crate_"
+i+
"_"
+j;
box.setMaterialToAllFaces(crateMaterial);
box.x =
3
*j;
box.y =
4
;
box.z =
3
*i;
container.addChild(box);
break
;
case
4
:
box =
new
Box(
3
,
1
,
3
,
1
);
box.setMaterialToAllFaces(floorMaterial);
box.x =
3
*j;
box.y =
2
;
box.z =
3
*i;
container.addChild(box);
player =
new
Box(
3
,
3
,
3
,
1
);
player.setMaterialToAllFaces(playerMaterial);
player.x =
3
*j;
player.y =
4
;
player.z =
3
*i;
container.addChild(player);
playerCol=j;
playerRow=i;
break
;
}
}
}
// Adding
container.addChild(camera);
// View frame
addChild(frame);
onResize();
stage.addEventListener(Event.ENTER_FRAME, updateEvent);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDwn);
stage.addEventListener(Event.RESIZE, onResize);
}
private
function
onKeyDwn(e:KeyboardEvent):
void
{
if
(playerRotation==
0
&&playerMovement==
0
)
{
switch
(e.keyCode)
{
case
Keyboard.LEFT :
playerRotation=+
9
;
playerAngle+=
90
;
break
;
case
Keyboard.RIGHT :
playerRotation=-
9
;
playerAngle-=
90
;
break
;
case
Keyboard.UP :
movingCrate=
null
;
playerAngle=Math.round(player.rotationY*
180
/Math.PI)%
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;
dRow=
1
;
dCol=
0
;
break
;
case
180
:
dRow=
0
;
dCol=
1
;
break
;
case
270
:
//dRow=1;
dRow=-
1
;
dCol=
0
;
break
;
}
if
(levels[playerRow+dRow][playerCol+dCol]==
0
||levels[playerRow+dRow][playerCol+dCol]==
2
)
{
// the player can move
playerMovement=-
1
;
}
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=container.getChildByName(
"crate_"
+(playerRow+dRow)+
"_"
+(playerCol+dCol))
as
Box;
playerMovement=-
1
;
}
}
}
break
;
}
}
}
public
function
updateEvent(e:Event):
void
{
if
(playerRotation)
{
player.rotationY+=playerRotation*Math.PI/
180
;
if
(Math.abs(Math.round(player.rotationY*
180
/Math.PI))%
90
==
0
)
{
playerRotation=
0
;
}
}
if
(playerMovement)
{
switch
(playerAngle)
{
case
0
:
player.x += playerMovement;
break
;
case
90
:
player.z += -playerMovement;
break
;
case
180
:
player.x += -playerMovement;
break
;
case
270
:
player.z += playerMovement;
break
;
}
if
(movingCrate)
{
switch
(playerAngle)
{
case
0
:
movingCrate.x += playerMovement;
break
;
case
90
:
movingCrate.z += -playerMovement;
break
;
case
180
:
movingCrate.x += -playerMovement;
break
;
case
270
:
movingCrate.z += playerMovement;
break
;
}
}
// we need this to know if the player stopped on the destination tile
if
((playerAngle%
180
==
0
&&(Math.round(player.x*
10
)/
10
)%
3
==
0
)||(playerAngle%
180
!=
0
&&(Math.round(player.z*
10
)/
10
)%
3
==
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.setMaterialToAllFaces(goalMaterial);
}
else
{
movingCrate.setMaterialToAllFaces(crateMaterial);
}
levels[playerRow+dRow][playerCol+dCol]-=
3
;
movingCrate.name=
"crate_"
+(playerRow+
2
*dRow)+
"_"
+(playerCol+
2
*dCol);
}
playerCol+=dCol;
playerRow+=dRow;
}
}
onEnterFrame();
}
public
function
correct_camera_angles():
void
{
//set camera position
var
r:
Number
=
10
;
var
a:
Number
= -player.rotationY;
var
cx:
Number
= player.x+Math.cos(a)*r;
var
cz:
Number
= player.z+Math.sin(a)*r;
var
cy:
Number
= player.y+
10
;
controller.setObjectPosXYZ(cx,cy,cz);
//look at player box
controller.lookAtXYZ(player.x,player.y,player.z);
//correct camera angles
var
cprotY:
Number
= player.rotationY;
cprotY=Math.round(player.rotationY*
180
/Math.PI)%
360
;
if
(cprotY<
0
)
{
cprotY+=
360
;
}
if
(cprotY>
180
)
{
camera.rotationX = camera.rotationX + (
90
*Math.PI/
180
)*Math.sin((cprotY%
180
)*Math.PI/
180
);
}
camera.rotationY = camera.rotationY+
90
*Math.PI/
180
-player.rotationY;
}
public
function
onEnterFrame(e:Event =
null
):
void
{
controller.update();
correct_camera_angles();
cplayer.update();
camera.render();
}
public
function
onResize(e:Event =
null
):
void
{
//here you can add border size for view
var
pd:
Number
=
0
;
camera.view.width = stage.stageWidth - pd*
2
;
camera.view.height = stage.stageHeight - pd*
2
;
camera.view.x = pd;
camera.view.y = pd;
frame.graphics.clear();
frame.graphics.beginFill(
0x000000
,
0.75
);
frame.graphics.drawRect(
0
,
0
, stage.stageWidth, stage.stageHeight);
frame.graphics.lineStyle(
0
,
0x7F7F7F
);
frame.graphics.drawRect(pd, pd, camera.view.width, camera.view.height);
frame.graphics.endFill();
}
}
}