Flex 3 SDKとで三次元を遊ぶ[18]
Flex 3 SDKとPapervision3Dで三次元を遊ぶ [18]
http://www.ObjectClub.jp/ml-arch/magazine/xxx.html
/**
* Copyright Akiyah ( http://wonderfl.net/user/Akiyah )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vCr5
*/
/*
Flex 3 SDKとPapervision3Dで三次元を遊ぶ [18]
http://www.ObjectClub.jp/ml-arch/magazine/xxx.html
動かす条件:
・ボードからはみ出すことは出来ない
・駒毎の進める方向にしか進めない
・自分の駒と同じところに置くことは出来ない
・相手の駒と同じところに置いたら相手のコマをもらうことができて、パーキングにおく
・パーキングの駒はすでにコマが置いていない場所にうつことができる。
・自分と相手は交互にコマを動かす
・自分の番のときにライオンがとられていたか、相手のライオンが自陣に入っていたらまけ
・ひよこは相手陣についたらニワトリになる。
・ニワトリは、とられたらひよこになる
・ひよこを打ったときに相手陣においてもニワトリにはならない
座標
(1,1) (2,1) (3,1)
(1,2) (2,2) (3,2)
(1,3) (2,3) (3,3)
(1,4) (2,4) (3,4)
side == true 上向き 手前 自分
side == false 下向き 奥 コンピューター
持ち駒がある場合の座標
(-1,1) () (1,1) (2,1) (3,1) () (5,1)
(-1,2) () (1,2) (2,2) (3,2) () (5,2)
(-1,3) () (1,3) (2,3) (3,3) () (5,3)
(-1,4) () (1,4) (2,4) (3,4) () (5,4)
駒のid
0:tora, 味方
1:tora, 敵
2:hiyoko, 味方
3:hiyoko, 敵
4:kirin, 味方
5:kirin, 敵
6:zou, 味方
7:zou, 敵
*/
package {
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.filters.BlurFilter;
import caurina.transitions.Tweener;
import org.papervision3d.core.effects.BitmapFireEffect;
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;
import org.papervision3d.view.layer.BitmapEffectLayer;
public class DoubutsuShogi extends ReflectionView {
public var plane_for_drug:Plane;
public var kanban:Cube;
public var start_kanban:Cube;
public var mouse_points:Array = [];
public var camera_length:Number = Rule.CAMERA_LENGTH_DEFAULT;
public var bfx:BitmapEffectLayer;
public var bfe:BitmapFireEffect;
public var game_count:Number = 0;
public var in_game:Boolean = false;
public function DoubutsuShogi() {
viewport.interactive = true;
viewportReflection.filters = [new BlurFilter()];
createBitmapEffectLayer();
scene.addChild(createBoard());
scene.addChild(createKanban());
scene.addChild(createStartKanban());
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);
Rule.init();
Rule.ds = this;
for each(var pieceUI:PieceUI in Rule.pieceUIs) {
scene.addChild(pieceUI.cube);
}
view(false);
}
public function view(fire:Boolean = true):void {
Rule.board.reset_position();
var count_piece_true:int = 0;
var count_piece_false:int = 0;
for each(var piece:Piece in Rule.board.pieces) {
var pieceUI:PieceUI = Rule.pieceUIs[piece.id];
pieceUI.view();
}
if (fire) {
Tweener.addTween(this, {
time: 2,
onComplete: show_pieceUIs_fire
});
}
}
public function createBitmapEffectLayer():void {
bfx = new BitmapEffectLayer(viewport, stage.width, stage.height);
bfe = new BitmapFireEffect();
bfe.fadeRate = 0.1;
bfe.flameSpread = 1;
bfe.flameHeight = 0.5;
bfe.distortion = 1;
bfe.distortionScale = 1;
bfe.smoke = 1;
//f.blueFlame = true;
bfx.addEffect(bfe);
viewport.containerSprite.addLayer(bfx);
}
public function show_pieceUIs_fire():void {
for each(var piece:Piece in Rule.board.pieces) {
if (piece.side == Rule.board.side) {
show_fire(piece.id);
}
}
Tweener.addTween(this, {
time: 2,
onComplete: function():void {
for each(var piece:Piece in Rule.board.pieces) {
hide_fire(piece.id);
}
}
});
}
public function show_fire(id:int):void {
bfe.blueFlame = !Rule.board.pieces[id].side;
bfx.addDisplayObject3D(Rule.pieceUIs[id].cube);
}
public function hide_fire(id:int):void {
bfx.removeDisplayObject3D(Rule.pieceUIs[id].cube);
}
public function createOXCube(o:Boolean):Cylinder {
var material:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.KI_URL);
var materialTop:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.O_URL);
var materialBottom:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.X_URL);
var cube:Cylinder = new Cylinder(material, Rule.PIECE_SIZE / 8, Rule.PIECE_SIZE / 16, 10, 2, -1, true, true, materialTop, materialBottom);
var rotationZ:Number = o ? 0 : 180;
cube.rotationZ = rotationZ;
var x:Number = DoubutsuShogi.i_to_x(game_count * 0.5);
var y:Number = Rule.UNIT_SIZE / 4 - 20;
var z:Number = DoubutsuShogi.j_to_z(5);
cube.x = x;
cube.y = y + 300;
cube.z = z;
game_count++ ;
scene.addChild(cube);
Tweener.addTween(cube, {
y: y,
time: 3,
transition: 'easeOutBounce'
});
Tweener.addTween(cube, {
rotationZ: rotationZ + 360,
time: 3
});
return cube;
}
public function createBoard():Cube {
var boardTopMaterial:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.BOARD_TOP_URL);
var boardMaterial:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.BOARD_URL);
boardTopMaterial.interactive = true;
var mlist:MaterialsList = new MaterialsList( { all:boardMaterial, top:boardTopMaterial } );
var board:Cube = new Cube(mlist, Rule.UNIT_SIZE / 2 * 3 + 10, Rule.UNIT_SIZE / 2 * 4 + 10, 10, 3, 2, 4);
board.y = 5;
return board;
}
public function createKanban():Cube {
var topMaterial:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.KANBAN_KATI_URL);
var bottomMaterial:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.KANBAN_MAKE_URL);
var material:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.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 createStartKanban():Cube {
var topMaterial:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.KANBAN_START_URL);
var bottomMaterial:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.KANBAN_START_URL);
var material:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.KANBAN_URL);
topMaterial.interactive = true;
bottomMaterial.interactive = true;
material.interactive = true;
var mlist:MaterialsList = new MaterialsList( { all:material, top:topMaterial , bottom:bottomMaterial } );
start_kanban = new Cube(mlist, 100, 100, 10, 4, 2, 4);
start_kanban.rotationX = -90;
start_kanban.y = 100;
start_kanban.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, start_kanban_clicked);
return start_kanban;
}
public function start_kanban_clicked(event:InteractiveScene3DEvent):void {
Tweener.addTween(start_kanban, {
x: 200,
time: 4
});
hide_kanban();
Rule.reset();
start_pieceUIs();
if (in_game) {
createOXCube(false); // 試合中に試合開始を押した場合は負け
}
in_game = true;
view();
}
public function start_kanban_alert():void {
Tweener.addTween(start_kanban, {
x: 150,
time: 3,
transition: 'easeOutBounce',
onComplete: function():void {
Tweener.addTween(start_kanban, {
y: 130,
time: 3,
onComplete: function():void {
Tweener.addTween(start_kanban, {
y: 100,
time: 3,
transition: 'easeOutBounce',
onComplete: function():void {
if (in_game) {
return;
} else {
start_kanban_alert();
}
}
})
}
})
}
});
}
public function show_kanban(win:Boolean):void {
kanban.rotationY = win ? 0 : 180;
kanban.y = 500;
kanban.visible = true;
Tweener.addTween(this, {
time: 1,
onComplete: function():void {
createOXCube(win);
in_game = false;
Tweener.addTween(kanban, {
y: 100,
time: 3,
transition: 'easeOutBounce',
onComplete: function():void {
start_kanban_alert();
}
})
}
});
}
public function hide_kanban():void {
kanban.y = 100;
Tweener.addTween(kanban, {
y: 500,
time: 3,
onComplete: function():void {
kanban.visible = false;
}
})
}
public function show_win_loose():Boolean {
if (Rule.board.is_win()) {
show_kanban(Rule.board.side);
stop_pieceUIs();
return true;
}
if (Rule.board.is_lose()) {
show_kanban(!Rule.board.side);
stop_pieceUIs();
return true;
}
return false;
}
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 (!Rule.select_pieceUI) { return; }
var i:int = x_to_i(Rule.select_pieceUI.cube.x);
var j:int = z_to_j(Rule.select_pieceUI.cube.z);
var b:Board = Rule.board.move(Rule.select_pieceUI.id, i, j);
if (!b) {
view();
Rule.unselect();
return;
}
Rule.board = b;
view(); // 2sec
Rule.unselect();
var win_loose:Boolean = show_win_loose();
if (win_loose) {
return;
}
computer_hand();
}
public function computer_hand():void {
Tweener.addTween(this, {
time: 2,
onComplete: function():void {
var bp:Array = Rule.board.next_board_best_with_point(4);
Rule.board = bp[0];
Tweener.addTween(this, {
time: 5,
onComplete: function():void {
view();
show_win_loose();
}
})
}
})
}
public function start_pieceUIs():void {
for each(var pieceUI:PieceUI in Rule.pieceUIs) {
pieceUI.start();
}
}
public function stop_pieceUIs():void {
for each(var pieceUI:PieceUI in Rule.pieceUIs) {
pieceUI.stop();
}
}
public function moved(event:InteractiveScene3DEvent):void {
if (!Rule.select_pieceUI) { 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) {
Rule.select_pieceUI.cube.x += mouse_points[0].x - mouse_points[1].x;
Rule.select_pieceUI.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) + (Math.PI);
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 static function i_to_x(i:Number):Number {
return (i - 2) * Rule.UNIT_SIZE / 2; // (i - 1) * UNIT_SIZE / 2 - UNIT_SIZE / 2;
}
public static function x_to_i(x:Number):Number {
return int(x / (Rule.UNIT_SIZE / 2) + 2 + 0.5);
}
public static function j_to_z(j:Number):Number {
return (- j + 2.5) * Rule.UNIT_SIZE / 2; // - (j - 1.5) * UNIT_SIZE / 2 + UNIT_SIZE / 2;
}
public static function z_to_j(z:Number):Number {
return int(- z / (Rule.UNIT_SIZE / 2) + 2.5 + 0.5);
}
}
}
import flash.display.Bitmap;
import caurina.transitions.Tweener;
import flash.events.MouseEvent;
import flash.display.BitmapData;
import flash.system.Security;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import org.ascollada.utils.StringUtil;
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 static var pieceUIs:Array;
public static var select_pieceUI:PieceUI;
public static var ds:DoubutsuShogi;
public static var board:Board;
public static const CAMERA_LENGTH_DEFAULT:Number = 300;
public static const UNIT_SIZE:Number = 100;
public static const PIECE_SIZE:Number = 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 IMAGE_URL:String = "";
public static const PIECE_IMAGE_URL:Object = {
hiyoko: "b/ba/ba3b/ba3b579e1504b12fa567dc41055d01c53101e077",
kirin: "c/c7/c771/c771f6190264a7629a5ee1870aac8f37baf72685",
zou: "4/4f/4f9b/4f9bc33c1f980a2966316ccd00579ed34644720e",
tora: "0/05/05e6/05e6dd6f27b161e2145454a58b66100011c3e8b8",
niwatori: "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 O_URL:String = "4/40/408d/408da0724307fabc751915c3d98bd925b30bad22";
public static const X_URL:String = "1/11/1121/11212e259a565277956fa028ce26c6aa84f21c0c";
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 static const KANBAN_START_URL:String = "6/65/653b/653b243eec8e147dbcd44fdb2d561414c475666e";
public static const PIECE_POSITION:Array = [
["tora", 2, 4],
["hiyoko", 2, 3],
["kirin", 3, 4],
["zou", 1, 4]
];
public static const DIRECTIONS:Object = {
hiyoko: [[0,1,0], [0,0,0], [0,0,0]],
niwatori: [[1,1,1], [1,0,1], [0,1,0]],
kirin: [[0,1,0], [1,0,1], [0,1,0]],
tora: [[1,1,1], [1,0,1], [1,1,1]],
zou: [[1,0,1], [0,0,0], [1,0,1]]
};
public static function random_choose(arr:Array):Object {
var i:int = Math.floor(Math.random() * arr.length);
return arr[i];
}
public static function init():void {
reset();
createPieceUIs();
}
public static function createPieceUIs():void {
pieceUIs = [];
var k:int = 0;
for each(var pieceData:Array in PIECE_POSITION) {
var id:int;
id = k * 2;
pieceUIs.push(new PieceUI(id));
id = k * 2 + 1;
pieceUIs.push(new PieceUI(id));
k++;
}
}
public static function reset():void {
board = new Board(true);
var k:int = 0;
for each(var pieceData:Array in PIECE_POSITION) {
var id:int;
var type:String;
var i:int;
var j:int;
type = pieceData[0];
id = k * 2;
i = pieceData[1];
j = pieceData[2];
board.pieces.push(new Piece(id, type, i, j, true, true));
id = k * 2 + 1;
i = 4 - pieceData[1];
j = 5 - pieceData[2];
board.pieces.push(new Piece(id, type, i, j, false, true));
k++;
}
}
public static 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 static function select(pieceUI:PieceUI):void {
ds.select();
ds.show_fire(pieceUI.id);
select_pieceUI = pieceUI;
}
public static function unselect():void {
ds.hide_fire(select_pieceUI.id);
select_pieceUI = null;
}
}
class PieceUI {
public var id:int;
public var cube:Cube;
public function PieceUI(id:int) {
this.id = id;
cube = createCube();
//start();
}
public function pressed(event:InteractiveScene3DEvent):void {
if (Rule.board.side != Rule.board.pieces[id].side) { return; }
Rule.select(this);
Tweener.addTween(cube, {
y: Rule.UNIT_SIZE / 4 + 30,
time:1,
transition: 'easeInOutCubic'
});
}
public function start():void {
cube.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, pressed);
}
public function stop():void {
cube.removeEventListener(InteractiveScene3DEvent.OBJECT_PRESS, pressed);
}
public function createCube():Cube {
var materialKi:BitmapFileMaterial = new BitmapFileMaterial(Rule.IMAGE_URL + Rule.KI_URL);
materialKi.interactive = true
var materialsList:MaterialsList = new MaterialsList( { all:materialKi} );
//materialsList.addMaterial(materialKi, "all")
materialsList.addMaterial(createCompositeMaterial(Rule.board.pieces[id].type), "top")
if (Rule.board.pieces[id].type == "hiyoko") {
materialsList.addMaterial(createCompositeMaterial("niwatori"), "bottom")
}
return new Cube(materialsList, Rule.PIECE_SIZE / 2, Rule.PIECE_SIZE / 2, Rule.PIECE_SIZE / 4, 2, 2, 2);
}
private function createCompositeMaterial(type:String):CompositeMaterial {
var material:CompositeMaterial = new CompositeMaterial();
material.addMaterial(new BitmapFileMaterial(Rule.IMAGE_URL + Rule.PIECE_IMAGE_URL[type]));
material.addMaterial(createDirectionMarkMaterial(type));
material.interactive = true;
return material;
}
private function createDirectionMarkMaterial(type:String):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 (Rule.DIRECTIONS[type][j][i] == 1) {
bd.fillRect(new Rectangle(5 + i*40, 5 + j*40, 10, 10), 0xFFFF0000);
}
}
}
return new BitmapMaterial(bd);
}
public function view():void {
var piece:Piece = Rule.board.pieces[id];
var y:Number = Rule.UNIT_SIZE / 4;
var rotationY:Number = 0;
var rotationZ:Number = 0;
if (!piece.side) {
rotationY = 180;
}
if (piece.type == "niwatori") {
rotationZ = 180;
}
if (!piece.alive) {
y -= 10;
}
Tweener.addTween(cube, {
x: DoubutsuShogi.i_to_x(piece.i),
y: y,
z: DoubutsuShogi.j_to_z(piece.j),
rotationY: rotationY, // turn
rotationZ: rotationZ, // side
time:1,
transition: 'easeInOutCubic'
});
}
}
class Piece {
public var id:int;
public var type:String;
public var i:int;
public var j:int;
public var side:Boolean;
public var alive:Boolean;
public function Piece(id:int, type:String, i:int, j:int, side:Boolean, alive:Boolean) {
this.id = id;
this.type = type;
this.i = i;
this.j = j;
this.side = side;
this.alive = alive;
}
public function move(i:int, j:int):Piece {
var p:Piece = new Piece(this.id, this.type, i, j, this.side, true);
if (p.type == "hiyoko" && this.alive && p.entered()) {
p.type = "niwatori";
}
return p;
}
public function cought():Piece {
var type:String = this.type;
if (type == "niwatori") {
type = "hiyoko";
}
return new Piece(this.id, type, 0, 0, !this.side, false);
}
public function is_movable_direction(i:int, j:int):Boolean {
var di:int = i - this.i;
var dj:int = j - this.j;
if (!this.side) {
di = -di;
dj = -dj;
}
if (Math.abs(di) > 1 || Math.abs(dj) > 1 ) {
return false;
}
return Rule.DIRECTIONS[this.type][dj + 1][di + 1] == 1;
}
public function entered():Boolean {
return (side && j == 1) || (!side && j == 4);
}
}
class Board {
public var pieces:Array= [];
public var side:Boolean;
public function toString():String {
var s:String = "";
for each (var piece:Piece in pieces) {
s += "piece: " + piece.id + ", " + piece.type + ", " + piece.side + ", " + piece.i + ", " + piece.j + "\n";
}
return s;
}
public function Board(side:Boolean) {
this.side = side;
}
public function reset_position():void {
var count_true_side:int = 0;
var count_false_side:int = 0;
for each (var piece:Piece in pieces) {
if (!piece.alive) {
if (piece.side) {
piece.i = -1;
piece.j = 4 - count_true_side;
count_true_side++;
} else {
piece.i = 5;
piece.j = 1 + count_false_side;
count_false_side++;
}
}
}
}
public function is_movable(piece:Piece, i:int, j:int):Boolean {
var target_piece:Piece;
if (!Rule.in_board(i, j)) {
return false;
}
if (piece.side != this.side) {
// そのコマを動かす番じゃないとき
return false;
}
if (piece.alive) {
// コマを動かすとき
if (!piece.is_movable_direction(i, j)) {
// 動かせる方向じゃない場合
return false;
}
target_piece = this.get_piece_by_ij(i, j);
if (target_piece && target_piece.side == piece.side) {
// 自分のコマをとることは出来ない
return false;
}
} else {
// 持ち駒を打つとき
target_piece = this.get_piece_by_ij(i, j);
if (target_piece) {
// 元々コマがあるところには打てない
return false;
}
}
return true;
}
public function move(id:int, i:int, j:int):Board {
var piece:Piece = this.pieces[id];
if (!this.is_movable(piece, i, j)) {
return null;
}
var b:Board = new Board(!side);
b.pieces = this.pieces.slice(0);
if (piece.alive) {
var target_piece:Piece = this.get_piece_by_ij(i, j);
if (target_piece && target_piece.side != piece.side) {
// 元々あった敵のコマをとる
b.change(target_piece.cought());
}
}
b.change(piece.move(i, j));
return b;
}
public function change(piece:Piece):void {
this.pieces[piece.id] = piece;
}
public function is_lose():Boolean {
var tora:Piece = this.own_tora();
// 自分のトラがいなくて負け
return !tora;
}
public function is_win():Boolean {
var tora:Piece = this.own_tora();
// 自分のトラが相手のエリアにいて勝ち
return tora != null && tora.entered();
}
public function own_tora():Piece {
var piece:Piece = this.pieces[this.side ? 0 : 1];
if (piece.side != this.side) {
return null;
}
return piece;
}
public var _pieces_by_ij:Array;
public function get_piece_by_ij(i:int, j:int):Piece {
if (this._pieces_by_ij == null) {
var ps:Array = [[null,null,null],[null,null,null],[null,null,null],[null,null,null]];
for (var id:int = 0; id < 8; id++) {
var piece:Piece = this.pieces[id];
if (piece.alive) {
ps[piece.j - 1][piece.i - 1] = piece;
}
}
this._pieces_by_ij = ps;
}
return this._pieces_by_ij[j - 1][i - 1];
}
public function next_board_best_with_point(n:int):Array {
//var tab:String = "";
//for (var k:int = 0; k < (4 - n); k++) {
// tab += " ";
//}
//log(tab + "next_board_best_with_point(" + n + ")");
//var boards_win:Array = [];
var boards_lose:Array = [];
var boards_other:Array = [];
for (var piece_id:int = 0; piece_id < 8; piece_id++) {
for (var x:int = 1; x <= 3; x++) {
for (var y:int = 1; y <= 4; y++) {
if (this.is_movable(this.pieces[piece_id], x, y)) {
//log(tab + "is_movable(this.pieces[" + piece_id + "], " + x + ", " + y + ")");
var b:Board = this.move(piece_id, x, y);
if (b.is_win()) {
// 相手が勝った場合
boards_lose.push(b);
} else if (b.is_lose()) {
// 相手が負けた場合
//boards_win.push(b);
return [b, 1];
} else {
boards_other.push(b);
}
}
}
}
}
//if (boards_win.length != 0) {
// return [Rule.random_choose(boards_win), 1];
//}
if (boards_other.length != 0) {
if (n == 0) {
return [Rule.random_choose(boards_other), 1/2];
}
// その次の相手の最善手で、相手にとって一番悪い手を選ぶ
var worst_i:int = 0;
var worst_point:int = 1;
var boards_other_best:Array = [];
for (var i:int = 0; i < boards_other.length; i++) {
var b2:Board = boards_other[i];
var b_point:Array = b2.next_board_best_with_point(n - 1);
var point:int = b_point[1];
if (point == worst_point) {
boards_other_best.push(b2);
}
if (point < worst_point) {
boards_other_best = [b2];
worst_point = point;
}
}
// 相手の最善手の点数を逆にして、1/2に点数を上に縮めて返す
return [Rule.random_choose(boards_other_best), 1/2 + (1-worst_point)/2];
}
return [Rule.random_choose(boards_lose), 0];
}
}
import org.papervision3d.Papervision3D;
import org.papervision3d.core.geom.*;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.NumberUV;
import org.papervision3d.core.proto.*;
/**
* The Cylinder class lets you create and display Cylinders.
* <p/>
* The Cylinder is divided in vertical and horizontal segment, the smallest combination is two vertical and three horizontal segments.
*/
/*public*/ class Cylinder extends TriangleMesh3D
{
/**
* Number of segments horizontally. Defaults to 8.
*/
public var segmentsW :Number;
/**
* Number of segments vertically. Defaults to 6.
*/
public var segmentsH :Number;
/**
* Default radius of Cylinder if not defined.
*/
static public const DEFAULT_RADIUS :Number = 100;
/**
* Default height if not defined.
*/
static public const DEFAULT_HEIGHT :Number = 100;
/**
* Default scale of Cylinder texture if not defined.
*/
static public const DEFAULT_SCALE :Number = 1;
/**
* Default value of gridX if not defined.
*/
static public const DEFAULT_SEGMENTSW :Number = 8;
/**
* Default value of gridY if not defined.
*/
static public const DEFAULT_SEGMENTSH :Number = 6;
/**
* Minimum value of gridX.
*/
static public const MIN_SEGMENTSW :Number = 3;
/**
* Minimum value of gridY.
*/
static public const MIN_SEGMENTSH :Number = 1;
//public var topFace
// ___________________________________________________________________________________________________
// N E W
// NN NN EEEEEE WW WW
// NNN NN EE WW WW WW
// NNNNNN EEEE WWWWWWWW
// NN NNN EE WWW WWW
// NN NN EEEEEE WW WW
/**
* Create a new Cylinder object.
* <p/>
* @param material A MaterialObject3D object that contains the material properties of the object.
* <p/>
* @param radius [optional] - Desired radius.
* <p/>
* @param segmentsW [optional] - Number of segments horizontally. Defaults to 8.
* <p/>
* @param segmentsH [optional] - Number of segments vertically. Defaults to 6.
* <p/>
* @param topRadius [optional] - An optional parameter for con- or diverging cylinders.
* <p/>
* @param topFace [optional] - An optional parameter specifying if the top face of the cylinder should be drawn.
* <p/>
* @param bottomFace [optional] - An optional parameter specifying if the bottom face of the cylinder should be drawn.
* <p/>
*/
public function Cylinder( material:MaterialObject3D=null, radius:Number=100, height:Number=100, segmentsW:int=8, segmentsH:int=6, topRadius:Number=-1, topFace:Boolean=true, bottomFace:Boolean=true,topMat:MaterialObject3D = null ,bottomMat:MaterialObject3D = null)
{
super( material, new Array(), new Array(), null );
this.segmentsW = Math.max( MIN_SEGMENTSW, segmentsW || DEFAULT_SEGMENTSW); // Defaults to 8
this.segmentsH = Math.max( MIN_SEGMENTSH, segmentsH || DEFAULT_SEGMENTSH); // Defaults to 6
if (radius==0) radius = DEFAULT_RADIUS; // Defaults to 100
if (height==0) height = DEFAULT_HEIGHT; // Defaults to 100
if (topRadius==-1) topRadius = radius;
var scale :Number = DEFAULT_SCALE;
buildCylinder( radius, height, topRadius, topFace, bottomFace,topMat,bottomMat );
}
private function buildCylinder( fRadius:Number, fHeight:Number, fTopRadius:Number, fTopFace:Boolean, fBottomFace:Boolean ,topMat:MaterialObject3D,bottomMat:MaterialObject3D):void
{
var matInstance:MaterialObject3D = material;
var i:Number, j:Number, k:Number;
var iHor:Number = Math.max(MIN_SEGMENTSW, this.segmentsW);
var iVer:Number = Math.max(MIN_SEGMENTSH, this.segmentsH);
var aVertice:Array = this.geometry.vertices;
var aFace:Array = this.geometry.faces;
var aVtc:Array = new Array();
for (j=0;j<(iVer+1);j++) { // vertical
var fRad1:Number = Number(j/iVer);
var fZ:Number = fHeight*(j/(iVer+0))-fHeight/2;//-fRadius*Math.cos(fRad1*Math.PI);
var fRds:Number = fTopRadius+(fRadius-fTopRadius)*(1-j/(iVer));//*Math.sin(fRad1*Math.PI);
var aRow:Array = new Array();
var oVtx:Vertex3D;
for (i=0;i<iHor;i++) { // horizontal
var fRad2:Number = Number(2*i/iHor);
var fX:Number = fRds*Math.sin(fRad2*Math.PI);
var fY:Number = fRds*Math.cos(fRad2*Math.PI);
//if (!((j==0||j==iVer)&&i>0)) { // top||bottom = 1 vertex
oVtx = new Vertex3D(fY,fZ,fX);
aVertice.push(oVtx);
//}
aRow.push(oVtx);
}
aVtc.push(aRow);
}
var iVerNum:int = aVtc.length;
var aP4uv:NumberUV, aP1uv:NumberUV, aP2uv:NumberUV, aP3uv:NumberUV;
var aP1:Vertex3D, aP2:Vertex3D, aP3:Vertex3D, aP4:Vertex3D;
for (j=0;j<iVerNum;j++) {
var iHorNum:int = aVtc[j].length;
for (i=0;i<iHorNum;i++) {
if (j>0&&i>=0) {
// select vertices
var bEnd:Boolean = i==(iHorNum-0);
aP1 = aVtc[j][bEnd?0:i];
aP2 = aVtc[j][(i==0?iHorNum:i)-1];
aP3 = aVtc[j-1][(i==0?iHorNum:i)-1];
aP4 = aVtc[j-1][bEnd?0:i];
// uv
var fJ0:Number = j / iVerNum;
var fJ1:Number = (j-1) / iVerNum;
var fI0:Number = (i+1) / iHorNum;
var fI1:Number = i / iHorNum;
aP4uv = new NumberUV(fI0,fJ1);
aP1uv = new NumberUV(fI0,fJ0);
aP2uv = new NumberUV(fI1,fJ0);
aP3uv = new NumberUV(fI1,fJ1);
// 2 faces
aFace.push( new Triangle3D(this, [aP1,aP2,aP3], matInstance, [aP1uv,aP2uv,aP3uv]) );
aFace.push( new Triangle3D(this, [aP1,aP3,aP4], matInstance, [aP1uv,aP3uv,aP4uv]) );
}
}
if (j==0||j==(iVerNum-1)) {
for (i=0;i<(iHorNum-2);i++) {
// uv
var iI:int = Math.floor(i/2);
aP1 = aVtc[j][iI];
aP2 = (i%2==0)? (aVtc[j][iHorNum-2-iI]) : (aVtc[j][iI+1]);
aP3 = (i%2==0)? (aVtc[j][iHorNum-1-iI]) : (aVtc[j][iHorNum-2-iI]);
var bTop:Boolean = j==0;
aP1uv = new NumberUV( (bTop?1:0)+(bTop?-1:1)*(aP1.x/fRadius/2+.5), aP1.z/fRadius/2+.5 );
aP2uv = new NumberUV( (bTop?1:0)+(bTop?-1:1)*(aP2.x/fRadius/2+.5), aP2.z/fRadius/2+.5 );
aP3uv = new NumberUV( (bTop?1:0)+(bTop?-1:1)*(aP3.x/fRadius/2+.5), aP3.z/fRadius/2+.5 );
// face
if (j == 0) {
if(bottomMat)
{
if (fBottomFace) aFace.push( new Triangle3D(this, [aP1, aP3, aP2], bottomMat, [aP1uv, aP3uv, aP2uv]) );
}
else
{
if (fBottomFace) aFace.push( new Triangle3D(this, [aP1, aP3, aP2], matInstance, [aP1uv, aP3uv, aP2uv]) );
}
}
else {
if(topMat)
{
if (fTopFace) aFace.push( new Triangle3D(this, [aP1, aP2, aP3], topMat, [aP1uv, aP2uv, aP3uv]));
}
else
{
if (fTopFace) aFace.push( new Triangle3D(this, [aP1, aP2, aP3], matInstance, [aP1uv, aP2uv, aP3uv]));
}
}
}
}
}
this.geometry.ready = true;
if(Papervision3D.useRIGHTHANDED)
this.geometry.flipFaces();
}
}