snake on a cube
/**
* Copyright zob ( http://wonderfl.net/user/zob )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1uPa
*/
// forked from zonnbe's 蛇cube
package
{
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Debug;
import alternativ7.engine3d.core.MipMapping;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.core.Sorting;
import alternativ7.engine3d.core.View;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.objects.Sprite3D;
import alternativ7.engine3d.primitives.Box;
import flash.display.*;
import flash.filters.*;
import flash.events.*;
import flash.net.*;
import flash.utils.*;
import flash.text.*;
import flash.system.*;
import flash.ui.*;
import flash.geom.Point;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import flash.geom.Rectangle;
import net.wonderfl.score.basic.*;
[SWF(width=465,height=465,backgroundColor=0xDDDDDD,frameRate=60)]
public class snake3dALT3D extends Sprite
{
private var camera:Camera3D;
private var controller:SimpleObjectController;
public var cube:Box;
private var SNAKE_DIRECTION:int = 0; // default UP
private var key_up:Boolean = false;
private var key_down:Boolean = false;
private var key_left:Boolean = false;
private var key_right:Boolean = false;
private var MOVE_UP:int = 0;
private var MOVE_DOWN:int = 1;
private var MOVE_RIGHT:int = 2;
private var MOVE_LEFT:int = 3;
private var FRONT:int = 0;
private var BACK:int = 1;
private var LEFT:int = 2;
private var RIGHT:int = 3;
private var TOP:int = 4;
private var BOTTOM:int = 5;
private var FACES:Array = ["front", "back", "left", "right", "top", "bottom"];
private var CUBE_SIZE:int = 100;
private var GRID_WIDTH:int = 25;
private var GRID_MAX:int = GRID_WIDTH / 2 + 1;
private var GRID_SIZE:int = CUBE_SIZE / GRID_WIDTH;
private var snake_head:Dot = new Dot(0, 0, -GRID_MAX);
private var snake_prev:Dot = new Dot(0, 0, -GRID_MAX);
private var snake:Array = new Array();
private var SNAKE_MAX_LENGTH:int = 50;
private var to_up:Dot = new Dot(0, -1, 0);
private var to_down:Dot = new Dot(0, 1, 0);
private var to_left:Dot = new Dot(-1, 0, 0);
private var to_right:Dot = new Dot(1, 0, 0);
private var bitmapData:BitmapData;
private var bitmapDatas:Array = new Array();
private var pause_:Boolean = false;
private var counter:int = 0;
private var speed:int = 3;
private var recover_speed:Number = 0.33;
private var matrix:Matrix3D = new Matrix3D();
private var matrix2:Matrix3D = new Matrix3D();
private var matrix3:Matrix3D = new Matrix3D();
private var BITMAP_GRID_SIZE:int = 0;
private var ri:Array;
private var a:int, b:int;
private var iwidth:int, iheight:int, hwidth:int, hheight:int;
private var size:int;
private var ripplemap:Array;
private var oldind:Array;
private var newind:Array;
private var mapind:Array;
private var riprad:int;
private var timers:Array = new Array();
private var defaced:Dot = new Dot();
private var UP_temp:Dot = new Dot();
private var RIGHT_temp:Dot = new Dot();
private var LEFT_temp:Dot = new Dot();
private var mimi_UP:Dot = new Dot();
private var mimi_RIGHT:Dot = new Dot();
private var mimi_LEFT:Dot = new Dot();
private var excex:Dot = new Dot();
private var temp_dot:Dot = new Dot();
private var max_up:Dot = new Dot();
private var max_left:Dot = new Dot();
private var max_right:Dot = new Dot();
private var vUP:Dot = new Dot(0,-1,0);
private var BACK_BONE:Dot = new Dot();
private var FRONT_BONE:Dot = new Dot(0, 0, GRID_MAX);
private var DIF:Number = 0;
private var crossproduct:Dot = new Dot();
private var bait:Dot = new Dot();
private var mappers:Array = new Array();
private var gameover_txt:TextField = new TextField();
private var score_txt:TextField = new TextField();
private var clone_point:Vector3D = new Vector3D();
private var form_score:BasicScoreForm;
private var form_ranking:BasicScoreRecordViewer;
public function snake3dALT3D()
{
var picUrl:URLRequest = new URLRequest();
picUrl.url = "http://assets.wonderfl.net/images/related_images/1/15/152b/152bd818130009eb38713b51b6b785d26038b1da";
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, init3D);
loader.load(picUrl, new LoaderContext(true));
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKey_Down);
}
private function init3D(e:Event):void
{
var loader:Loader = Loader(e.target.loader);
var bitmap:Bitmap = Bitmap(loader.content);
bitmapData = bitmap.bitmapData;
camera = new Camera3D();
camera.view = new View(stage.stageWidth, stage.stageHeight);
addChild(camera.view);
camera.z = -300;
controller = new SimpleObjectController(stage, camera, 200, 3);
var container:ConflictContainer = new ConflictContainer();
camera.view.interactive = false;
addChild(camera.diagram);
var tf:TextFormat = new TextFormat("Arial", 43, 0xFFFFFF);
gameover_txt.defaultTextFormat = tf;
gameover_txt.autoSize = "left";
gameover_txt.text = "Game Over";
var stf:TextFormat = new TextFormat("Arial", 14, 0x6598FF);
score_txt.defaultTextFormat = stf;
score_txt.autoSize = "left";
score_txt.text = "0";
addChild(score_txt);
iwidth = bitmap.width;
iheight = bitmap.height;
BITMAP_GRID_SIZE = iwidth / GRID_WIDTH;
CUBE_SIZE = iwidth;
GRID_SIZE = CUBE_SIZE / GRID_WIDTH;
hwidth = iwidth>>1;
hheight = iheight>>1;
riprad=3;
size = iwidth * (iheight+2) * 2;
ripplemap = new Array();
ri = new Array();
oldind = new Array();
newind = new Array();
mapind = new Array();
var movieMaterials:Array = new Array();
var bitmaps:Array = new Array();
var movieClip:MovieClip;
var i:int = 0;
var j:int = 0;
var k:int = 0;
for(i = 0; i < 6; i++)
{
bitmapDatas.push(new BitmapData(iwidth, iwidth));
movieMaterials.push(new TextureMaterial(bitmapDatas[i]));
mappers.push(new Array());
for(j = 0; j < GRID_WIDTH; j++)
{
mappers[i].push(new Array());
for(k = 0; k < GRID_WIDTH; k++)
{
mappers[i][j].push(Boolean(false));
}
}
}
cube = new Box(100, 100, 100, 3, 3, 3, false, false, movieMaterials[LEFT], movieMaterials[RIGHT], movieMaterials[BACK], movieMaterials[FRONT], movieMaterials[BOTTOM], movieMaterials[TOP]);
container.addChild(camera);
container.addChild(cube);
give_me_bait();
matrix.identity();
matrix2.identity();
matrix3.identity();
stage.addEventListener( Event.ENTER_FRAME, loop );
}
private function loop(event:Event):void
{
processing();
paint();
camera.render();
}
private function paint():void
{
var i:int = 0;
for(i=0; i<6; i++)
{
//cube_faces[i].graphics.clear();
bitmapDatas[i].fillRect(bitmapDatas[i].rect, 0xFFFFFFFF);
}
for(i=0; i<snake.length; i++)
S_draw_body(snake[i]);
draw_bait();
}
private function processing():void
{
if(!pause_)
{
if(counter%speed==0)
{
if(key_up)
{
if(SNAKE_DIRECTION != MOVE_DOWN) SNAKE_DIRECTION = MOVE_UP;
} else if(key_down)
{
if(SNAKE_DIRECTION != MOVE_UP) SNAKE_DIRECTION = MOVE_DOWN;
} else if(key_left)
{
if(SNAKE_DIRECTION != MOVE_RIGHT) SNAKE_DIRECTION = MOVE_LEFT;
} else if(key_right)
{
if(SNAKE_DIRECTION != MOVE_LEFT) SNAKE_DIRECTION = MOVE_RIGHT;
}
false_all();
snake_prev.val_(snake_head);
defaced.val_(snake_head).add_(excex.val_(snake_head).excex_(GRID_MAX).div_(-GRID_MAX));
if(temp_dot.val_(defaced).add_(curr_direction()).has_(GRID_MAX))
{
snake_head.val_(defaced).add_(curr_direction());
update_directions(curr_righthand(), -Math.PI/2);
}
else
snake_head.add_(curr_direction());
snake.push(snake_head.clone());
var check_f:Dot = check_face(snake_head);
check_f.add_(new Dot(GRID_MAX-1,GRID_MAX-1,0));
if(mappers[int(check_f.z)][int(check_f.x)][int(check_f.y)])
{
speed = -9999;
gameOver();
}
else
mappers[int(check_f.z)][int(check_f.x)][int(check_f.y)] = true;
if(check_f.equal(bait))
{
score_txt.text = ""+ (parseInt(score_txt.text) + 100);
SNAKE_MAX_LENGTH+=3;
give_me_bait();
}
if(snake.length >= SNAKE_MAX_LENGTH)
{
check_f = check_face(snake[0]);
check_f.add_(new Dot(GRID_MAX-1,GRID_MAX-1,0));
mappers[int(check_f.z)][int(check_f.x)][int(check_f.y)] = false;
snake.splice(0, 1);
}
max_up.val_(to_up).mul_(GRID_MAX);
max_left.val_(to_left).mul_(GRID_MAX);
max_right.val_(to_right).mul_(GRID_MAX);
mimi_UP.val_(snake_head).replace_(max_up);
mimi_LEFT.val_(snake_head).replace_(max_left);
mimi_RIGHT.val_(snake_head).replace_(max_right);
if(SNAKE_DIRECTION == MOVE_UP || SNAKE_DIRECTION == MOVE_DOWN)
{
UP_temp.val_(snake_head).norm().cross_(mimi_RIGHT.norm()).norm();
} else {
RIGHT_temp.val_(mimi_UP).cross_(snake_head);
UP_temp.val_(snake_head).norm().cross_(RIGHT_temp.norm()).norm();
}
BACK_BONE.push_(0, 0, -1);
DIF = snake_head.angle_between(BACK_BONE);
crossproduct.val_(snake_head).cross_(BACK_BONE);
if(snake_head.equal(BACK_BONE.mul_(GRID_MAX)) || snake_head.equal(FRONT_BONE))
{
crossproduct.val_(snake_prev).cross_(BACK_BONE);
}
crossproduct.norm();
clone_point.x = crossproduct.x;
clone_point.y = crossproduct.y;
clone_point.z = crossproduct.z;
matrix.identity();
matrix.appendRotation(DIF/Math.PI*180, clone_point);
UP_temp.rotate_around_axis_(crossproduct, DIF);
DIF = UP_temp.angle_between(vUP);
if(UP_temp.x>0) DIF = -DIF;
BACK_BONE.norm();
clone_point.x = BACK_BONE.x;
clone_point.y = BACK_BONE.y;
clone_point.z = BACK_BONE.z;
matrix.appendRotation(-DIF/Math.PI*180, clone_point);
counter/=speed;
}
counter++;
var v:Vector.<Vector3D> = matrix.decompose();
cube.rotationX += rot_to(v[1].x - cube.rotationX)*0.33;
cube.rotationY += rot_to(v[1].y - cube.rotationY)*0.33;
cube.rotationZ += rot_to(v[1].z - cube.rotationZ)*0.33;
cube.rotationX = fix_rot(cube.rotationX);
cube.rotationY = fix_rot(cube.rotationY);
cube.rotationZ = fix_rot(cube.rotationZ);
}
}
private function give_me_bait():void
{
// simple random bait generator
var total_grid:int = GRID_WIDTH * GRID_WIDTH * 6;
var random_bait:int = Math.random() * total_grid;
var face:int = int(random_bait / (GRID_WIDTH * GRID_WIDTH));
var fy:int = int(random_bait % (GRID_WIDTH * GRID_WIDTH))/GRID_WIDTH;
var fx:int = int(random_bait % (GRID_WIDTH * GRID_WIDTH))%GRID_WIDTH;
if(mappers[face][fx][fy])
{
give_me_bait();
} else {
bait.x = fx;
bait.y = fy;
bait.z = face;
}
}
private function rot_to(rot:Number):Number
{
var r:Number = rot;
if(r > Math.PI) r = (-Math.PI*2 + r);
if(r < -Math.PI) r = ( Math.PI*2 + r);
return r;
}
private function fix_rot(rot:Number):Number
{
var r:Number = rot;
if(r > Math.PI*2) r = (-Math.PI*2 + r);
if(r < -Math.PI*2) r = ( Math.PI*2 + r);
return r;
}
private function draw_bait():void
{
bitmapDatas[int(bait.z)].fillRect(new Rectangle(bait.x*GRID_SIZE, bait.y*GRID_SIZE, GRID_SIZE, GRID_SIZE), 0xFFFF9900);
}
private function S_draw_body(p:*):void
{
var SH2D:Dot = check_face(p);
SH2D.add_(new Dot(GRID_MAX-1,GRID_MAX-1,0));
bitmapDatas[int(SH2D.z)].fillRect(new Rectangle(SH2D.x*GRID_SIZE, SH2D.y*GRID_SIZE, GRID_SIZE, GRID_SIZE), 0xFFFF0000);
}
private function curr_direction():Dot
{
switch(SNAKE_DIRECTION)
{
case MOVE_UP:
return to_up;
break;
case MOVE_DOWN:
return to_down;
break;
case MOVE_LEFT:
return to_left;
break;
case MOVE_RIGHT:
return to_right;
break;
}
return null;
}
private function curr_righthand():Dot
{
switch(SNAKE_DIRECTION)
{
case MOVE_UP:
return to_right;
break;
case MOVE_DOWN:
return to_left;
break;
case MOVE_LEFT:
return to_up;
break;
case MOVE_RIGHT:
return to_down;
break;
}
return null;
}
private function update_directions(p:*, s:*):void
{
to_up.rotate_around_axis_(p, s);
to_down.rotate_around_axis_(p, s);
to_left.rotate_around_axis_(p, s);
to_right.rotate_around_axis_(p, s);
to_up.round();
to_down.round();
to_left.round();
to_right.round();
}
private function check_face(p:*):Dot
{
if(p.x == -GRID_MAX)
{
return new Dot( -p.y, -p.z, LEFT);
}
else if(p.x == GRID_MAX)
{
return new Dot( p.y, -p.z, RIGHT);
}
else if(p.y == -GRID_MAX)
{
return new Dot(p.x, -p.z, BACK);
}
else if(p.y == GRID_MAX)
{
return new Dot( -p.x, -p.z, FRONT);
}
else if(p.z == -GRID_MAX)
{
return new Dot( -p.x, -p.y, BOTTOM);
}
else if(p.z == GRID_MAX)
{
return new Dot(p.x, -p.y, TOP);
}
return null;
}
private function onKey_Down( event:KeyboardEvent ):void
{
switch (event.keyCode) {
case Keyboard.SPACE:
pause_ = !pause_;
break;
case Keyboard.UP:
case 87:
key_up = true;
break;
case Keyboard.DOWN:
case 83:
key_down = true;
break;
case Keyboard.LEFT:
case 65:;
key_left = true;
break;
case Keyboard.RIGHT:
case 68:
key_right = true;
break;
}
}
private function false_all():void
{
key_up = false;
key_down = false;
key_left = false;
key_right = false;
}
private function gameOver():void
{
gameover_txt.x = stage.stageWidth/2 - gameover_txt.width/2;
gameover_txt.y = stage.stageHeight/2 - gameover_txt.height*1.5;
addChild(gameover_txt);
entryRanking();
}
public function entryRanking():void
{
form_score = new BasicScoreForm(this, (465-280)/2, (465-160)/2, parseInt(score_txt.text), "ENTRY", onCloseScoreForm);
return;
}
private function onCloseScoreForm(succeeded:Boolean):void
{
if (form_score != null) {removeChild(form_score);}
form_ranking = new BasicScoreRecordViewer(this, (465-220)/2, (465-240)/2, "RANKING", 30, true, onCloseRankingForm);
return;
}
private function showRanking(e:Event):void
{
form_ranking = new BasicScoreRecordViewer(this, (465-220)/2, (465-240)/2, "RANKING", 30, true, onCloseRankingForm);
return;
}
private function onCloseRankingForm():void
{
if (form_ranking != null) {removeChild(form_ranking);}
return;
}
}
}
import flash.utils.Timer;
class Dot
{
public var x:Number = 0;
public var y:Number = 0;
public var z:Number = 0;
public function Dot(px:Number = 0, py:Number = 0, pz:Number = 0) { x = px; y = py; z = pz; }
public function push_(px:Number=0, py:Number=0, pz:Number=0):Dot {x = px; y = py; z = pz; return this;}
public function val_(p:*):Dot {x=p.x; y=p.y; z=p.z; return this;}
public function clone():Dot {return new Dot(x, y, z);}
public function add_ (p:*):Dot {x+=p.x; y+=p.y; z+=p.z; return this;}
public function sub_ (p:*):Dot {x-=p.x; y-=p.y; z-=p.z; return this;}
public function mul_ (p:*):Dot {x*=p; y*=p; z*=p; return this;}
public function div_ (p:*):Dot {x/=p; y/=p; z/=p; return this;}
public function round():Dot {x=Math.round(x); y=Math.round(y); z=Math.round(z); return this;}
public function norm():Dot {var l:Number = len(); x/=l; y/=l; z/=l; return this;}
public function dot(p:*):Number {return x*p.x + y*p.y + z*p.z;}
public function len():Number {return Math.sqrt(x*x + y*y + z*z);}
public function cross_(p:*):Dot {
var tx:Number = x;
var ty:Number = y;
var tz:Number = z;
x = ty * p.z - tz * p.y;
y = tz * p.x - tx * p.z;
z = tx * p.y - ty * p.x;
return this;
}
public function equal(p:*):Boolean {return (x==p.x && y==p.y && z==p.z);}
public function has_(p:*):Boolean {return (x == p || x == -p || y == p || y == -p || z == p || z == -p)? true: false;}
public function excex_(p:*):Dot {x = (x==p||x==-p)?x:0; y = (y==p||y==-p)?y:0; z = (z==p||z==-p)?z:0; return this;}
public function replace_ (p:*):Dot {
if(p.x != 0) x = p.x;
if(p.y != 0) y = p.y;
if(p.z != 0) z = p.z;
return this;
}
public function angle_between(b:Dot):Number
{
var dotproduct:Number = dot(b);
var lengtha:Number = len();
var lengthb:Number = b.len();
var r:Number = Math.acos( dotproduct / (lengtha * lengthb) );
return r;
}
public function rotate_around_axis_(arb_axis:*, speed:Number):void
{
var Cos:Number = Math.cos(speed);
var Sin:Number = Math.sin(speed);
var Tan:Number = 1 - Cos;
var aalen:Number = arb_axis.len();
var n1:Number = arb_axis.x/aalen;
var n2:Number = arb_axis.y/aalen;
var n3:Number = arb_axis.z/aalen;
var tx:Number = x;
var ty:Number = y;
var tz:Number = z;
x = tx * ( Math.pow(n1,2) * Tan + Cos ) + ty * ( n1 * n2 * Tan - n3 * Sin ) + tz * ( n1 * n3 * Tan + n2 * Sin );
y = tx * ( n1 * n2 * Tan + n3 * Sin ) + ty * ( Math.pow(n2,2) * Tan + Cos ) + tz * ( n2 * n3 * Tan - n1 * Sin );
z = tx * ( n1 * n3 * Tan - n2 * Sin ) + ty * ( n2 * n3 * Tan + n1 * Sin ) + tz * ( Math.pow(n3,2) * Tan + Cos );
}
}
class Timerx extends Timer
{
public var id:int = 0;
public var count:int = 0;
public var speed:int = 3;
public function Timerx(t:int) {super(t);}
}