forked from: forked from: PaperVision3Dでハノイ
PaperVisionテスト
ブロックの表示が変なのはどうしたらよいのでしょう...
→ QuadrantRenderEngine使うと、ボリゴン欠けは多少改善されるかと思います
参考:http://clockmaker.jp/blog/2008/10/pv3d_quadtree/
// forked from clockmaker's forked from: PaperVision3Dでハノイ
// forked from masibonge's PaperVision3Dでハノイ
package{
//PaperVisionテスト
//ブロックの表示が変なのはどうしたらよいのでしょう...
// → QuadrantRenderEngine使うと、ボリゴン欠けは多少改善されるかと思います
// 参考:http://clockmaker.jp/blog/2008/10/pv3d_quadtree/
import flash.display.*;
import flash.events.Event;
import flash.text.*;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.render.*;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Cylinder;
import org.papervision3d.materials.*;
import org.papervision3d.materials.utils.*;
import org.papervision3d.materials.special.CompositeMaterial;
import org.papervision3d.materials.shadematerials.*;
import org.papervision3d.lights.*;
import net.hires.debug.Stats;
public class Hanoi extends Sprite{
private const NSTONE:int = 5;
private const FRAME:int = 60;
private var scene:Scene3D;
private var viewport:Viewport3D;
private var camera:ECamera3D;
private var render:BasicRenderEngine;
private var objStones:Array;
private var objCylinders:Array;
private var objPlane:Plane;
private var light:PointLight3D;
private var order:int;
private var max_order:int;
private var move:Array;
private var stack:Array;
//for animation
private var count:int;
private var speed:Number;
private var from:int;
private var to:int;
private var ftop:int;
private var ttop:int;
private const TIME_REQ:int = 10;
private var s:Sprite;
private var tf:TextField;
private var ttf:TextFormat;
public function Hanoi(){
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.frameRate = FRAME;
init();
addChild(new Stats)
}
private function init():void{
viewport = new Viewport3D(0, 0, true);
viewport.opaqueBackground = 0;
addChild(viewport);
light = new PointLight3D();
light.x = light.y = 500;
light.z = -100;
//render
render = new QuadrantRenderEngine(QuadrantRenderEngine.ALL_FILTERS);
//render = new BasicRenderEngine();
//camera
camera = new ECamera3D();
camera.y = 300;
camera.z = -1000;
camera.focus = 500;
camera.zoom = 1;
//scene
scene = new Scene3D();
//material
var colorMat:ColorMaterial = new ColorMaterial(0x06699, 1);
var wireMat:WireframeMaterial = new WireframeMaterial(0x0099cc);
var compoMat:CompositeMaterial = new CompositeMaterial();
compoMat.addMaterial(colorMat);
compoMat.addMaterial(wireMat);
compoMat.doubleSided = true;
//objects
objStones = new Array(NSTONE);
for(var i:int=0;i<NSTONE;++i){
objStones[i] = makeStone(compoMat, i);
scene.addChild(objStones[i]).y = -40+55*i;
}
objCylinders = new Array(3);
for(i=0;i<3;++i){
objCylinders[i] = new Cylinder(new FlatShadeMaterial(light),10,500,10);
objCylinders[i].y = 200;
scene.addChild(objCylinders[i]).x = i*500-500;
}
order = 0;
max_order = Math.pow(2, NSTONE) - 1;
//array for move
move = new Array(max_order);
for(i=0;i<max_order;++i)
move[i] = new Array(2);
stack = new Array(3);
for(i=0;i<3;++i)
stack[i] = new Array(NSTONE);
for(i=0;i<NSTONE;++i){
stack[0][i] = i;
stack[1][i] = stack[2][i] = -1;
}
//hanoi
recu(NSTONE, 0, 1, 2);
//animation start
order = count = 0;
from = move[order][0];
to = move[order][1];
ftop = checkHighest(from);
ttop = checkHighest(to);
speed = makeSpeed(objStones[ftop].y);
//event
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function makeStone(compoMat:CompositeMaterial, i:int):Cube{
i = NSTONE - i;
// グーローシェイディングはQuadrantRenderエンジンと相性がわるかったのでフラットシェーディングにしてます
var tmp:Cube = new Cube(new MaterialsList
({all:new FlatShadeMaterial(light)}),
50*i+100, 50*i+100, 50);
tmp.x = -500;
return tmp;
}
private function recu(n:int, x:int, y:int, z:int):void{
if(n){
recu(n - 1, x, z, y);
move[order][0]=x;
move[order][1]=y;
++order;
recu(n - 1, z, y, x );
}
}
private function checkHighest(c:int):int{
for(var i:int=NSTONE;i--;)
if(stack[c][i] > -1) return i;
return -1;
}
private function makeSpeed(tmp:Number):Number{
return (1000 - tmp ) / TIME_REQ ;
}
private function onEnterFrame(event:Event):void{
if(order < max_order){
objStones[stack[from][ftop]].y += speed;
if(count == TIME_REQ){
objStones[stack[from][ftop]].x= 500 * to - 500;
objStones[stack[from][ftop]].y = 1000;
if(ttop<0)speed = -makeSpeed(0);
else speed = -makeSpeed(objStones[stack[to][ttop]].y+80);
}
if(count > TIME_REQ * 2){
objStones[stack[from][ftop]].y = ttop * 55;
if(ttop<0)stack[to][0] = stack[from][ftop];
else stack[to][ttop+1] = stack[from][ftop];
stack[from][ftop] = -1;
++order;
count = 0;
from = move[order][0];
to = move[order][1];
ftop = checkHighest(from);
ttop = checkHighest(to);
speed = makeSpeed(objStones[ftop].y);
}
++count;
}
camera.loop();
render.renderScene(scene, camera, viewport);
}
}
}
import org.papervision3d.cameras.Camera3D;
class ECamera3D extends Camera3D{
private var flag:int;
public function ECamera3D(){
flag = 1;
new Camera3D();
}
public function loop():void{
flag?++this.x:--this.x;
if(this.x>1000){this.x = 999;flag=0;}
if(this.x<-1000){this.x = -999;flag=1;}
this.rotationY = this.rotationY - 0.09;
flag?this.z = -Math.sqrt(1000000 - (this.x * this.x )):
this.z = Math.sqrt(1000000 - (this.x * this.x ));
}
}