Flex 3 SDKとで三次元を遊ぶ[13]
/**
* Copyright Akiyah ( http://wonderfl.net/user/Akiyah )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/iGqe
*/
package {
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import caurina.transitions.Tweener;
import org.papervision3d.core.effects.view.ReflectionView;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.materials.BitmapFileMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.scenes.Scene3D;
public class DoubutsuShogi extends ReflectionView {
public var plane_for_drug:Plane;
public var kanban:Cube;
public var mouse_points:Array = [];
public var camera_length:Number = 200;
public var rule:Rule;
public static const UNIT_SIZE:Number = 100;
public function DoubutsuShogi() {
viewport.interactive = true;
viewportReflection.filters = [new BlurFilter()];
rule = new Rule();
rule.ds = this;
for each(var koma:Koma in rule.komas) {
scene.addChild(koma.cube);
}
scene.addChild(createBoard());
scene.addChild(createKanban());
plane_for_drug = createPlane();
scene.addChild(plane_for_drug);
addEventListener(Event.ENTER_FRAME, update);
stage.addEventListener(MouseEvent.MOUSE_UP, released);
stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouse_wheel);
}
public function createBoard():Cube {
var boardTopMaterial:BitmapFileMaterial = new BitmapFileMaterial(Koma.IMAGE_URL + Koma.BOARD_TOP_URL);
var boardMaterial:BitmapFileMaterial = new BitmapFileMaterial(Koma.IMAGE_URL + Koma.BOARD_URL);
boardTopMaterial.interactive = true;
var mlist:MaterialsList = new MaterialsList( { all:boardMaterial, top:boardTopMaterial } );
var board:Cube = new Cube(mlist, UNIT_SIZE / 2 * 3 + 10, UNIT_SIZE / 2 * 4 + 10, 10, 3, 2, 4);
board.y = 5;
return board;
}
public function createKanban():Cube {
var topMaterial:BitmapFileMaterial = new BitmapFileMaterial(Koma.IMAGE_URL + Koma.KANBAN_KATI_URL);
var bottomMaterial:BitmapFileMaterial = new BitmapFileMaterial(Koma.IMAGE_URL + Koma.KANBAN_MAKE_URL);
var material:BitmapFileMaterial = new BitmapFileMaterial(Koma.IMAGE_URL + Koma.KANBAN_URL);
var mlist:MaterialsList = new MaterialsList( { all:material, top:topMaterial , bottom:bottomMaterial } );
kanban = new Cube(mlist, 100, 100, 10, 4, 2, 4);
kanban.rotationX = -90;
kanban.visible = false;
return kanban;
}
public function show_kanban():void {
kanban.y = 500;
kanban.visible = true;
Tweener.addTween(kanban, {
y: 100,
time: 3,
transition: 'easeOutBounce'
});
}
public function show_win():void {
kanban.rotationY = 180;
show_kanban();
}
public function show_loose():void {
kanban.rotationY = 0;
show_kanban();
}
public function createPlane():Plane {
var material:MaterialObject3D = new MaterialObject3D();
//var material:MaterialObject3D = new WireframeMaterial();
material.doubleSided = true;
material.interactive = true;
var plane:Plane = new Plane(material, 400, 400, 10, 10);
plane.pitch(90);
plane.y = 80;
plane.visible = false;
plane.addEventListener(InteractiveScene3DEvent.OBJECT_MOVE, moved);
return plane;
}
public function released(event:MouseEvent):void {
plane_for_drug.visible = false;
mouse_points = [];
if (!select_koma()) { return; }
var i:int = x_to_i(select_koma().cube.x);
var j:int = z_to_j(select_koma().cube.z);
rule.move(select_koma(), i, j);
rule.unselect();
}
public function moved(event:InteractiveScene3DEvent):void {
if (!select_koma()) { return; }
var x:Number = event.renderHitData.x;
var y:Number = event.renderHitData.y;
var z:Number = event.renderHitData.z;
mouse_points.unshift(new Number3D(x, y, z));
if (mouse_points.length > 1) {
select_koma().cube.x += mouse_points[0].x - mouse_points[1].x;
select_koma().cube.z += mouse_points[0].z - mouse_points[1].z;
}
}
public function update(e:Event):void {
var c:Number = (1 - ((mouseX / stage.width) - 0.5) * 1.5) * (Math.PI / 4);
var d:Number = (1 - ((mouseY / stage.height) - 0.5) * 1.5) * (Math.PI / 4);
camera.x = Math.sin(c) * Math.cos(d) * camera_length;
camera.z = Math.cos(c) * Math.cos(d) * camera_length;
camera.y = Math.sin(d) * camera_length;
singleRender();
}
public function mouse_wheel(event:MouseEvent):void {
camera_length -= event.delta * 5;
camera_length = Math.max(camera_length, 50);
camera_length = Math.min(camera_length, 1000);
}
public function select():void {
plane_for_drug.visible = true;
}
public function select_koma():Koma {
return rule.select_koma;
}
public static function i_to_x(i:int):Number {
return (i - 2) * UNIT_SIZE / 2; // (i - 1) * UNIT_SIZE / 2 - UNIT_SIZE / 2;
}
public static function x_to_i(x:Number):int {
return int(x / (UNIT_SIZE / 2) + 2 + 0.5);
}
public static function j_to_z(j:int):Number {
return (- j + 2.5) * UNIT_SIZE / 2; // - (j - 1.5) * UNIT_SIZE / 2 + UNIT_SIZE / 2;
}
public static function z_to_j(z:Number):int {
return int(- z / (UNIT_SIZE / 2) + 2.5 + 0.5);
}
}
}
import caurina.transitions.Tweener;
import flash.events.MouseEvent;
import flash.display.BitmapData;
import flash.system.Security;
import flash.geom.Rectangle;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.materials.BitmapFileMaterial;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.special.CompositeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
class Rule {
public var komas:Array;
public var side:Boolean = false;
public var select_koma:Koma;
public var ds:DoubutsuShogi;
public function Rule() {
createKomas([[Hiyoko, 2, 3], [Zou, 1, 4], [Tora, 2, 4], [Kirin, 3, 4]]);
}
public function createKomas(komaDatas:Array):void {
var komaData:Array;
var koma:Koma;
komas = [];
for each(komaData in komaDatas) {
koma = new komaData[0]();
koma.rule = this;
koma.move(komaData[1], komaData[2]);
komas.push(koma);
}
for each(komaData in komaDatas) {
koma = new komaData[0]();
koma.rule = this;
koma.move(4 - komaData[1], 5 - komaData[2]);
koma.turn();
komas.push(koma);
}
}
public function move(koma:Koma, i:int, j:int):void {
if (!in_board(i, j)) {
koma.revert();
return;
}
if (koma.side != side) {
koma.revert();
return;
}
if (koma.in_board() && !can_move(koma, i, j)) {
koma.revert();
return;
}
var other_koma:Koma = get_koma(i, j);
if (!koma.in_board() && other_koma) {
koma.revert();
return;
}
if (other_koma && other_koma.side == koma.side) {
koma.revert();
return;
}
if (other_koma) {
capture(other_koma);
}
koma.move(i, j);
win_loose();
side = !side;
}
public function win_loose():void {
if (capture_tora(!side)) {
if (side) {
ds.show_loose();
} else {
ds.show_win();
}
return;
}
if (entered_tora(!side)) {
if (side) {
ds.show_win();
} else {
ds.show_loose();
}
return;
}
}
public function capture_tora(side:Boolean):Boolean {
for each(var koma:Koma in komas) {
if ((koma as Tora) && (koma.side == side)) {
return false;
}
}
return true;
}
public function entered_tora(side:Boolean):Boolean {
for each(var koma:Koma in komas) {
if ((koma as Tora) && (koma.side == side) && koma.entered()) {
return true;
}
}
return false;
}
public function in_board(i:int, j:int):Boolean {
if (i <= 0 || 3 < i) { return false; }
if (j <= 0 || 4 < j) { return false; }
return true;
}
public function can_move(koma:Koma, i:int, j:int):Boolean {
var di:int = i - koma.i;
var dj:int = j - koma.j;
if (Math.abs(di) > 1) { return false; }
if (Math.abs(dj) > 1) { return false; }
return koma.direction(di, dj) == 1;
}
public function get_koma(i:int, j:int):Koma {
for each(var koma:Koma in komas) {
if ((koma.i == i) && (koma.j == j)) {
return koma;
}
}
return null;
}
public function capture(koma:Koma):void {
koma.turn();
var n:int = 0;
if (koma.side) {
while (get_koma(-1, 4 - n)) { n += 1; }
koma.move(-1, 4 - n);
} else {
while (get_koma(5, 1 + n)) { n += 1; }
koma.move(5, 1 + n);
}
}
public function select(koma:Koma):void {
ds.select();
select_koma = koma;
}
public function unselect():void {
select_koma = null;
}
}
class Koma {
public var cube:Cube;
public var i:int;
public var j:int;
public var side:Boolean = true;
public var rule:Rule;
private var _direction:Array;
private var _direction_other:Array;
protected var _reverse:Boolean = false;
public static const KOMA_SIZE:Number = DoubutsuShogi.UNIT_SIZE * 0.8;
Security.loadPolicyFile("http://assets.wonderfl.net/crossdomain.xml");
public static const IMAGE_URL:String = "http://assets.wonderfl.net/images/related_images/";
public static const HIYOKO_URL:String = "b/ba/ba3b/ba3b579e1504b12fa567dc41055d01c53101e077";
public static const KIRIN_URL:String = "c/c7/c771/c771f6190264a7629a5ee1870aac8f37baf72685";
public static const ZOU_URL:String = "4/4f/4f9b/4f9bc33c1f980a2966316ccd00579ed34644720e";
public static const TORA_URL:String = "0/05/05e6/05e6dd6f27b161e2145454a58b66100011c3e8b8";
public static const NIWATORI_URL:String = "7/7e/7ea7/7ea774a207e87eac909343ca90528467f3be4449";
public static const BOARD_URL:String = "a/a4/a408/a408a5d33c12f0a559f761afe70dedae02ef61a9";
public static const BOARD_TOP_URL:String = "7/7c/7cb8/7cb89b99e9b0633f58000ff968deecfc17d1e0d0";
public static const KI_URL:String = "4/4b/4b43/4b43a7eae5a186a1af9267c0697d66b91d9d38a4";
public static const KANBAN_URL:String = "b/b0/b08e/b08ef67a78d08af9cb9e3a03b069706dcb8985b0";
public static const KANBAN_KATI_URL:String = "d/d0/d03e/d03e8b0f6897df951bc18382e2291153fc2b4e5f";
public static const KANBAN_MAKE_URL:String = "f/f1/f10c/f10cfce67511df8ae09b779f9d3bcac217a4f70c";
public function Koma(filename:String, _direction:Array,
filename_other:String = null, _direction_other:Array = null) {
this.rule = rule;
this._direction = _direction;
this._direction_other = _direction_other;
cube = createCube(filename, _direction, filename_other, _direction_other);
cube.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, pressed);
}
public function pressed(event:InteractiveScene3DEvent):void {
if (rule.side != side) { return; }
rule.select(this);
Tweener.addTween(cube, {
y: DoubutsuShogi.UNIT_SIZE / 4 + 30,
time:1,
transition: 'easeInOutCubic'
});
}
public function move(i:int, j:int):void {
this.i = i;
this.j = j;
var y:Number = DoubutsuShogi.UNIT_SIZE / 4;
if (!in_board()) {
y -= 10;
}
Tweener.addTween(cube, {
x: DoubutsuShogi.i_to_x(this.i),
y: y,
z: DoubutsuShogi.j_to_z(this.j),
time:1,
transition: 'easeInOutCubic'
});
}
public function in_board():Boolean {
return rule.in_board(i, j);
}
public function revert():void {
move(this.i, this.j)
}
public function turn():void {
this.side = !this.side;
Tweener.addTween(cube, {
rotationY: cube.rotationY + 180,
time:1,
transition: 'easeInOutCubic'
});
}
public function reverse():void {}
public function direction(di:int, dj:int):int {
if (!side) {
di = -di;
dj = -dj;
}
var dir:Array;
if (_reverse) {
dir = _direction_other;
} else {
dir = _direction;
}
return dir[dj + 1][di + 1];
}
public function createCube(filename:String, direction:Array, filename_other:String, direction_other:Array):Cube {
var materialsList:MaterialsList = new MaterialsList( { all:materialKi} );
var materialKi:BitmapFileMaterial = new BitmapFileMaterial(Koma.IMAGE_URL + Koma.KI_URL);
materialKi.interactive = true
materialsList.addMaterial(materialKi, "all")
materialsList.addMaterial(createCompositeMaterial(filename, direction), "top")
if (filename_other != null) {
materialsList.addMaterial(createCompositeMaterial(filename_other, direction_other), "bottom")
}
return new Cube(materialsList, KOMA_SIZE / 2, KOMA_SIZE / 2, KOMA_SIZE / 4, 2, 2, 2);
}
private function createCompositeMaterial(filename:String, direction:Array):CompositeMaterial {
var material:CompositeMaterial = new CompositeMaterial();
material.addMaterial(new BitmapFileMaterial(Koma.IMAGE_URL + filename));
material.addMaterial(createDirectionMarkMaterial(direction));
material.interactive = true;
return material;
}
private function createDirectionMarkMaterial(direction:Array):BitmapMaterial {
var bd:BitmapData = new BitmapData(100, 100, true, 0x00000000);
for (var j:Number = 0; j < 3; j++) {
for (var i:Number = 0; i < 3; i++) {
if (direction[j][i] == 1) {
bd.fillRect(new Rectangle(5 + i*40, 5 + j*40, 10, 10), 0xFFFF0000);
}
}
}
return new BitmapMaterial(bd);
}
public function entered():Boolean {
return (side && (j == 1)) || (!side && (j == 4));
}
}
class Hiyoko extends Koma {
public function Hiyoko() {
super(Koma.HIYOKO_URL, [[0,1,0],[0,0,0],[0,0,0]],
Koma.NIWATORI_URL, [[1,1,1],[1,0,1],[0,1,0]]);
}
public override function reverse():void {
_reverse = !_reverse;
Tweener.addTween(cube, {
rotationZ: cube.rotationZ + 180,
time:1,
transition: 'easeInOutCubic'
});
}
public override function move(i:int, j:int):void {
if (in_board() && j == 1 && side && !_reverse) {
reverse();
}
if (in_board() && j == 4 && !side && !_reverse) {
reverse();
}
super.move(i, j);
if (!in_board() && _reverse) {
reverse();
}
}
}
class Kirin extends Koma {
public function Kirin() {
super(Koma.KIRIN_URL, [[0,1,0],[1,0,1],[0,1,0]]);
}
}
class Tora extends Koma {
public function Tora() {
super(Koma.TORA_URL, [[1,1,1],[1,0,1],[1,1,1]]);
}
}
class Zou extends Koma {
public function Zou() {
super(Koma.ZOU_URL, [[1,0,1],[0,0,0],[1,0,1]]);
}
}