module br.enemyImpl;
private import str = std.string;
private import util.basis;
private import util.parts;
private import util.shape;
private import util.vector;
private import util.matrix;
private import util.log;
private import util.particle;
private import util.ring;
private import util.animation;
private import util.animationImpl;
private import br.shapeImpl;
private import br.gamemanager;
private import br.enemy;
private import br.bullet;
private import br.append;
private import br.stage;
private import br.sound;
private import std.math;
private import opengl;

public Enemy makeEnemy(char[] name ,double x,double y,double z ,double aim ,Object[] o = null){
	switch(name){
		case "stillEnemy":		return new StillEnemy(x,y,z);
		case "enemy1":				return new Enemy1(new Vector3(x ,y ,z),aim);
		case "enemy2":				return new Enemy2(new Vector3(x ,y ,z),aim);
		case "wall":				return new Wall(new Vector3(x ,y ,z),aim);
		case "homingEnemy":				return new HomingEnemy(new Vector3(x ,y ,z),aim);
		case "chaseEnemy":				return new ChaseEnemy(new Vector3(x ,y ,z) ,aim);
		case "foldEnemy":				return new FoldEnemy(new Vector3(x ,y ,z) ,aim);
		case "sidewayEnemy":				return new SidewayEnemy(new Vector3(x ,y ,z),aim);
		case "fourwayEnemy":				return new FourwayEnemy(new Vector3(x ,y ,z),aim);
		case "boundEnemy":			return new BoundEnemy(new Vector3(x ,y ,z) ,aim);
		case "turretEnemy":				return new TurretEnemy(new Vector3(x ,y ,z),aim);
		case "enemy3D":				return new Enemy3D(new Vector3(x ,y ,z),o[0]);
		case "bird":					return new Bird(x,y,z,aim);
		case "wideSlowEnemy":	return new WideSlowEnemy(x,y,z,aim);
		case "thrustEnemy":	return new ThrustEnemy(x,y,z,aim);
		case "upLaserEnemy":	return new UpLaserEnemy(x ,y ,z ,aim);
		case "downLaserEnemy":	return new DownLaserEnemy(x ,y ,z ,aim);
		case "middleEnemy1":	return new MiddleEnemy1(x,y,z,aim);
		case "zab":				return new Zab(x ,y ,z);
		case "backBone":		return new BackBone(x,y,z);
		case "boss1":			return new Boss1(x ,y ,z ,aim);
		case "boss2":			return new Boss2(x ,y ,z ,aim);
		case "boss3":			return new Boss3(x ,y ,z ,aim);
		case "boss4":			return new Boss4(x ,y ,z ,aim);
		case "boss5":			return new Boss5(x ,y ,z ,aim);
		case "boss6":			return new Boss6(x ,y ,z ,aim);
		case "boss7":			return new Boss7(x ,y ,z ,aim);
		case "boss8":			return new Boss8(x ,y ,z ,aim);
		case "boss8imitate":	return new Boss8imitate(x ,y ,z ,aim);
//		case "boss7":			return new Boss7(x ,y ,z ,aim);
		default:							return null;
	}
	
	return null;
}

public class EnemyAppend:Enemy{
	private:
	int vanishCount;
	bool parentExist;
	public this(Shape shape ,double size ,double hp ,double R = -1.0,double G = -1.0 ,double B = -1.0,double alpha = -1.0 ,Matrix poseBase = new Matrix()){
		super(hp ,R ,G ,B ,alpha);
		this.shape = cast(Shape)shape.clone();
//		Log_write("a");
//		drawing = WIRE ;
		this.size = size;
		setPoseBase(poseBase);
		parentExist = true;
	}
	
	public void setCollision(double collisionSize = -1){
		
//		Log_write("b");
		drawing = WIRE | POLYGON;
		
		collisionManager.add(this, collisionManager.kind.SHIP ,2);
		collisionManager.add(this, collisionManager.kind.SWORD ,2);
		if(collisionSize > 0){
			this.collisionRange = collisionSize;
		}else this.collisionRange = size / 2.0;
		
//		parentExist = true;
	}
	
	public void move(){
		super.move();
		
		
		if(parentExist & (parent is null || parent.exists == false)){
			parentExist = false;
			vanishCount = 5;
			
		}
		if(parentExist == false){
			vanishCount --;
			if(vanishCount < 0)destroy();
		}
	}
	public void destroy(){
		super.destroy();
		makeParticle(shape, size ,WIRE ,rpos ,new Vector3() ,rpose ,R ,G ,B ,alpha);
	}
	public void reportRing(Ring ring){
	}
}
public class Turret:EnemyAppend{
	public this(){
		super(TurretShape1.getShape() ,30 ,-1);
		collisionRange = 15;
	}
	public void reportRing(Ring ring){
		
			Vector3 po = vec3translate(new Vector3(1.0 ,0.0 ,0.0), rpose);
			new Enemy1(rpos , atan2(po.y ,po.x));
			
	}
}
public class Turret2:EnemyAppend{
	public this(int size,int hp){
		super(TurretShape2.getShape() ,size ,hp);
		collisionRange = size / 2.0;
	}
	public void reportRing(Ring ring){
		switch(ring.name){
			case "missile":
			int term = rand.nextInt(20) + 40;
			new Missile(rpos ,rposeZ*PI/180 ,term ,5.0);
			break;
			case "laser":
			new Missile(rpos ,rposeZ*PI/180 ,1000 ,8.0 ,2.0);
			break;
			case "bomb":
			new Missile(rpos ,rposeZ*PI/180 ,20 ,3.0);
			break;
			default:break;
		}
	}

}

public class Turret3:EnemyAppend{
	public this(int size){
		super(TurretShape3.getShape() ,size ,4);
		collisionRange = size / 2.0;
	}
	public void reportRing(Ring ring){
		switch(ring.name){
			case "shot":
			double aim =  rposeZ*PI/180.0;
			new Enemy1(rpos , aim,4.0);
			break;
			case "reflectshot":
			double aim =  rposeZ*PI/180.0;
			new ReflectEnemy(rpos , aim,6.0);
			break;
			
			/*
			case "wall":
			double aim ,bendAim;
			if(rpos.y < 0){
				aim = PI /2.0;
				bendAim = -PI / 2.0;
			}else{
				aim = -PI/2.0;
				bendAim = PI/2.0;
			}
			for(double d = 0;d < 20;d +=0.5){
				new BendBullet(rpos ,true , aim,bendAim ,30 ,d ,3.0);
			}
			
			break;
			*/
			default:break;
		}
	}
}

public class NoseTurret:EnemyAppend{
	public this(int size,int hp){
		super(NoseShape.getShape() ,size ,hp);
		collisionRange = size / 2.0;
	}
	public void reportRing(Ring ring){
		
	}

}
public class WingTurret:EnemyAppend{
	public this(int size){
		super(Wing.getShape() ,size ,-1);
		collisionRange = -1;
	}
	public void reportRing(Ring ring){
		Vector3 po = ship.rpos - rpos;
		double aim =  atan2(po.y ,po.x);
		new Enemy2(rpos , aim,2.0);
	}
}
public class HeadTurret:EnemyAppend{
	public this(int size){
		super(Head.getShape() ,size ,-1);
		collisionRange = -1;
	}
	public void reportRing(Ring ring){
		Vector3 po = vec3translate(new Vector3(1.0 ,0.0 ,0.0), rpose);
		double aim =  atan2(po.y ,po.x);
		new Bullet3D(rpos + vec3Normalize(new Vector3(po.y ,-po.x ,po.z)) * 10.0,true , aim,4.0);
		new Bullet3D(rpos + vec3Normalize(new Vector3(-po.y ,po.x ,po.z)) * 10.0,true , aim,4.0);
	}
}
public class TailTurret:EnemyAppend{
	public this(int size){
		super(Tail.getShape() ,size ,-1);
		collisionRange = -1;
	}
	public void reportRing(Ring ring){
		Vector3 po = ship.rpos - rpos;//vec3translate(new Vector3(1.0 ,0.0 ,0.0), rpose);
		double aim =  atan2(po.y ,po.x);
		new Enemy2(rpos , aim,3.0);
//		new Enemy3D(rpos , (vec3Normalize(po) + new Vector3(0 ,0 ,0.3)) * 3.0);
	}
}
public class HeadTurret2:EnemyAppend{
	public this(int size){
		super(Head2.getShape() ,size ,-1);
		collisionRange = -1;
	}
	public void reportRing(Ring ring){
		for(double aim = PI; -PI <= aim;aim -= PI/6.0){
			new BombEnemy(rpos ,aim ,4.0);
		}
	}
}
public class ArmTurret:EnemyAppend{
	public this(int size){
		super(ArmShape.getShape() ,size ,-1);
		collisionRange = -1;
	}
	public void reportRing(Ring ring){
		
		new BombEnemy(rpos ,-PI/2.0);
		
	}
}
public class TailTurret2:EnemyAppend{
	public this(int size){
		super(ArmShape.getShape() ,size ,-1);
		collisionRange = -1;
	}
	public void reportRing(Ring ring){
		switch(ring.name){
			case "shot":
			Vector3 po = ship.rpos - rpos;//vec3translate(new Vector3(1.0 ,0.0 ,0.0), rpose);
			double aim =  atan2(po.y ,po.x);
			new AccBullet(rpos ,true , aim,1.0 ,5.0 ,0.1);
			break;
			case "eightway":
			double rad = cast(double)cnt /180.0*PI;
			for(double aim=-PI;aim<PI;aim+= PI/2.0){
				new AccBullet(rpos ,true , aim+rad,0.0 ,6.0 ,0.1);
			}
			for(double aim=-PI;aim<PI;aim+= PI/2.0){
				new Enemy1(rpos , aim+rad+PI/4.0,3.0);
			}
			break;
			default:break;
		}
//		new Enemy3D(rpos , (vec3Normalize(po) + new Vector3(0 ,0 ,0.3)) * 3.0);
	}
}
public class Joint1:EnemyAppend{
	public this(){
		super(Octahedron.getShape() ,30 ,7);
		collisionRange = 15;
	}
	public void reportRing(Ring ring){
		
	}
}
public class JointTurret:EnemyAppend{
	public this(double size ,double hp){
		super(JointShape.getShape() ,size ,hp);
		
	}
	public void reportRing(Ring ring){
		switch(ring.name){
			case "homing":
			new HomingEnemy2(rpos ,PI+atan2(rpos.y ,rpos.x) ,4.0 ,1.2 ,PI/180 ,5);
			break;
			case "reflect":
			new ReflectEnemy(rpos ,atan2(rpos.y ,rpos.x) ,2.0 ,ReflectEnemy.UP|ReflectEnemy.DOWN|ReflectEnemy.LEFT|ReflectEnemy.RIGHT ,2.5);
			for(double a=-PI;a<PI;a+=PI/2.0){
				new StraightBullet(rpos ,true ,a+PI+atan2(rpos.y ,rpos.x) ,0.5);
			}
//			Vector3 pos,double aim ,double speed = 2.0 ,uint border = UP | DOWN ,double hp = 1.0)
			break;
			case "wave":
			double taim = atan2(rpos.y ,rpos.x);
			for(double a=-PI/3.0;a<=PI/3.0;a+=PI/12.0){
				new AccBullet(rpos ,true ,taim+a ,0.0 ,4.0 ,0.1);
				
			}
			/*
			for(double a=-PI/3.0;a<=PI/3.0;a+=PI/3.0){
				new Enemy1(rpos ,taim + a + PI , 2.0 ,1.2);
			}
			*/
			break;
			
			default:break;
			
		}
//		Vector3 pos,double aim ,double speed = 2.0 ,double hp = 1.0 ,int num = 1)
	}
}

public class Arm:EnemyAppend{
	public this(){
		super(Octahedron.getShape() ,20 ,8);
		collisionRange = 10;
	}
	public void move(){
		super.move();
		rotate(POSEZ ,daimmark(rposeZ ,atan2(ship.rpos.y -rpos.y ,ship.rpos.x -rpos.x) * 180.0 /PI) * 2.0);
		foreach(Parts child;childs){
			child.rotate(LINKZ ,daimmark(rposeZ ,atan2(ship.rpos.y -rpos.y ,ship.rpos.x -rpos.x) * 180.0 /PI) * 2.0);
		}
	}
	public void reportRing(Ring ring){
		switch(ring.name){
			case "shot":
//			new StraightBullet();
			break;
			default:break;
		}
	}
}
public class NailTurret:EnemyAppend{
	public this(int size){
		super(NailShape.getShape() ,size ,-1);
		collisionRange = size / 2.0;
	}
	public void reportRing(Ring ring){
//		Vector3 po = ship.rpos - rpos;
		switch(ring.name){
			case "reflect":
			double aim =  rposeZ*PI/180.0;
			new ReflectEnemy(rpos , aim,6.0);
			break;
			case "wall":
			double aim ,bendAim;
			if(rpos.y < 0){
				aim = PI /2.0;
				bendAim = -PI / 2.0;
			}else{
				aim = -PI/2.0;
				bendAim = PI/2.0;
			}
			for(double d = 0;d < 20;d +=0.5){
				new BendBullet(rpos ,true , aim,bendAim ,30 ,d ,3.0);
			}
			break;
			default:break;
		}
	}
}



public class Enemy1:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
		double aim;
		double speed;
		public this(Vector3 pos,double aim ,double speed = 2.0 ,double hp = 1.0){
			super(hp);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
			}
    	shape = cast(Shape)baseShape.clone();
			size =  25;
		
			collisionRange = 12;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
			this.speed = speed;
		}
	public void  move(){
		super.move();
/*		if(cnt % 30 == 0){
			new AttackRing(this ,"shot",30);
			
		}
		*/	
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		poseZ += 3;
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class Enemy2:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
		double aim;
		double speed;
		public this(Vector3 pos,double aim ,double speed = 2.0 ,double hp = 1.0 ,int num = 1){
			super(hp);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,6);
			}
    	shape = cast(Shape)baseShape.clone();
			size =  25;
		
			collisionRange = 12;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
			this.speed = speed;
			num --;
			if(0 < num){
				Parts p = new Enemy2(pos ,aim ,speed ,hp ,num);
				addChild(p ,"f1",50 ,FOLLOW);
			}
		}
	public void  move(){
		super.move();
		if(parent is null){
	/*		if(cnt % 30 == 0){
				new AttackRing(this ,"shot",30);
				
			}
			*/	
			if(rpos.z < -800 - 4)pos.z +=4.0;
			else if(-800 + 4 < rpos.z)pos.z -= 4.0;
			else{
				pos.x += speed * cos(aim);
				pos.y += speed * sin(aim);
			}
		}
		poseZ += 3;
		
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class HomingEnemy2:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.3]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
		double aim;
		double daim;
		double speed;
		public this(Vector3 pos,double aim ,double speed = 2.0 ,double hp = 1.0 ,double daim = PI/180.0 ,int num = 1){
			super(hp);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
			}
    	shape = cast(Shape)baseShape.clone();
			size =  25;
		
			collisionRange = 12;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
			this.speed = speed;
			this.daim = daim;
			num --;
			if(0 < num){
				Parts p = new HomingEnemy2(pos ,aim ,speed ,hp ,daim ,num);
				addChild(p ,"f1",40 ,FOLLOW);
			}
		}
	public void  move(){
		super.move();
		if(parent is null){
	/*		if(cnt % 30 == 0){
				new AttackRing(this ,"shot",30);
				
			}
			*/	
			if(rpos.z < -800 - 4)pos.z +=4.0;
			else if(-800 + 4 < rpos.z)pos.z -= 4.0;
			else{
				double taim = atan2(ship.rpos.y-rpos.y ,ship.rpos.x-rpos.x);
				if(abs(aim-taim)<daim){}
				else if(raimmark(aim ,taim) < 0)aim -= daim;
				else aim += daim;
				
				pos.x += speed * cos(aim);
				pos.y += speed * sin(aim);
			}
		}else aim = (cast(HomingEnemy2)parent).aim;
		if(0.0 < daim)daim -= PI/180000;
		else daim = 0.0;
		poseZ = aim*180.0/PI;
		
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class Wall:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,-0.8 ,0.0 ,0.8 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,0.9 ,1.0 ,0.9 ,0.0]
  	];
		double aim;
		double speed;
		public this(Vector3 pos,double aim ,double speed = 2.5 ,double hp = 2.0){
			super(hp);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
			}
    	shape = cast(Shape)baseShape.clone();
			size =  30;
		
			collisionRange = 20;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
			this.speed = speed;
		}
	public void  move(){
		super.move();
/*		if(cnt % 30 == 0){
			new AttackRing(this ,"shot",30);
			
		}
		*/	
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class ReflectEnemy:Enemy{
	public:
	static enum {
		UP=1 ,DOWN = 2 ,LEFT = 4 ,RIGHT = 8
	};
	private:
	static Shape baseShape;
	
	/*
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
	*/
//		double aim;
		uint border;
		Vector3 vel;
		double speed;
		public this(Vector3 pos,double aim ,double speed = 2.0 ,uint border = UP | DOWN ,double hp = 1.0){
			super(hp);
			
			if(baseShape is null){
			baseShape = new SH_Sphere(1.0 ,6);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  25;
		
			collisionRange = 12;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
//			this.aim = aim;
			this.speed = speed;
			this.vel = new Vector3(speed * cos(aim) ,speed * sin(aim) ,0);
			this.border = border;
//			Log_write("!");
		}
	public void  move(){
		super.move();
/*		if(cnt % 30 == 0){
			new AttackRing(this ,"shot",30);
			
		}
		*/
		
		if(border & UP){
			if(screen.GAME_UP < rpos.y){
				vel = new Vector3(vel.x ,-vel.y,vel.z);
				pos.y = screen.GAME_UP;
			}
		}
		if(border & DOWN){
			if(rpos.y < screen.GAME_DOWN){
				vel = new Vector3(vel.x ,-vel.y,vel.z);
				pos.y = screen.GAME_DOWN;
			}
		}
		if(border & LEFT){
			if(rpos.x < screen.GAME_LEFT ){
				vel = new Vector3(-vel.x ,vel.y,vel.z);
				pos.x = screen.GAME_LEFT;
			}
		}
		if(border & RIGHT){
			if(screen.GAME_RIGHT  < rpos.x){
				vel = new Vector3(-vel.x ,vel.y,vel.z);
				pos.x = screen.GAME_RIGHT;
			}
		}
		pos += vel;	
		
		
		
		poseZ += 4.0;
		poseY += 1.0;
//		pos.x += speed * cos(aim);
//		pos.y += speed * sin(aim);
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class BombEnemy:Enemy{
	
	private:
	static Shape baseShape;
	
	
	static  float[][] a = 
		[
			[-1.2 , -0.4 ,0.0 ,0.4 ,1.2],
			[-1.2 , -0.4 ,0.0 ,0.4 ,1.2]
  	   ];
  	static float[][] b =
		[
			[0.0 , 0.4 ,1.2  ,0.4 ,0.0],
			[0.0 , 0.4 ,0.6  ,0.4 ,0.0]
  	];
	
//		double aim;
		Vector3 vel;
		double speed;
		public this(Vector3 pos,double aim ,double speed = 2.0  ,double hp = 2.5){
			super(hp);
			
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,8);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  35;
		
			collisionRange = 15;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
//			this.aim = aim;
			this.speed = speed;
			this.vel = new Vector3(speed * cos(aim) ,speed * sin(aim) ,0);
//			Log_write("!");
		}
	public void  move(){
		super.move();

		
		if(rpos.z < -800-2.0)pos.z+=2.0;
		else if(-800+2.0 < rpos.z)pos.z-=2.0;
		else{
			if(screen.GAME_UP < rpos.y){
				vel = new Vector3();
				
				new AttackRing(this ,"up" ,20);
			}
		
			if(rpos.y < screen.GAME_DOWN){
				vel = new Vector3();
				new AttackRing(this ,"down" ,20);
			}
			
			if(rpos.x < screen.GAME_LEFT ){
				vel = new Vector3();
				new AttackRing(this ,"left" ,20);
			}
		
			if(screen.GAME_RIGHT  < rpos.x){
				vel = new Vector3();
				new AttackRing(this ,"right" ,20);
			}
			
			pos += vel;	
		
		
		}
		
		
		
		poseZ += 4.0;
		poseY += 3.0;
//		pos.x += speed * cos(aim);
//		pos.y += speed * sin(aim);
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
		double aim = 0.0;
		switch(ring.name){
			case "up":aim = -PI / 2.0;break;
			case "down":aim = PI / 2.0;break;
			case "left":aim = 0.0 ;break;
			case "right":aim = PI;break;
			default:break;
		}
		for(double s=3.0;s<10.0;s+=0.5){
			new Enemy1(rpos ,aim ,s ,0.6);
			
		}
		destroy();
	}
	
}
public class BoundEnemy:Enemy{
	private:
	static Shape baseShape;
	Vector3 vel;
	double acc;
	int bnum;
		public this(Vector3 pos,double aim ,double speed = 2.0 ,double acc = 0.1,double hp = 1.6){
			super(hp);
			
			if(baseShape is null){
				baseShape = new SH_Sphere(1.0,7);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  30;
		
			collisionRange = 15;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.acc = acc;
			vel = new Vector3(speed * cos(aim) ,speed * sin(aim) ,0.0);
			bnum = 1;
		}
	public void  move(){
		super.move();

		pos += vel;
		vel.y -= acc;
		if(rpos.y < screen.GAME_DOWN){
			if(bnum <= 3){
				vel.y = -vel.y * 2.0 / 3.0;
				pos.y = screen.GAME_DOWN;
				bnum ++;
			}
			
		}
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class Missile:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,-0.7 ,-0.4 ,1.5 ,2.0]
  	   ];
  	static float[][] b =
		[
			[0.6  ,0.4  ,0.6  ,0.6 ,0.0]
  	];
		double aim;
		double speed;
		int term;
		double acc;
		public this(Vector3 pos,double aim ,int term = 60 ,double speed = 4.0 ,double hp = 1.6){
			super(hp);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,6);
			}
    	shape = cast(Shape)baseShape.clone();
			size =  40;
		
			collisionRange = 20;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
			this.speed = 0.0;
			this.acc = speed / 45.0;
			this.term = term;
		}
	public void  move(){
		super.move();
		if(cnt < 45)speed += acc;
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		poseZ = aim*180.0/PI;
		if(cnt == term)new AttackRing(this ,"all" ,60);
	}
	public void reportRing(Ring ring){
		for(double a=-PI;a<PI;a+=PI/8.0){
		
			new AccBullet(pos ,true,a  ,0.0 ,4.0 ,0.02);
		}
		destroy();
	}
	
}
public class HomingEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,-0.4 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,0.8 ,0.6 ,0.0]
  	];
		double aim;
		double speed;
		double maxSpeed;
		Vector3 vel;
		public this(Vector3 pos,double aim ,double speed = 0.2 ,double maxSpeed = 5.0){
			super(2.0);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  30;
			disableBorder();
		
			collisionRange = 15;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
			this.speed = speed;
			this.maxSpeed = maxSpeed;;
			vel = new Vector3();
		}
	public void  move(){
		super.move();
		if(rpos.z < -800 - 4)pos.z +=4.0;
		else if(-800 + 4 < rpos.z)pos.z -= 4.0;
		else{
			if(cnt % 10 == 0){
				new AttackRing(this ,"shot",30);
				
			}
			
			pos += vel;	
		}
		double taim = atan2(ship.pos.y-pos.y ,ship.pos.x-pos.x);
		if(abs(aim -taim) < PI / 90.0){}
		else if(raimmark(aim ,taim) < 0)aim -= PI / 90.0;
		else aim += PI / 90.0;
		
		aim = radlimit(aim);
		vel.x += speed * cos(aim);
		vel.y += speed * sin(aim);
		
		if(maxSpeed < vel.x)vel.x = maxSpeed;
		else if(vel.x < -maxSpeed)vel.x = -maxSpeed;
		if(maxSpeed < vel.y)vel.y = maxSpeed;
		else if(vel.y < -maxSpeed)vel.y = -maxSpeed;
		if(maxSpeed < vel.z)vel.z = maxSpeed;
		else if(vel.z < -maxSpeed)vel.z = -maxSpeed;
		poseZ = aim*180.0/PI;
	
	}
	public void reportRing(Ring ring){
		new StraightBullet(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x) ,0.5);
	}
	
}

public class FoldEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
		double aim;
		double speed;
		int term;
		double acc;
		public this(Vector3 pos,double aim = 0.0,int term = 60 ,double minSpeed = 2.0 ,double maxSpeed = -4.0,double hp = 0.5){
			super(hp);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,6);
			}
    	shape = cast(Shape)baseShape.clone();
			size =  30;
			collisionRange = 15;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = atan2(this.pos.y ,this.pos.x);
			this.speed = minSpeed;
			this.acc = (maxSpeed -minSpeed) / 90.0;
			this.term = term;
		}
	public void  move(){
		super.move();
		if(cnt < 120)speed += acc;
		if(speed < 0.0){
			speed = -speed;
			acc = -acc;
			aim =aim + PI;
		}
		
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		poseZ = aim*180.0/PI;
		if(cnt == 0)new AttackRing(this ,"shot" ,30);
	}
	public void reportRing(Ring ring){
		
		new StraightBullet(pos ,true,atan2(-this.pos.y ,-this.pos.x)  ,1.5 );
		
//		destroy();
	}
	
}
public class ChaseEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,-1.3 ,0.3 ,1.3],
			[-1.0 ,-0.5 ,0.3 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.3 ,0.6 ,0.0],
			[0.0 ,0.7 ,0.5 ,0.2]
  	];
		double vx ,vy;
//		int term;
//		double acc;
		public this(Vector3 pos,double aim = 0.0,double speed = 0.0 ,double hp = 3.0){
			super(hp);
			if(baseShape is null){
				baseShape = new SH_Pole(a ,b ,4);
			}
   	 		shape = cast(Shape)baseShape.clone();
			disableBorder();
			
			size =  30;
			collisionRange = 15;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
//			this.speed = speed;
			this.vx = speed * cos(aim);
			this.vy = speed * sin(aim);

		}
	public void  move(){
		super.move();
		if(abs(rpos.x - ship.rpos.x) < size){}
		else if(rpos.x < ship.rpos.x)vx += 0.1;
		else vx -= 0.2;
		vx = fmin(12.0 ,fmax(-8.0 ,vx));
		if(abs(rpos.y - ship.rpos.y)<size){}
		else if(rpos.y < ship.rpos.y)vy += 0.2;
		else vy -= 0.2;
		vy = fmin(4.0 ,fmax(-4.0 ,vy));
		
		pos.x += vx;
		pos.y += vy;
		
		poseZ = 0;
		poseX = 90.0 + vy*7.5;
		
		if(cnt % 60 == 0)new AttackRing(this ,"shot" ,30);
	}
	public void reportRing(Ring ring){
		double aim = atan2(ship.rpos.y-this.rpos.y ,ship.rpos.x-this.rpos.x);
		for(double r=-PI/6.0;r<PI/6.0;r+=PI/32.0){
			new AccBullet(pos ,true, aim+r, 0.0 ,3.5 ,0.05 );
		}
		
//		destroy();
	}
	
}

public class SidewayEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,-0.4 ,0.0 ,1.0],
			[-1.0 ,-0.4 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,0.5 ,0.4 ,0.0],
			[0.0 ,0.8 ,0.6 ,0.0]
  	];
		double aim;
		double speed;
		double maxSpeed;
		Vector3 vel;
		public this(Vector3 pos,double aim ,double speed = 0.2 ,double maxSpeed = 5.0){
			super(1.5);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  30;
		
		
			collisionRange = 15;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
			this.speed = speed;
			this.maxSpeed = maxSpeed;;
			vel = new Vector3(speed * cos(aim) ,speed * sin(aim) , 0.0);
		}
	public void  move(){
		super.move();
		pos += vel;
		if(cnt % 6 == 0)new AttackRing(this ,"shot" ,30);
		if(0 < vel.x){
			if(maxSpeed < vel.x)vel.x = maxSpeed;
			else vel.x += 0.1;
		}else {
			if(vel.x < -maxSpeed)vel.x = -maxSpeed;
			else vel.x -= 0.1;
		}
		poseZ = atan2(vel.y ,vel.x)*180.0/PI;
	
	}
	public void reportRing(Ring ring){
		new AccBullet(pos ,true, -PI / 2.0 ,0.0 ,4.0 ,0.1);
		new AccBullet(pos ,true, PI / 2.0 ,0.0 ,4.0,0.1);
	}
	
}
public class FourwayEnemy:Enemy{
	private:
	static Shape baseShape;
	static float[][] a = [
        [-1.2 ,-0.6 ,0   ,0.6 ,1.2],
        [-0.4 ,-0.4 ,-0.4  ,0.4 ,0.4]
      ];
      static float[][] b =[
        [0    ,0.6  ,1.2 ,0.6 ,0],
        [0.4  ,0.4  ,0.4   ,0.4  ,0.4]
      ];
		double aim;
		double speed;
		double maxSpeed;
		Vector3 vel;
		public this(Vector3 pos,double aim){
			super(4.0);
			if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,8);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  60;
		
			
			collisionRange = 20;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
			vel = new Vector3(2.0 * cos(aim) ,2.0 * sin(aim) , 0.0);
			
			poseY = 90.0;
		}
	public void  move(){
		super.move();
		pos += vel;
		if(/*cnt % 360 < 180 && */cnt % 10 == 0)new AttackRing(this ,"fourway" ,30);
		
		poseZ += 0.6;
	
	}
	public void reportRing(Ring ring){
		double taim = poseZ * PI /180.0;
		new StraightBullet(pos ,true, taim+0.0 ,3.0);
		new StraightBullet(pos ,true, taim+PI ,3.0);
		new StraightBullet(pos ,true, taim-PI / 2.0 ,3.0);
		new StraightBullet(pos ,true, taim+PI / 2.0 ,3.0);
	}
	
}

public class TurretEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[] a = 
			[-1.0 ,-0.6 ,0.0 ,0.6 ,0.6 ,2.0 ,2.1 ,2.0 ,1.0 ,2.0 ,2.1 ,2.0 ,0.6 ,0.6 ,0.0 ,-0.6];
  	static float[] b =
		
			[0.0 ,0.6  ,1.0 ,0.6 ,0.6  ,0.5 ,0.3 ,0.1 ,0.0 ,-0.1,-0.3,-0.5,-0.6,-0.6,-1.0,-0.6];
	static float[] z=
	[-0.6 ,-0.4 ,0.0 ,0.4 ,0.6];
	static float[] scale =
	[0.2 ,0.6 ,1.0 ,0.6 ,0.2];
		double aim;
		public this(Vector3 pos,double aim){
			super(4.0);
			if(baseShape is null){
			baseShape = new SH_Pot(a ,b ,z ,scale);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  30;
//			disableBorder();
		
			collisionRange = 15;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
//			this.speed = speed;
//			this.maxSpeed = maxSpeed;;
//			vel = new Vector3();
		}
	public void  move(){
		super.move();
		if(cnt % 60 < 30){
			if(cnt % 10 == 0){
				new AttackRing(this ,"shot",30);
			}
			double taim = atan2(ship.rpos.y-rpos.y ,ship.rpos.x-rpos.x);
			if(abs(aim -taim) < PI / 90.0){}
			else if(raimmark(aim ,taim) < 0)aim -= PI / 90.0;
			else aim += PI / 90.0;
			
			aim = radlimit(aim);
		}else{
			
		}
		/*
		vel.x += speed * cos(aim);
		vel.y += speed * sin(aim);
		
		if(maxSpeed < vel.x)vel.x = maxSpeed;
		else if(vel.x < -maxSpeed)vel.x = -maxSpeed;
		if(maxSpeed < vel.y)vel.y = maxSpeed;
		else if(vel.y < -maxSpeed)vel.y = -maxSpeed;
		if(maxSpeed < vel.z)vel.z = maxSpeed;
		else if(vel.z < -maxSpeed)vel.z = -maxSpeed;
		*/
		poseZ = aim*180.0/PI;
	
	}
	public void reportRing(Ring ring){
		new Enemy1(rpos , aim ,4.0 ,0.5);
	}
	
}

public class TurretEnemy2:Enemy{
	private:
	static Shape baseShape;
	static  float[] a = 
			[-1.0 ,-0.6 ,0.0 ,0.6 ,0.6 ,2.0 ,2.1 ,2.0 ,1.0 ,2.0 ,2.1 ,2.0 ,0.6 ,0.6 ,0.0 ,-0.6];
  	static float[] b =
		
			[0.0 ,0.6  ,1.0 ,0.6 ,0.6  ,0.5 ,0.3 ,0.1 ,0.0 ,-0.1,-0.3,-0.5,-0.6,-0.6,-1.0,-0.6];
	static float[] z=
	[-0.6 ,-0.4 ,0.0 ,0.4 ,0.6];
	static float[] scale =
	[0.2 ,0.6 ,1.0 ,0.6 ,0.2];
		double aim;
		public this(Vector3 pos,double aim){
			super(4.0);
			if(baseShape is null){
			baseShape = new SH_Pot(a ,b ,z ,scale);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  30;
//			disableBorder();
		
			collisionRange = 15;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim;
//			this.speed = speed;
//			this.maxSpeed = maxSpeed;;
//			vel = new Vector3();
		}
	public void  move(){
		super.move();
		if(cnt % 60 < 30){
			if(cnt % 60 == 0){
				new AttackRing(this ,"shot",30);
			}
			double taim = atan2(ship.rpos.y-rpos.y ,ship.rpos.x-rpos.x);
			if(abs(aim -taim) < PI / 90.0){}
			else if(raimmark(aim ,taim) < 0)aim -= PI / 90.0;
			else aim += PI / 90.0;
			
			aim = radlimit(aim);
		}else{
			
		}
		/*
		vel.x += speed * cos(aim);
		vel.y += speed * sin(aim);
		
		if(maxSpeed < vel.x)vel.x = maxSpeed;
		else if(vel.x < -maxSpeed)vel.x = -maxSpeed;
		if(maxSpeed < vel.y)vel.y = maxSpeed;
		else if(vel.y < -maxSpeed)vel.y = -maxSpeed;
		if(maxSpeed < vel.z)vel.z = maxSpeed;
		else if(vel.z < -maxSpeed)vel.z = -maxSpeed;
		*/
		poseZ = aim*180.0/PI;
	
	}
	public void reportRing(Ring ring){
		new HomingBullet(rpos , true ,aim ,PI/90.0 ,4.0 ,3);
	}
	
}

public class Enemy3D:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
		Vector3 aim;
//		double speed;
		public this(Vector3 pos,Object o){
			super(1.5);
			if(baseShape is null){
				baseShape = new SH_Pole(a ,b ,5);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  25;
		
			collisionRange = 12;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = cast(Vector3)o;
//			this.speed = speed;
		}
	public void  move(){
		super.move();
/*		if(cnt % 30 == 0){
			new AttackRing(this ,"shot",30);
			
		}
		*/	
		/*
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		*/
		pos.x += aim.x;
		pos.y += aim.y;
		if(abs(rpos.z + 800) > collisionRange){
			pos.z += aim.z;
		}
		poseY += 5;
		poseZ += 4;
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class Enemy3D2:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
		Vector3 aim;
//		double speed;
		public this(Vector3 pos,Object o){
			super(1.5);
			if(baseShape is null){
				baseShape = new SH_Pole(a ,b ,5);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  25;
		
			collisionRange = 12;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = cast(Vector3)o;
//			this.speed = speed;
		}
	public void  move(){
		super.move();
/*		if(cnt % 30 == 0){
			new AttackRing(this ,"shot",30);
			
		}
		*/	
		/*
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		*/
		pos += aim;
		poseY += 5;
		poseZ += 4;
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class Blaster:Enemy{
	private:
	static Shape baseShape;
	/*
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
	*/
		Vector3 aim;
//		double speed;
		public this(Vector3 pos,Vector3 aim ,double speed){
			super(5.0);
			if(baseShape is null){
				baseShape = new SH_Sphere(1.0 ,12);
			}
    		shape = cast(Shape)baseShape.clone();
			size =  100;
		
			collisionRange = 80;
			this.pos = cast(Vector3)pos.clone;
			this.rpos = cast(Vector3)this.pos.clone();
			this.aim = aim * speed;
//			this.speed = speed;
		}
	public void  move(){
		super.move();
/*		if(cnt % 30 == 0){
			new AttackRing(this ,"shot",30);
			
		}
		*/	
		/*
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		*/
		pos += aim;
		poseY += 3;
		poseZ += 7;
	
	}
	public void reportRing(Ring ring){
//		new EBullet2(pos ,true, atan2(ship.pos.y - pos.y ,ship.pos.x - pos.x));
	}
	
}
public class WideSlowEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,-0.2 ,0.3 ,1.5]
			
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.7 ,0.0]
			
  	];
		double aim;
		
	public this(float x,float y ,float z ,float aim){
		super(2);
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
		}
   	shape = cast(Shape)baseShape.clone();
		size =  30;
	
		collisionRange = 15;
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		this.aim = aim;
		
		
	}
	public void  move(){
		super.move();
		if(cnt == 0){
			new AttackRing(this ,"wideshot",30);
		}
		if(120 < cnt){
			pos.x += 2 * cos(aim);
			pos.y += 2 * sin(aim);
		}
		poseZ = aim / PI * 180;
		poseX += 5;
	}
	public void reportRing(Ring ring){
		for(double rad=-PI/2.0;rad<=PI/2.0;rad+=PI/36){
			new SlowStraightBullet(pos ,true, rad + aim);
		}
	}
}
public class ThrustEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-0.8 ,-1.0 ,-0.3 ,1.0],
			[-0.8 ,-0.5 ,-0.3 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.7 ,0.0],
			[0.0 ,0.6 ,0.7 ,0.0]
  	];
		double aim;
		double speed;
		double maxSpeed;
		double acc;
//		double brad;
//		double bSpeed;
	public this(float x,float y ,float z ,float aim ,float speed = 8.0){
		super(1.0);
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,8);
		}
   	shape = cast(Shape)baseShape.clone();
		size =  30;
	
		collisionRange = 10;
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		this.aim = aim;
		this.speed = 0.0;
		this.maxSpeed = speed;
		this.acc = maxSpeed / 30.0;
		
//		brad = 
	}
	public void  move(){
		super.move();
		if(cnt == 0){
			new AttackRing(this ,"shot",30);
		}
		if(speed < maxSpeed){
			speed += acc;
		}else speed = maxSpeed;
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		poseZ = aim / PI * 180;
		poseX += 5;
	}
	public void reportRing(Ring ring){
		double a = atan2(ship.rpos.y - rpos.y, ship.rpos.x - rpos.x);
		for(double rad=-PI/12.0;rad<=PI/12.0;rad+=PI/36){
			new StraightBullet(pos ,true, rad + a ,5.0 + rad * 8.0);
		}
	}
}
public class UpLaserEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[0 ,-0.5 ,0 ,1.0 ,0],
       		[0]
			
  	   ];
  	static float[][] b =
		[
			[0  ,0.5 ,1.0 ,0.5 ,0.0],
      		[0.5]
			
  	];
		double aim;
		
	public this(float x,float y ,float z ,float aim){
		super(-1);
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,8);
		}
   		shape = cast(Shape)baseShape.clone();
		size =  40;
	
		collisionRange = 20;
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		this.aim = aim;
		
//		poseZ = 90;
	}
	public void  move(){
		super.move();
		if(rpos.z < -800 - 2)pos.z +=2;
		else if(-800 + 2 < rpos.z)pos.z -= 2;
		else{
			
			
			pos.x += 2 * cos(aim);
			pos.y += 2 * sin(aim);
			
			
		}
		if(cnt % 5 == 0){
			new AttackRing(this ,"laser",10);
		}
		poseZ = -90 + aim / PI * 180;
		poseX += 5;
	}
	public void reportRing(Ring ring){
		
		new StraightBullet(pos ,true, aim - PI / 2.0 ,5.0);
		
	}
}
public class DownLaserEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[0 ,-0.5 ,0 ,1.0 ,0],
       		[0]
			
  	   ];
  	static float[][] b =
		[
			[0  ,0.5 ,1.0 ,0.5 ,0.0],
      		[0.5]
			
  	];
		double aim;
		
	public this(float x,float y ,float z ,float aim){
		super(-1);
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,8);
		}
   		shape = cast(Shape)baseShape.clone();
		size =  40;
	
		collisionRange = 20;
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		this.aim = aim;
		
//		poseZ = 90;
	}
	public void  move(){
		super.move();
		if(rpos.z < -800 - 2)pos.z +=2;
		else if(-800 + 2 < rpos.z)pos.z -= 2;
		else {
			
			
			pos.x += 2 * cos(aim);
			pos.y += 2 * sin(aim);
			
		}
		if(cnt % 5 == 0){
			new AttackRing(this ,"laser",10);
		}
		poseZ = 90 + aim / PI * 180;
		poseX += 5;
	}
	public void reportRing(Ring ring){
		
		new StraightBullet(pos ,true, aim + PI / 2.0 ,5.0);
		
	}
}

public class StillEnemy:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
		double aim;
	public this(float x,float y ,float z){
		super(0.5);
		if(baseShape is null){
		baseShape = new SH_Pole(a ,b ,4);
		}
   	shape = cast(Shape)baseShape.clone();
		size =  20;
	
		collisionRange = 10;
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		this.aim = aim;
	}
	public void move(){
		super.move();
		poseZ += 5;
	}
}

public class MiddleEnemy1:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-0.6 ,-1 ,-0.6  ,1.0 ,0.4],
        	[-0.6 ,0  ,0     ,0  ,0.4]
  	   ];
  	static float[][] b =
		[
			[0 ,0.5  ,1.0 ,0.4 ,0],
			[0 ,0.6  ,0.6  ,0.6,0]
  	];
		double aim;
	public this(float x,float y ,float z ,float aim){
		super(6);
		if(baseShape is null){
		baseShape = new SH_Pole(a ,b ,6);
		}
   		shape = cast(Shape)baseShape.clone();
		shape.multi(1.5);
		size =  50;
	
		collisionRange = 25;
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		this.aim = aim;
		poseZ = aim * 180.0 / PI;
	}
	public void move(){
		super.move();
		float speed = 0.0;
		if(cnt < 60)speed = cast(float)(60 - (cnt % 60)) / 30.0;
		else{
			
			if(((cnt - 60) % 180) == 0)new AttackRing(this ,"en1" ,30);
			else if(((cnt - 60) % 180) == 10)new AttackRing(this ,"en2" ,30);
			else if(((cnt - 60) % 180) == 20)new AttackRing(this ,"en3" ,30);
			
		
		}
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		poseX += 1;
	}
	public void reportRing(Ring ring){
		
		switch(ring.name){
			case "en1":
			new Enemy1(rpos, aim ,1.3);
			break;
			case "en2":
			new Enemy1(rpos, aim + PI / 6.0 ,1.3);
			new Enemy1(rpos, aim - PI / 6.0 ,1.3);
			break;
			case "en3":
			new Enemy1(rpos, aim + PI * 2.0 / 6.0 ,1.3);
			new Enemy1(rpos, aim - PI * 2.0 / 6.0 ,1.3);
			break;
			default:break;
		}
		
	}
}
public class Zab:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[0.0 ,-1.0 ,0.0 ,1.0 ,0.0]
			
  	   ];
  	static float[][] b =
		[
			[0.0  ,0.5 ,1.0 ,0.5 ,0.0]
  	];
	double aim;
	double speed;
	public this(float x,float y ,float z){
		super(0.5);
		if(baseShape is null){
		baseShape = new SH_Pole(a ,b ,4);
		}
   		shape = cast(Shape)baseShape.clone();
		size =  20;
		
		collisionRange = 10;
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		this.aim = atan2(ship.pos.y-pos.y ,ship.pos.x-pos.x);
		speed = 0.0;
		poseY = 90;
	}
	public void  move(){
		super.move();
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
		if(speed < 5.0)speed += 0.2;
		poseZ += 3;
	}
}
public class BackBone:Enemy{
	private:
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.3 ,-0.8 ,0.0 ,0.8 ,1.3]
  	   ];
  	static float[][] b =
		[
			[0.3  ,0.8 ,1.0 ,0.8 ,0.3]
  	];
	double aim;
	public this(float x,float y ,float z){
		super(3);
		if(baseShape is null){
		baseShape = new SH_Pole(a ,b ,4);
		}
   		shape = cast(Shape)baseShape.clone();
		size =  30;
		
		collisionRange = 15;
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		this.aim = 0.0;
	}
	public void move(){
		super.move();
		
		if(parent is null || !parent.exists){
			if(rpos.z < -800 - 2)pos.z +=2.0;
			else if(-800 + 2 < rpos.z)pos.z -= 2.0;
			double saim = atan2(ship.pos.y-pos.y,ship.pos.x-pos.x);
			
			if(raimmark(aim , saim) > 0.0)aim += 0.6 * PI / 180.0;
			else aim -= 0.6 * PI / 180.0;
			
			poseZ = aim * 180.0 / PI;
				
			pos.x += 2 * cos(aim);
			pos.y += 2 * sin(aim);
		}else{
			if(rpos.z < -800 - 1)pos.z +=0.5;
			else if(-800 + 1 < rpos.z)pos.z -= 0.5;
			
			aim = rposeZ*PI/180.0;
		}
		poseX += 3;
	}
}

public class Boss1:Boss{
	
	//import br.mainloop;
	private{
		double aim;
		static Shape baseShape;
		static  float[][] a = 
		[
			[-1.0 ,0.0 ,2.0],
			[-1.0 ,0.0 ,2.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0],
 			[0.0 ,0.5 ,0.0]
  	];
	}

	public this(double x,double y,double z,double aim){
		super(10);
		Matrix po =  new Matrix();
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;

		size =  40;
		collisionRange = 20;
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,8);
		}
    shape = cast(Shape)baseShape.clone();

		
		
		
		addAnimation(new Rotate(0 ,POSEX ,3 ,0.0 ,true),"rotate");
		Parts p;
		p = new EnemyAppend(Octahedron.getShape() ,20 ,-1);
		(cast(Enemy)p).disableBorder();
		

		addChild(p ,"jointl1", 70 ,ENGAGED ,matRotateZ(90) * matRotateZ(-30) ,matRotateZ(-30));
		p = new Turret();//(Turret1.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();
		

		childHash["jointl1"].addChild(p ,"turretl1", 70 ,ENGAGED ,matRotateZ(90) * matRotateZ(-60) ,matRotateZ(-60));
		p = new EnemyAppend(Octahedron.getShape() ,20 ,-1);
		(cast(Enemy)p).disableBorder();
		

		childHash["turretl1"].addChild(p ,"jointl2", 70 ,ENGAGED ,matRotateZ(90) * matRotateZ(-90) ,matRotateZ(-90));
		p = new Turret();//(Turret1.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();
		

		childHash["jointl2"].addChild(p ,"turretl2", 70 ,ENGAGED ,matRotateZ(90) * matRotateZ(-120) ,matRotateZ(-120));
		p = new EnemyAppend(Octahedron.getShape() ,20 ,-1);
		(cast(Enemy)p).disableBorder();
		

		addChild(p ,"jointr1", 70 ,ENGAGED ,matRotateZ(-90) * matRotateZ(30) ,matRotateZ(30));
		p = new Turret();//Turret1.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();
		

		childHash["jointr1"].addChild(p ,"turretr1", 70 ,ENGAGED ,matRotateZ(-90) * matRotateZ(60) ,matRotateZ(60));
		p = new EnemyAppend(Octahedron.getShape() ,20 ,-1);
		(cast(Enemy)p).disableBorder();
	

		childHash["turretr1"].addChild(p ,"jointr2", 70 ,ENGAGED ,matRotateZ(-90) * matRotateZ(90) ,matRotateZ(90));
		p =  new Turret();//(Turret1.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();
		

		childHash["jointr2"].addChild(p ,"turretr2", 70 ,ENGAGED ,matRotateZ(-90) * matRotateZ(120) ,matRotateZ(120));
		rotateAll(matRotateZ(180 ) * matRotateX(90));// * matRotateX(90 ) );
		
		addAnimation(new RotateAll(100 ,matRotateX(-0.9),false), "rotate" );
		
//		addAnimation(new RotateAll(0 ,matRotateX(2),true), "rotate" );
//		childHash["joint1"].addAnimation(new Swing(200 ,POSEZ ,-0.4 ,0.8 ,20 ,true) ,"swing2");
		
	}
	public void move(){
		super.move();
	
		switch(state){
			case "start":
			
			if(rpos.z < -800 - 2)pos.z +=2;
			else if(-800 + 2 < rpos.z)pos.z -= 2;
			else {
				pos.z = -800;
				
				childHash["jointl1"].addAnimation(new RotateTo(60 ,BOTHZ ,30 ,1.0 ,false) ,"rotate1");
				childHash["jointr1"].addAnimation(new RotateTo(60 ,BOTHZ ,-30 ,1.0 ,false) ,"rotate2");
				changeState("standby");
			}
			break;
			case "standby":
			if(nowStateCnt >= 60){
				childHash["jointl1"].addAnimation(new Swing(200 ,BOTHZ ,-0.3 ,0.8 ,-10 ,true) ,"swing1");
				childHash["jointr1"].addAnimation(new Swing(200 ,BOTHZ ,0.3 ,0.8 ,-10 ,true) ,"swing2");
				changeState("attack");
			}
			
			break;
			case "attack":
			if(nowStateCnt % 300 < 90 && nowStateCnt % 30 == 0){
//				new AttackRing(this ,"shot",30);
				new AttackRing(cast(Enemy)childHash["turretr1"] ,"shot",30);
				new AttackRing(cast(Enemy)childHash["turretr2"] ,"shot",30);
				new AttackRing(cast(Enemy)childHash["turretl1"] ,"shot",30);
				new AttackRing(cast(Enemy)childHash["turretl2"] ,"shot",30);
				
			}
			break;
			default:break;
		}
		
	}
	public void reportRing(Ring ring){
		for(double rad=PI/2.0;rad<=PI*3.0/2.0;rad+=PI/36){
			new SlowStraightBullet(pos ,true, rad);
		}
	}
}

public class Boss2:Boss{
	private:
		double aim;
		static Shape baseShape;
		static  float[] a = 
		
			[-1.2 	,-0.8 	,0.7 	,1.5 	,0.7 	,-0.8 	,-1.2];
  	static float[] b =
			[0.0  	,0.7 	,0.4 	,0.0 	,-0.4	,-0.7	,0.0];
	
	static float[] z=
			[-0.7 ,-0.5 ,0.0 ,0.5 ,0.7];
	static float[] scale = 
			[0.0 ,0.8 ,1.0 ,0.8 ,0.0];
	bool att;
	public this(double x0,double y0,double z0,double aim){
		super(10);
		Matrix po =  new Matrix();
		pos = new Vector3(x0 ,y0 ,z0);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;

		size =  40;
		collisionRange = 20;
		if(baseShape is null){
			baseShape = new SH_Pot(a ,b ,z ,scale);
		}
    	shape = cast(Shape)baseShape.clone();
		
		Parts p;
		p = new BackBone(x0 ,y0 ,z0);
		addChild(p ,"bone1", 70 ,FOLLOW);
		(cast(Enemy)p).disableBorder();
		p = new BackBone(x0 ,y0 ,z0);
		childHash["bone1"].addChild(p ,"bone2", 90 ,FOLLOW);
		(cast(Enemy)p).disableBorder();
		p = new BackBone(x0 ,y0 ,z0);
		childHash["bone2"].addChild(p ,"bone3", 80 ,FOLLOW);
		(cast(Enemy)p).disableBorder();
		p = new BackBone(x0 ,y0 ,z0);
		childHash["bone3"].addChild(p ,"bone4", 80 ,FOLLOW);
		(cast(Enemy)p).disableBorder();
		p = new BackBone(x0 ,y0 ,z0);
		childHash["bone4"].addChild(p ,"bone5", 80 ,FOLLOW);
		(cast(Enemy)p).disableBorder();
		p = new BackBone(x0 ,y0 ,z0);
		childHash["bone5"].addChild(p ,"bone6", 80 ,FOLLOW);
		(cast(Enemy)p).disableBorder();
		/*
		p = new BackBone(x0 ,y0 ,z0);
		childHash["bone6"].addChild(p ,"bone7", 80 ,FOLLOW);
		(cast(Enemy)p).disableBorder();

		p = new BackBone(x0 ,y0 ,z0);
		childHash["bone7"].addChild(p ,"bone8", 80 ,FOLLOW);
		(cast(Enemy)p).disableBorder();
		*/
		att = true;
	}
	
	public void move(){
		super.move();
		float speed = 1.5;
		switch(state){
			case "start":
			if(rpos.z < -800 - 20)pos.z +=2.0;
			else if(-800 + 20 < rpos.z)pos.z -= 2.0;
			else {
//				pos.z = -800;
				changeState("standby");
			}
			
			aim += 0.8 * PI / 180.0;
			break;
			case "standby":
			if(rpos.z < -800 - 2)pos.z +=2.0;
			else if(-800 + 2 < rpos.z)pos.z -= 2.0;
			else {
				pos.z = -800;
				changeState("straight");
			}
			break;
			case "homing":
				double saim = atan2(ship.pos.y-pos.y,ship.pos.x-pos.x);	
				if(raimmark(aim , saim) > 0.0)aim += 1.2 * PI / 180.0;
				else aim -= 1.2 * PI / 180.0;
				if(nowStateCnt > 90){
					
					changeState("straight");
				}
				
				break;
			case "straight":
				if(nowStateCnt > 100){
//					att ^=true;
					changeState("homing");
				}
				if(/*att && */(nowStateCnt == 10)){
					new AttackRing(this ,"angle1",45);
				}
				speed = 2.5;
				break;
			default:break;
		}
		
		poseZ = aim * 180.0 / PI;
		poseX += 3;
		pos.x += speed * cos(aim);
		pos.y += speed * sin(aim);
	}
	public void reportRing(Ring ring){
		for(double rad=-PI;rad<=PI;rad+=PI/36){
			new StraightBullet(pos ,true, rad + aim ,1.5);
		}
		/*
		double s1,s2;
		s1 = 1.9;
		s2 = 2.0;
		
		switch(ring.name){
			case "angle1":
			for(double rad=-PI;rad<PI;rad+=PI/2){
				new StraightBullet(pos ,true, aim + rad ,s1);
				new StraightBullet(pos ,true, aim + rad ,s2);
			}
			break;
			case "angle2":
			for(double rad=-PI;rad<PI;rad+=PI/2){
				new StraightBullet(pos ,true, aim + rad + PI /40.0 ,s1);
				new StraightBullet(pos ,true, aim + rad + PI /40.0 ,s2);
			}
			break;
			case "angle3":
			for(double rad=-PI;rad<PI;rad+=PI/2){
				new StraightBullet(pos ,true, aim + rad + 2.0 * PI /40.0 ,s1);
				new StraightBullet(pos ,true, aim + rad + 2.0 * PI /40.0 ,s2);
			}
			break;
			case "angle4":
			for(double rad=-PI;rad<PI;rad+=PI/2){
				new StraightBullet(pos ,true, aim + rad + 3.0 * PI /40.0 ,s1);
				new StraightBullet(pos ,true, aim + rad + 3.0 * PI /40.0 ,s2);
			}
			break;
			case "angle5":
			for(double rad=-PI;rad<PI;rad+=PI/2){
				new StraightBullet(pos ,true, aim + rad + 4.0 * PI /40.0 ,s1);
				new StraightBullet(pos ,true, aim + rad + 4.0 * PI /40.0 ,s2);
			}
			break;
			default:break;
		}
		*/
	}
}

public class Boss3:Boss{
	private:
		double aim;
		static Shape baseShape;
		static  float[] a = 
		
			[-1.2 	,-0.8 	,0.7 	,1.5 	,0.7 	,-0.8 	,-1.2];
  	static float[] b =
			[0.0  	,0.7 	,0.4 	,0.0 	,-0.4	,-0.7	,0.0];
	
	static float[] z=
			[-0.7 ,-0.5 ,0.0 ,0.5 ,0.7];
	static float[] scale = 
			[0.0 ,0.8 ,1.0 ,0.8 ,0.0];
	
	public this(double x0,double y0,double z0,double aim){
		super(10);
		Matrix po =  new Matrix();
		pos = new Vector3(x0 ,y0 ,z0);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;

		size =  40;
		collisionRange = 20;
		if(baseShape is null){
			baseShape = new SH_Sphere(1.0 ,6);
		}
    	shape = cast(Shape)baseShape.clone();
		
		Parts p;
		p = new Joint1();
		addChild(p ,"bone11", 70 ,ENGAGED ,matRotateZ(0));
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone11"].addChild(p ,"bone12", 90 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone12"].addChild(p ,"bone13", 80 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone13"].addChild(p ,"bone14", 80 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Joint1();
		addChild(p ,"bone21", 70 ,ENGAGED ,matRotateZ(90));
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone21"].addChild(p ,"bone22", 90 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone22"].addChild(p ,"bone23", 80 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone23"].addChild(p ,"bone24", 80 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Joint1();
		addChild(p ,"bone31", 70 ,ENGAGED ,matRotateZ(180));
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone31"].addChild(p ,"bone32", 90 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone32"].addChild(p ,"bone33", 80 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone33"].addChild(p ,"bone34", 80 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Joint1();
		addChild(p ,"bone41", 70 ,ENGAGED ,matRotateZ(-90));
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone41"].addChild(p ,"bone42", 90 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone42"].addChild(p ,"bone43", 80 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		p = new Turret();
		childHash["bone43"].addChild(p ,"bone44", 80 ,ENGAGED);
		(cast(Enemy)p).disableBorder();
		
		childHash["bone11"].addAnimation(new RotateTo(120 ,BOTHZ ,360 ,0.8) ,"guruguru");
		childHash["bone21"].addAnimation(new RotateTo(120 ,BOTHZ ,360 ,0.8) ,"guruguru");
		childHash["bone31"].addAnimation(new RotateTo(120 ,BOTHZ ,360 ,0.8) ,"guruguru");
		childHash["bone41"].addAnimation(new RotateTo(120 ,BOTHZ ,360 ,0.8) ,"guruguru");
	}
	public void move(){
		super.move();
		switch(state){
			case "start":
			if(rpos.z < -800 - 2)pos.z +=2.0;
			else if(-800 + 2 < rpos.z)pos.z -= 2.0;
			else if(120 < nowStateCnt){
				if("bone11" in childHash)childHash["bone11"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone21" in childHash)childHash["bone21"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone31" in childHash)childHash["bone31"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone41" in childHash)childHash["bone41"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone12" in childHash)childHash["bone12"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone22" in childHash)childHash["bone22"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone32" in childHash)childHash["bone32"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone42" in childHash)childHash["bone42"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone13" in childHash)childHash["bone13"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone23" in childHash)childHash["bone23"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone33" in childHash)childHash["bone33"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone43" in childHash)childHash["bone43"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone14" in childHash)childHash["bone14"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone24" in childHash)childHash["bone24"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone34" in childHash)childHash["bone34"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone44" in childHash)childHash["bone44"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				changeState("standby");
			}
			break;
			case "standby":
			if(60 < nowStateCnt)changeState("attack1");
			break;
			case "attack1":
			if(-200 < pos.x)pos.x -= 0.7;
			else {
				changeState("attack2");
				if("bone12" in childHash)childHash["bone12"].addAnimation(new RotateTo(120 ,BOTHZ ,430 ,0.8) ,"bend");
				if("bone22" in childHash)childHash["bone22"].addAnimation(new RotateTo(120 ,BOTHZ ,430 ,0.8) ,"bend");
				if("bone32" in childHash)childHash["bone32"].addAnimation(new RotateTo(120 ,BOTHZ ,430 ,0.8) ,"bend");
				if("bone42" in childHash)childHash["bone42"].addAnimation(new RotateTo(120 ,BOTHZ ,430 ,0.8) ,"bend");
			}
			if(nowStateCnt % 240 == 40)new AttackRing(this, "all",45);
			break;
			case "attack2":
			if(420 < nowStateCnt){
				if("bone11" in childHash)childHash["bone11"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone21" in childHash)childHash["bone21"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone31" in childHash)childHash["bone31"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone41" in childHash)childHash["bone41"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone12" in childHash)childHash["bone12"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone22" in childHash)childHash["bone22"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone32" in childHash)childHash["bone32"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone42" in childHash)childHash["bone42"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone13" in childHash)childHash["bone13"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone23" in childHash)childHash["bone23"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone33" in childHash)childHash["bone33"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone43" in childHash)childHash["bone43"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone14" in childHash)childHash["bone14"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone24" in childHash)childHash["bone24"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone34" in childHash)childHash["bone34"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone44" in childHash)childHash["bone44"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				changeState("attack3");
			}
			if(nowStateCnt > 120 && nowStateCnt % 10 == 0){
				if("bone14" in childHash)new AttackRing(cast(Enemy)childHash["bone14"], "shot",30);
				if("bone24" in childHash)new AttackRing(cast(Enemy)childHash["bone24"], "shot",30);
				if("bone34" in childHash)new AttackRing(cast(Enemy)childHash["bone34"], "shot",30);
				if("bone44" in childHash)new AttackRing(cast(Enemy)childHash["bone44"], "shot",30);
			}
			break;
			case "attack3":
			if(pos.x < 200)pos.x += 0.7;
			else {
				changeState("attack4");
				if("bone12" in childHash)childHash["bone12"].addAnimation(new RotateTo(120 ,BOTHZ ,430 ,0.8) ,"bend");
				if("bone22" in childHash)childHash["bone22"].addAnimation(new RotateTo(120 ,BOTHZ ,430 ,0.8) ,"bend");
				if("bone32" in childHash)childHash["bone32"].addAnimation(new RotateTo(120 ,BOTHZ ,430 ,0.8) ,"bend");
				if("bone42" in childHash)childHash["bone42"].addAnimation(new RotateTo(120 ,BOTHZ ,430 ,0.8) ,"bend");
			}
			if(nowStateCnt % 240 == 40)new AttackRing(this, "all",45);
			break;
			case "attack4":
			if(420 < nowStateCnt){
				if("bone11" in childHash)childHash["bone11"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone21" in childHash)childHash["bone21"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone31" in childHash)childHash["bone31"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone41" in childHash)childHash["bone41"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone12" in childHash)childHash["bone12"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone22" in childHash)childHash["bone22"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone32" in childHash)childHash["bone32"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone42" in childHash)childHash["bone42"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone13" in childHash)childHash["bone13"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone23" in childHash)childHash["bone23"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone33" in childHash)childHash["bone33"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone43" in childHash)childHash["bone43"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone14" in childHash)childHash["bone14"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone24" in childHash)childHash["bone24"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone34" in childHash)childHash["bone34"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				if("bone44" in childHash)childHash["bone44"].addAnimation(new RotateTo(60 ,BOTHZ ,360) ,"fix");
				changeState("attack1");
			}
			if(nowStateCnt > 120 && nowStateCnt % 10 == 0){
				if("bone14" in childHash)new AttackRing(cast(Enemy)childHash["bone14"], "shot",30);
				if("bone24" in childHash)new AttackRing(cast(Enemy)childHash["bone24"], "shot",30);
				if("bone34" in childHash)new AttackRing(cast(Enemy)childHash["bone34"], "shot",30);
				if("bone44" in childHash)new AttackRing(cast(Enemy)childHash["bone44"], "shot",30);
			}
			break;
			default:break;
		}
		rotateAll(matRotateZ(0.7));
	}
	public void reportRing(Ring ring){
		for(double rad=-PI;rad<=PI;rad+=PI/36){
			new StraightBullet(pos ,true, rad + aim ,1.8);
		}
	}
}
/*
public class Boss4:Boss{
	private:
		double aim;
		static Shape baseShape;
		static  float[][] a = 
		[
			[-0.6 ,-1.2 ,-0.2 ,1.0],
			[-0.6 ,-0.2 ,0.2  ,1.0]
			
			
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.6 ,1.3 ,0.0],
			[0.0 ,0.8 ,0.8 ,0.0]
  	];
	public this(double x0,double y0,double z0,double aim){
		super(10);
		Matrix po =  matRotateX(90);
		pos = new Vector3(x0 ,y0 ,z0);
		setPoseBase(po);
		this.aim = aim;

		size =  40;
		collisionRange = 20;
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
		}
    	shape = cast(Shape)baseShape.clone();
		
		Parts p;
		
		
		p = new Arm();
		addChild(p ,"armr", 100 ,NORMAL ,new Matrix());
		(cast(Enemy)p).disableBorder();p.linkY =110;
		p = new EnemyAppend(BulletShape.getShape() ,20 ,-1);
		childHash["armr"].addChild(p ,"finr1", 20 ,ENGAGED ,new Matrix());// ,matRotateY(50) * matRotateZ(180));
		(cast(Enemy)p).disableBorder();p.linkY =p.poseY =-130;p.linkY -= 110;
		p = new EnemyAppend(BulletShape.getShape() ,20 ,-1);
		childHash["armr"].addChild(p ,"finr2", 20 ,ENGAGED ,new Matrix());// ,matRotateY(-30)*matRotateX(60) * matRotateZ(180));
		(cast(Enemy)p).disableBorder();p.linkY =p.poseY =30;p.linkZ =p.poseZ = 120;;p.linkY -= 110;
		p = new EnemyAppend(BulletShape.getShape() ,20 ,-1);
		childHash["armr"].addChild(p ,"finr3", 20 ,ENGAGED ,new Matrix());// ,matRotateY(-30)*matRotateX(-60) * matRotateZ(180));
		(cast(Enemy)p).disableBorder();p.linkY =p.poseY =30;p.linkZ =p.poseZ = -120;;p.linkY -= 110;
		
		p = new Arm();
		addChild(p ,"arml", 100 ,NORMAL  ,new Matrix());
		(cast(Enemy)p).disableBorder();p.linkY = -110;
		p = new EnemyAppend(BulletShape.getShape() ,20 ,-1);
		childHash["arml"].addChild(p ,"finl1", 20 ,ENGAGED ,new Matrix());// ,matRotateY(-50) * matRotateZ(180));
		(cast(Enemy)p).disableBorder();p.linkY =p.poseY =130;p.linkY += 110;
		
		p = new EnemyAppend(BulletShape.getShape() ,20 ,-1);
		childHash["arml"].addChild(p ,"finl2", 20 ,ENGAGED ,new Matrix());// ,matRotateY(30)*matRotateX(60) * matRotateZ(180));
		(cast(Enemy)p).disableBorder();p.linkY =p.poseY =-30;p.linkZ =p.poseZ = 120;p.linkY += 110;
		p = new EnemyAppend(BulletShape.getShape() ,20 ,-1);
		childHash["arml"].addChild(p ,"finl3", 20 ,ENGAGED ,new Matrix());// ,matRotateY(30)*matRotateX(-60) * matRotateZ(180));
		(cast(Enemy)p).disableBorder();p.linkY =p.poseY =-30;p.linkZ =p.poseZ = -120;p.linkY += 110;
		
//		rotateAll(matRotateX(90));
//		addAnimation(new RotateAll(90 ,matRotateX(1)) ,"turn");
		addAnimation(new Rotate(90 , POSEX ,1) ,"roll1");
//		childHash["arml"].addAnimation(new Rotate(90 , LINKX ,1) ,"roll1");
//		childHash["armr"].addAnimation(new Rotate(90 , LINKX ,1) ,"roll1");
	}
	public void move(){
		super.move();
		switch(state){
			case "start":
			if(nowStateCnt == 90){
				addAnimation(new Rotate(60 , POSEY ,3) ,"turn");
				changeState("standby");
				
			}
			pos.x += 7.0;
			break;
			case "standby":
			if(nowStateCnt == 90){
				changeState("attack");
				addAnimation(new RotateAll(90 ,matRotateX(2) ,true) ,"roll1" );
			}
			if(rpos.z < -800 - 2)pos.z +=4.0;
			else if(-800 + 2 < rpos.z)pos.z -= 4.0;
			if(nowStateCnt < 30)pos.x += 5.0;
			else pos.x -= 1.0;
			
			break;
			case "attack":
			
			break;
			default:break;
		}
		
//		Log_write(cast(int)rlinkX);
		
//		rotateAll(matRotateX(1));
	}
}
*/
public class Boss4:Boss{
	
	//import br.mainloop;
	private{
		double aim;
		static Shape baseShape;
		static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
 
  	];
	bool headright;
	}
	
	public this(double x,double y,double z,double aim){
		super(13);
		Matrix po =  matRotate(-90 ,0 ,0 ,1) * matRotate(45 ,1 ,0 ,0);
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;
		//super(pos ,po);
		//set(pos ,p);
		//setPoseBase(p);
		size =  30;
		collisionRange = 10;
		headright = true;
		
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
		}
    shape = cast(Shape)baseShape.clone();
		Parts p;//Parts p;
		
		//wing
		p = new EnemyAppend(BaseOfWing.getShape() ,45 ,-1);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();
		//partsManager.add(wing1);
		addChild(p, "rWingBase", 60 ,NORMAL ,matRotateX(90) * matRotateX(-20));
		
		p = new EnemyAppend(BaseOfWing.getShape() ,30 ,-1);//p = new BaseOfWing();
		(cast(Enemy)p).disableBorder();
		//partsManager.add(wing2);
		addChild(p, "lWingBase",60 ,NORMAL ,matRotateX(90) * matRotateZ(180)* matRotateX(- 20) );
		
		p = new EnemyAppend(Tail.getShape() ,30 ,-1);//p = new Tail();
		(cast(Enemy)p).disableBorder();
		addChild(p, "tail_0", 60 ,ENGAGED ,matRotateX(90) * matRotateY(0) * matRotateZ(-90));
		p = new HeadTurret(40);//p = new Head();
		(cast(Enemy)p).disableBorder();
		addChild(p, "head" ,60 ,NORMAL ,matRotateX(90) * matRotateZ(90) ,matRotateZ(-30) * matRotateY(90));
		
		
		for(int i = 0;i < 5;i ++){
			char[] rw0 = "rWing_"~str.toString(i)~"_"~str.toString(0);
			char[] rw1 = "rWing_"~str.toString(i)~"_"~str.toString(1);
			char[] rw2 = "rWing_"~str.toString(i)~"_"~str.toString(2);
			char[] rw3 = "rWing_"~str.toString(i)~"_"~str.toString(3);
			char[] lw0 = "lWing_"~str.toString(i)~"_"~str.toString(0);
			char[] lw1 = "lWing_"~str.toString(i)~"_"~str.toString(1);
			char[] lw2 = "lWing_"~str.toString(i)~"_"~str.toString(2);
			char[] lw3 = "lWing_"~str.toString(i)~"_"~str.toString(3);
			p = new EnemyAppend(Wing.getShape() ,30 ,-1);//p = new Wing();
			(cast(Enemy)p).disableBorder();
			//partsManager.add(append);
			childHash["rWingBase"].addChild(p ,rw0 ,60 ,ENGAGED ,matRotateX(90) * matRotateZ(30 * (i - 2)) * matRotateX(-20) );
			p = new EnemyAppend(Wing.getShape() ,30 ,-1);//p = new Wing();
			(cast(Enemy)p).disableBorder();
			childHash[rw0].addChild(p ,rw1 ,60 , ENGAGED);//matRotateX(PI / 2.0) * matRotateZ(PI * (i - 2) / 6));
			p = new EnemyAppend(Wing.getShape() ,30 ,-1);//p = new Wing();
			(cast(Enemy)p).disableBorder();
			//partsManager.add(append3);
			childHash[rw1].addChild(p ,rw2 ,60 , ENGAGED);
			p = new WingTurret(30);//p = new Wing();
			(cast(Enemy)p).disableBorder();
			//partsManager.add(append3);
			childHash[rw2].addChild(p ,rw3 ,60 , ENGAGED);
			
			p = new EnemyAppend(Wing.getShape() ,30 ,-1);//p = new Wing();
			(cast(Enemy)p).disableBorder();
			
			//partsManager.add(append);
			childHash["lWingBase"].addChild(p ,lw0 ,60 ,ENGAGED ,matRotateX(90) * matRotateZ(180 - 30 * (i - 2.0)) * matRotateX(-20)) ;
			p = new EnemyAppend(Wing.getShape() ,30 ,-1);//p = new Wing();
			(cast(Enemy)p).disableBorder();
			//partsManager.add(append2);
			childHash[lw0].addChild(p ,lw1 ,60 , ENGAGED);//matRotateX(PI / 2.0) * matRotateZ(PI * (1.0 + ((i - 2.0) / 6.0))));
			p = new EnemyAppend(Wing.getShape() ,30 ,-1);//p = new Wing();
			(cast(Enemy)p).disableBorder();
			//partsManager.add(append3);
			childHash[lw1].addChild(p ,lw2 ,60 , ENGAGED);
			p = new WingTurret(30);//p = new Wing();
			(cast(Enemy)p).disableBorder();
			//partsManager.add(append3);
			childHash[lw2].addChild(p ,lw3 ,60 , ENGAGED);
		}
		
		
		for(int i = 1;i < 4;i ++){
			char[] t1 = "tail_"~str.toString(i-1);
			char[] t2 = "tail_"~str.toString(i);
			p = new EnemyAppend(Tail.getShape() ,30 ,-1);//p = new Tail();
			(cast(Enemy)p).disableBorder();
			childHash[t1].addChild(p ,t2 ,60 ,ENGAGED);
			//append2 = append;
		}
		p = new TailTurret(30);//p = new Tail();
		(cast(Enemy)p).disableBorder();
		childHash["tail_3"].addChild(p ,"tail_4" ,60 ,ENGAGED);
		changeScale(1.3 ,true);
		rotateAll(matRotateX(-30 ) );
		rotateAll(matRotateY(120 ) );
		
		
		childHash["tail_0"].addAnimation(new Swing(200 ,BOTHZ ,-0.4 ,0.8 ,20 ,true) ,"swing");
		childHash["lWingBase"].addAnimation(new Swing(120 ,BOTHZ ,-0.7 ,0.9 ,20 ,true) ,"swing");
		childHash["rWingBase"].addAnimation(new Swing(120 ,BOTHZ ,-0.7 ,0.9 ,20 ,true) ,"swing");
		childHash["head"].addAnimation(new RotateTo(120 ,BOTHZ ,-30 ,0.0 ) ,"nod");
		
		addAnimation(new RotateAll(200 ,matRotateY(0.2)) ,"turn");
	}
	public void move(){
		super.move();
		switch(state){
			case "start":
			if(rpos.z < -800 - 2)pos.z +=2.0;
			else if(-800 + 2 < rpos.z)pos.z -= 2.0;
			else {
				if("head" in childHash && childHash["head"])childHash["head"].addAnimation(new RotateTo(70 ,POSEY ,80) ,"turn1");
				headright ^= true;
				changeState("attack1");
			}
			break;
			case "attack1":
			if("head" in childHash && childHash["head"]){
				if(!childHash["head"].inAnimation("turn1")){
					if(headright)childHash["head"].addAnimation(new RotateTo(140 ,POSEY ,80) ,"turn1");
					else childHash["head"].addAnimation(new RotateTo(140 ,POSEY ,-80) ,"turn1");
					headright ^= true;
				}
				
			}
			if(nowStateCnt == 270){
				changeState("stop1");
				if("head" in childHash && childHash["head"]){
					childHash["head"].addAnimation(new RotateTo(60 ,POSEY ,0) ,"fix");
				}
			}
			if(nowStateCnt % 7 == 0){
				if("head" in childHash && childHash["head"])new AttackRing(cast(Enemy)childHash["head"] ,"laser" ,30);
			}
			if(110 <= nowStateCnt && nowStateCnt < 130 && nowStateCnt % 11 == 0){
				if("rWing_0_3" in childHash && childHash["rWing_0_3"])new AttackRing(cast(Enemy)childHash["rWing_0_3"] ,"laser" ,60);
				if("rWing_1_3" in childHash && childHash["rWing_1_3"])new AttackRing(cast(Enemy)childHash["rWing_1_3"] ,"laser" ,60);
				if("rWing_2_3" in childHash && childHash["rWing_2_3"])new AttackRing(cast(Enemy)childHash["rWing_2_3"] ,"laser" ,60);
				if("rWing_3_3" in childHash && childHash["rWing_3_3"])new AttackRing(cast(Enemy)childHash["rWing_3_3"] ,"laser" ,60);
				if("rWing_4_3" in childHash && childHash["rWing_4_3"])new AttackRing(cast(Enemy)childHash["rWing_4_3"] ,"laser" ,60);
				if("lWing_0_3" in childHash && childHash["lWing_0_3"])new AttackRing(cast(Enemy)childHash["lWing_0_3"] ,"laser" ,60);
				if("lWing_1_3" in childHash && childHash["lWing_1_3"])new AttackRing(cast(Enemy)childHash["lWing_1_3"] ,"laser" ,60);
				if("lWing_2_3" in childHash && childHash["lWing_2_3"])new AttackRing(cast(Enemy)childHash["lWing_2_3"] ,"laser" ,60);
				if("lWing_3_3" in childHash && childHash["lWing_3_3"])new AttackRing(cast(Enemy)childHash["lWing_3_3"] ,"laser" ,60);
				if("lWing_4_3" in childHash && childHash["lWing_4_3"])new AttackRing(cast(Enemy)childHash["lWing_4_3"] ,"laser" ,60);
			}
			/*
			if(nowStateCnt % 30 == 0){
				if("tail_4" in childHash && childHash["tail_4"])new AttackRing(cast(Enemy)childHash["tail_4"] ,"enemy" ,60);
			}
			*/
			/*
			if(nowStateCnt % 30 == 0){
				if("rWing_0_3" in childHash && childHash["rWing_0_3"])new AttackRing(cast(Enemy)childHash["rWing_0_3"] ,"laser" ,30);
				if("rWing_1_3" in childHash && childHash["rWing_1_3"])new AttackRing(cast(Enemy)childHash["rWing_1_3"] ,"laser" ,30);
				if("rWing_2_3" in childHash && childHash["rWing_2_3"])new AttackRing(cast(Enemy)childHash["rWing_2_3"] ,"laser" ,30);
				if("rWing_3_3" in childHash && childHash["rWing_3_3"])new AttackRing(cast(Enemy)childHash["rWing_3_3"] ,"laser" ,30);
				if("rWing_4_3" in childHash && childHash["rWing_4_3"])new AttackRing(cast(Enemy)childHash["rWing_4_3"] ,"laser" ,30);
				if("lWing_0_3" in childHash && childHash["lWing_0_3"])new AttackRing(cast(Enemy)childHash["lWing_0_3"] ,"laser" ,30);
				if("lWing_1_3" in childHash && childHash["lWing_1_3"])new AttackRing(cast(Enemy)childHash["lWing_1_3"] ,"laser" ,30);
				if("lWing_2_3" in childHash && childHash["lWing_2_3"])new AttackRing(cast(Enemy)childHash["lWing_2_3"] ,"laser" ,30);
				if("lWing_3_3" in childHash && childHash["lWing_3_3"])new AttackRing(cast(Enemy)childHash["lWing_3_3"] ,"laser" ,30);
				if("lWing_4_3" in childHash && childHash["lWing_4_3"])new AttackRing(cast(Enemy)childHash["lWing_4_3"] ,"laser" ,30);
			}
			*/
			break;
			case "stop1":
			if(nowStateCnt == 30){
				addAnimation(new RotateAll(100 ,matRotateY(0.4)) ,"turn");
				changeState("move1");
			}
			break;
			case "move1":
			if(-100 < rpos.x)pos.x -= 1.0;
			else{
				changeState("attack2");
			}
			if(nowStateCnt % 30 == 0){
				if("tail_4" in childHash && childHash["tail_4"])new AttackRing(cast(Enemy)childHash["tail_4"] ,"enemy" ,60);
			}
			break;
			case "attack2":
			if("head" in childHash && childHash["head"]){
				if(!childHash["head"].inAnimation("turn1")){
					if(headright)childHash["head"].addAnimation(new RotateTo(140 ,POSEY ,80) ,"turn1");
					else childHash["head"].addAnimation(new RotateTo(140 ,POSEY ,-80) ,"turn1");
					headright ^= true;
				}
				
			}
			if(nowStateCnt == 270){
				changeState("stop2");
				if("head" in childHash && childHash["head"]){
					childHash["head"].addAnimation(new RotateTo(60 ,POSEY ,0) ,"fix");
				}
			}
			if(nowStateCnt % 7 == 0){
				if("head" in childHash && childHash["head"])new AttackRing(cast(Enemy)childHash["head"] ,"laser" ,30);
			}
			if(110 <= nowStateCnt && nowStateCnt < 130 && nowStateCnt % 10 == 0){
				if("rWing_0_3" in childHash && childHash["rWing_0_3"])new AttackRing(cast(Enemy)childHash["rWing_0_3"] ,"laser" ,60);
				if("rWing_1_3" in childHash && childHash["rWing_1_3"])new AttackRing(cast(Enemy)childHash["rWing_1_3"] ,"laser" ,60);
				if("rWing_2_3" in childHash && childHash["rWing_2_3"])new AttackRing(cast(Enemy)childHash["rWing_2_3"] ,"laser" ,60);
				if("rWing_3_3" in childHash && childHash["rWing_3_3"])new AttackRing(cast(Enemy)childHash["rWing_3_3"] ,"laser" ,60);
				if("rWing_4_3" in childHash && childHash["rWing_4_3"])new AttackRing(cast(Enemy)childHash["rWing_4_3"] ,"laser" ,60);
				if("lWing_0_3" in childHash && childHash["lWing_0_3"])new AttackRing(cast(Enemy)childHash["lWing_0_3"] ,"laser" ,60);
				if("lWing_1_3" in childHash && childHash["lWing_1_3"])new AttackRing(cast(Enemy)childHash["lWing_1_3"] ,"laser" ,60);
				if("lWing_2_3" in childHash && childHash["lWing_2_3"])new AttackRing(cast(Enemy)childHash["lWing_2_3"] ,"laser" ,60);
				if("lWing_3_3" in childHash && childHash["lWing_3_3"])new AttackRing(cast(Enemy)childHash["lWing_3_3"] ,"laser" ,60);
				if("lWing_4_3" in childHash && childHash["lWing_4_3"])new AttackRing(cast(Enemy)childHash["lWing_4_3"] ,"laser" ,60);
			}
			break;
			case "stop2":
			if(nowStateCnt == 60){
				addAnimation(new RotateAll(100 ,matRotateY(-0.4)) ,"turn");
				changeState("move2");
				
			}
			break;
			case "move2":
			if(rpos.x < 100)pos.x += 1.0;
			else{
				changeState("attack1");
			}
			if(nowStateCnt % 30 == 0){
				if("tail_4" in childHash && childHash["tail_4"])new AttackRing(cast(Enemy)childHash["tail_4"] ,"enemy" ,60);
			}
			break;
			default:break;
		}
		/*
		if(cnt > 200){
			Animation swing = childHash["tail_0"].animes["swing"];
			if(swing !is null && swing.count % swing.span == 0){
				swing.vanish();
				childHash["tail_0"].addAnimation(new Swing(200 ,BOTHZ ,-0.6 ,0.9 ,20 ,true) ,"swing");
			}
		}
		*/
	}
	
}
public class Boss5:Boss{
	
	//import br.mainloop;
	private{
		double aim;
		static Shape baseShape;
		static  float[] a = 
		
			[-1.0 ,-0.7 ,0.6 ,1.0 ,0.8 ,1.0 ,0.6 ,-0.7 ,-1.0];
  	static float[] b =
			[0.3  ,1.0 ,0.8  ,0.3 ,0.0 ,-0.3 ,-0.8 ,-1.0 ,-0.3];
	static float[] sz =
	[-0.5 ,0.0 ,0.5];
	static float[] scale = 
	[0.6 ,1.0 ,0.6];

	}
	
	public this(double x,double y,double z,double aim){
		super(9);
		Matrix po =  matRotateX(0);
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;
		//super(pos ,po);
		//set(pos ,p);
		//setPoseBase(p);
		size =  60;
		collisionRange = 30;

		
		if(baseShape is null){
			baseShape = new SH_Pot(a ,b ,sz ,scale);
		}
    shape = cast(Shape)baseShape.clone();
		Parts p;//Parts p;
		
		p = new EnemyAppend(TubeShape.getShape() ,30 ,8);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "tube1", 110 ,ENGAGED );p.linkZ = p.poseZ = 90;
		p = new NailTurret(30);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		childHash["tube1"].addChild(p, "nail1", 110 ,ENGAGED);
		p = new EnemyAppend(TubeShape.getShape() ,30 ,8);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "tube2", 110 ,ENGAGED);p.linkZ = p.poseZ = 45;
		p = new NailTurret(30);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		childHash["tube2"].addChild(p, "nail2", 110 ,ENGAGED);// ,matRotateZ(0));
		p = new EnemyAppend(TubeShape.getShape() ,30 ,8);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "tube3", 110 ,ENGAGED);p.linkZ = p.poseZ = -45;
		p = new NailTurret(30);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		childHash["tube3"].addChild(p, "nail3", 110 ,ENGAGED);// ,matRotateZ(0));
		p = new EnemyAppend(TubeShape.getShape() ,30 ,8);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "tube4", 110 ,ENGAGED);p.linkZ = p.poseZ = -90;
		p = new NailTurret(30);//new BaseOfWing();
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		childHash["tube4"].addChild(p, "nail4", 110 ,ENGAGED);
		if("tube1" in childHash && childHash["tube1"].exists)childHash["tube1"].addAnimation( new RotateTo(60 ,BOTHZ ,20 ,1.0) ,"pose");
			if("tube2" in childHash && childHash["tube2"].exists)childHash["tube2"].addAnimation( new RotateTo(60 ,BOTHZ ,10 ,1.0) ,"pose");
			if("tube3" in childHash && childHash["tube3"].exists)childHash["tube3"].addAnimation( new RotateTo(60 ,BOTHZ ,-10 ,1.0) ,"pose");
			if("tube4" in childHash && childHash["tube4"].exists)childHash["tube4"].addAnimation( new RotateTo(60 ,BOTHZ ,-20 ,1.0) ,"pose");
	}
	public void move(){
		super.move();
		switch(state){
			case "start":
			if(rpos.z < -800 - 2.0)pos.z += 2.0;
			else if(rpos.z > -800 + 2.0)pos.z -= 2.0;
			else changeState("attack");
			if(nowStateCnt == 61){
				if("tube1" in childHash && childHash["tube1"].exists)childHash["tube1"].addAnimation( new RotateTo(60 ,BOTHZ ,90 ,1.0) ,"pose");
			if("tube2" in childHash && childHash["tube2"].exists)childHash["tube2"].addAnimation( new RotateTo(60 ,BOTHZ ,45 ,1.0) ,"pose");
			if("tube3" in childHash && childHash["tube3"].exists)childHash["tube3"].addAnimation( new RotateTo(60 ,BOTHZ ,-45 ,1.0) ,"pose");
			if("tube4" in childHash && childHash["tube4"].exists)childHash["tube4"].addAnimation( new RotateTo(60 ,BOTHZ ,-90 ,1.0) ,"pose");
			}
			
			break;
			case "attack":
			switch(nowStateCnt % 120){
				case 0:
				if("tube2" in childHash && childHash["tube2"].exists){
					childHash["tube2"].addAnimation( new RotateTo(90 ,BOTHZ ,rand.nextFloat(50)+30.0) ,"aim");
				}
				break;
				case 35:case 40:case 45:
				if("nail2" in childHash && childHash["nail2"].exists){
					new AttackRing(cast(Enemy)childHash["nail2"] ,"reflect" ,60);
				}
				break;
				case 60:
				if("tube3" in childHash && childHash["tube3"].exists){
					childHash["tube3"].addAnimation( new RotateTo(90 ,BOTHZ ,-rand.nextFloat(50)-30.0) ,"aim");
				}
				break;
				
				case 95:case 100:case 105:
				if("nail3" in childHash && childHash["nail3"].exists){
					new AttackRing(cast(Enemy)childHash["nail3"] ,"reflect" ,60);
				}
				break;
				default:break;
			}
			switch(nowStateCnt % 120){
				case 0:
				if("tube1" in childHash && childHash["tube1"].exists){
					childHash["tube1"].addAnimation( new RotateTo(25 ,BOTHZ ,40 ,-1.0) ,"up");
				}
				if("nail1" in childHash && childHash["nail1"].exists){
					new AttackRing(cast(Enemy)childHash["nail1"] ,"wall" ,60);
				}
				break;
				case 30:
				if("tube1" in childHash && childHash["tube1"].exists){
					childHash["tube1"].addAnimation( new RotateTo(25 ,BOTHZ ,90,-1.0) ,"down" );
				}
				break;
				case 60:
				if("tube4" in childHash && childHash["tube4"].exists){
					childHash["tube4"].addAnimation( new RotateTo(25 ,BOTHZ ,-40 ,-1.0) ,"up");
				}
				if("nail4" in childHash && childHash["nail4"].exists){
//					Log_write(nowStateCnt);
					new AttackRing(cast(Enemy)childHash["nail4"] ,"wall" ,60);
				}
				break;
				case 90:
				if("tube4" in childHash && childHash["tube4"].exists){
					childHash["tube4"].addAnimation( new RotateTo(25 ,BOTHZ ,-90,-1.0) ,"down" );
				}
				
				default:break;
			}
			if(nowStateCnt == 600){
				changeState("rest1");
				
			}
			break;
			case "rest1":
			if(nowStateCnt == 60){
				if("tube1" in childHash && childHash["tube1"].exists)childHash["tube1"].addAnimation( new RotateTo(60 ,BOTHZ ,90 ,0.0) ,"pose");
				if("tube2" in childHash && childHash["tube2"].exists)childHash["tube2"].addAnimation( new RotateTo(60 ,BOTHZ ,45 ,0.0) ,"pose");
				if("tube3" in childHash && childHash["tube3"].exists)childHash["tube3"].addAnimation( new RotateTo(60 ,BOTHZ ,-45 ,0.0) ,"pose");
				if("tube4" in childHash && childHash["tube4"].exists)childHash["tube4"].addAnimation( new RotateTo(60 ,BOTHZ ,-90 ,0.0) ,"pose");
				if("nail1" in childHash && childHash["nail1"].exists)childHash["nail1"].addAnimation( new RotateTo(60 ,BOTHZ ,0 ,0.0) ,"pose");
				if("nail2" in childHash && childHash["nail2"].exists)childHash["nail2"].addAnimation( new RotateTo(60 ,BOTHZ ,-45 ,0.0) ,"pose");
				if("nail3" in childHash && childHash["nail3"].exists)childHash["nail3"].addAnimation( new RotateTo(60 ,BOTHZ ,45 ,0.0) ,"pose");
				if("nail4" in childHash && childHash["nail4"].exists)childHash["nail4"].addAnimation( new RotateTo(60 ,BOTHZ ,0 ,0.0) ,"pose");
			}
			if(nowStateCnt == 240){
				if("nail2" in childHash && childHash["nail2"].exists)childHash["nail2"].addAnimation( new RotateTo(60 ,BOTHZ ,0 ,0.0) ,"pose");
				if("nail3" in childHash && childHash["nail3"].exists)childHash["nail3"].addAnimation( new RotateTo(60 ,BOTHZ ,0 ,0.0) ,"pose");
				changeState("rest2");
			}
			break;
			case "rest2":
				if(nowStateCnt == 60)changeState("attack");
			break;
			default:break;
		}
	}
	
}
public class Boss6:Boss{
	
	//import br.mainloop;
	private{
		double aim;
		static Shape baseShape;
		static  float[] a = 
		
			[-1.3 ,-0.9 ,0.0 ,0.9 ,1.3 ,0.9 ,0.0 ,-0.9];
  	static float[] b =
			[0.0  ,0.6  ,1.0 ,0.6 ,0.0 ,-0.6 ,-1.0 ,-0.6];
	static float[] sz =
	[-0.6 ,0.0 ,0.6];
	static float[] scale = 
	[0.7 ,1.0 ,0.7];

	}
	int[6] reload;
	bool right;
	public this(double x,double y,double z,double aim){
		super(18);
		Matrix po =  matRotateX(0);
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;
		//super(pos ,po);
		//set(pos ,p);
		//setPoseBase(p);
		size =  50;
		collisionRange = 25;

		
		if(baseShape is null){
			baseShape = new SH_Pot(a ,b ,sz ,scale);
		}
   		 shape = cast(Shape)baseShape.clone();
		Parts p;//Parts p;
		
		p = new Turret2(50 ,12);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "t1", 280 ,ENGAGED ,new Matrix());p.poseZ = 90;p.linkZ = -5;
		p = new Turret2(50 ,12);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "t2", 190 ,ENGAGED ,new Matrix());p.poseZ = 90;p.linkZ = 0;
		p = new Turret2(50 ,12);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "t3", 100 ,ENGAGED ,new Matrix());p.poseZ = 90;p.linkZ = 10;
		
		p = new Turret2(50 ,12);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "t4", 100 ,ENGAGED ,new Matrix());p.poseZ = 90;p.linkZ = 170;
		p = new Turret2(50 ,12);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "t5", 190 ,ENGAGED ,new Matrix());p.poseZ = 90;p.linkZ = 180;
		p = new Turret2(50 ,12);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		//partsManager.add(wing1);
		addChild(p, "t6", 280 ,ENGAGED ,new Matrix());p.poseZ = 90;p.poseX = 180;p.linkZ = -175;
		
		
		foreach(inout r;reload){
			r = rand.nextInt(180);
		}
		right = true;
		/*
		p = new EnemyAppend(ShipShape.getShape() ,200 ,-1);
		(cast(Enemy)p).disableBorder();
		//partsManager.add(wing1);
		addChild(p, "nose", 80 ,ENGAGED ,matRotateY(90) ,new Matrix());
		p = new EnemyAppend(ShipShape.getShape() ,200 ,-1);
		(cast(Enemy)p).disableBorder();
		//partsManager.add(wing1);
		addChild(p, "nose", 80 ,ENGAGED ,matRotateY(-90) ,new Matrix());
		*/
	}
	public void move(){
		super.move();
		switch(state){
			case "start":
			if(rpos.y < -200)pos.y += 1.5;
			else {
				if("t3" in childHash && childHash["t3"].exists){
					childHash["t3"].addAnimation(new RotateTo(30 ,POSEY ,-90) ,"set");
				}
				if("t4" in childHash && childHash["t4"].exists){
					childHash["t4"].addAnimation(new RotateTo(30 ,POSEY ,-90) ,"set");
				}
				if("t1" in childHash && childHash["t1"].exists){
					childHash["t1"].addAnimation(new RotateTo(30 ,POSEZ ,70) ,"set");
				}
				if("t6" in childHash && childHash["t6"].exists){
					childHash["t6"].addAnimation(new RotateTo(30 ,POSEZ ,110) ,"set");
				}
				changeState("standby2");
			}
			attack1();
			break;
			case "standby1":
			if(nowStateCnt >= 30)changeState("attack1");
			break;
			case "attack1":
			attack1();
			if(right){
				if(rpos.x < 150.0)pos.x += 1.0;
				else right ^= true;
			}else{
				if(-150.0 < rpos.x)pos.x -= 1.0;
				else right ^= true;
			}
			if(nowStateCnt >= 450){
				if("t3" in childHash && childHash["t3"].exists){
					childHash["t3"].addAnimation(new RotateTo(30 ,POSEY ,-90) ,"set");
				}
				if("t4" in childHash && childHash["t4"].exists){
					childHash["t4"].addAnimation(new RotateTo(30 ,POSEY ,-90) ,"set");
				}
				if("t1" in childHash && childHash["t1"].exists){
					childHash["t1"].addAnimation(new RotateTo(30 ,POSEZ ,70) ,"set");
				}
				if("t6" in childHash && childHash["t6"].exists){
					childHash["t6"].addAnimation(new RotateTo(30 ,POSEZ ,110) ,"set");
				}
				changeState("standby2");
			}
			break;
			case "standby2":
			if(nowStateCnt >= 30)changeState("attack2");
			break;
			case "attack2":
			if(right){
				if(rpos.x < 150.0)pos.x += 1.0;
				else right ^= true;
			}else{
				if(-150.0 < rpos.x)pos.x -= 1.0;
				else right ^= true;
			}
			if(nowStateCnt >= 450){
				if("t3" in childHash && childHash["t3"].exists){
					childHash["t3"].addAnimation(new RotateTo(30 ,POSEY ,0) ,"set");
				}
				if("t4" in childHash && childHash["t4"].exists){
					childHash["t4"].addAnimation(new RotateTo(30 ,POSEY ,0) ,"set");
				}
				if("t1" in childHash && childHash["t1"].exists){
					childHash["t1"].addAnimation(new RotateTo(30 ,POSEZ ,90) ,"set");
				}
				if("t6" in childHash && childHash["t6"].exists){
					childHash["t6"].addAnimation(new RotateTo(30 ,POSEZ ,90) ,"set");
				}
				changeState("standby1");
			}
			attack2();
			break;
			default:break;
		}
	}
	public void attack1(){
		
		if(reload[0] <= 0){
			if("t1" in childHash && childHash["t1"].exists){
				
				new AttackRing(cast(Enemy)childHash["t1"] ,"missile" ,30);
				
			}
			reload[0] = rand.nextInt(90) + 120;
		}
		if(reload[1] <= 0){
			if("t2" in childHash && childHash["t2"].exists){
				
				new AttackRing(cast(Enemy)childHash["t2"] ,"missile" ,30);
			}
			reload[1] = rand.nextInt(90) + 120;
		}
		if(reload[2] <= 0){
			if("t3" in childHash && childHash["t3"].exists){
				
				new AttackRing(cast(Enemy)childHash["t3"] ,"missile" ,30);
			}
			reload[2] = rand.nextInt(60) + 90;
		}
		if(reload[3] <= 0){
			if("t4" in childHash && childHash["t4"].exists){
				
				new AttackRing(cast(Enemy)childHash["t4"] ,"missile" ,30);
			}
			reload[3] = rand.nextInt(60) + 90;
		}
		if(reload[4] <= 0){
			if("t5" in childHash && childHash["t5"].exists){
				
				new AttackRing(cast(Enemy)childHash["t5"] ,"missile" ,30);
			}
			reload[4] = rand.nextInt(90) + 120;
		}
		if(reload[5] <= 0){
			if("t6" in childHash && childHash["t6"].exists){
				
				new AttackRing(cast(Enemy)childHash["t6"] ,"missile" ,30);
			}
			reload[5] = rand.nextInt(90) + 120;
		}
		foreach(inout r;reload){
			r --;
		}
	}
	public void attack2(){
		if(nowStateCnt % 10 == 0){
			if("t2" in childHash && childHash["t2"].exists){
				new AttackRing(cast(Enemy)childHash["t2"] ,"laser" ,30);
			}
			if("t5" in childHash && childHash["t5"].exists){
				new AttackRing(cast(Enemy)childHash["t5"] ,"laser" ,30);
			}
		}
		if(nowStateCnt % 90 == 0){
			if("t1" in childHash && childHash["t1"].exists){
				new AttackRing(cast(Enemy)childHash["t1"] ,"bomb" ,30);
			}
		}
		if(nowStateCnt % 90 == 45){
			if("t6" in childHash && childHash["t6"].exists){
				new AttackRing(cast(Enemy)childHash["t6"] ,"bomb" ,30);
			}
		}
	}
}

public class Boss7:Boss{
	
	//import br.mainloop;
	private{
		double aim;
		static Shape baseShape;
		static  float[] a = 
		
			[-1.3 ,-0.9 ,0.0 ,0.9 ,1.3 ,0.9 ,0.0 ,-0.9];
  	static float[] b =
			[0.0  ,0.6  ,1.0 ,0.6 ,0.0 ,-0.6 ,-1.0 ,-0.6];
	static float[] sz =
	[-0.6 ,0.0 ,0.6];
	static float[] scale = 
	[0.7 ,1.0 ,0.7];

	}
	int[6] reload;
	bool right;
	
	char[] runState;
	int nowRunStateCnt;
	int speed;
	public this(double x,double y,double z,double aim){
		super(18);
		Matrix po =  matRotateX(0);
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;
		//super(pos ,po);
		//set(pos ,p);
		//setPoseBase(p);
		size =  40;
		collisionRange = 25;
		
		nowRunStateCnt = 0;
		runState = "start";
		speed = 10;

		/*
		if(baseShape is null){
			baseShape = new SH_Pot(a ,b ,sz ,scale);
		}
		*/
   		 shape = BodyShape.getShape();
		Parts p;//Parts p;
		
		p = new HeadTurret2(50);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		addChild(p, "head", 80 ,ENGAGED ,matRotateZ(20) ,matRotateZ(-40));
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		addChild(p, "rshoulder", 80 ,ENGAGED ,matRotateY(90));
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		addChild(p, "lshoulder", 80 ,ENGAGED ,matRotateY(-90));
		p = new EnemyAppend(BodyShape.getShape() ,40 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		addChild(p, "body", 120 ,ENGAGED ,matRotateZ(180));
		p = new EnemyAppend(BodyShape.getShape() ,40 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["body"].addChild(p, "ass", 100 ,ENGAGED ,matRotateZ(180));
		
		p = new EnemyAppend(TubeShape.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["rshoulder"].addChild(p, "rarm", 60 ,ENGAGED ,matRotateZ(-60));
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,20 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["rarm"].addChild(p, "rarmjoint", 60 ,ENGAGED ,matRotateZ(-60));
		p = new ArmTurret(30);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["rarmjoint"].addChild(p, "rhand", 80 ,ENGAGED ,matRotateZ(-60));
		p = new EnemyAppend(TubeShape.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["lshoulder"].addChild(p, "larm", 80 ,ENGAGED ,matRotateZ(-60));
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,20 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["larm"].addChild(p, "larmjoint", 60 ,ENGAGED ,matRotateZ(-60));
		p = new ArmTurret(30);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["larmjoint"].addChild(p, "lhand", 60 ,ENGAGED ,matRotateZ(-60));
		
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["ass"].addChild(p, "rhipjoint", 80 ,ENGAGED ,matRotateY(90));
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["ass"].addChild(p, "lhipjoint", 80 ,ENGAGED ,matRotateY(-90));
		
		p = new EnemyAppend(TubeShape.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["rhipjoint"].addChild(p, "rthigh",80 ,ENGAGED ,matRotateZ(-120));
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,20 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["rthigh"].addChild(p, "rthighjoint", 60 ,ENGAGED ,matRotateZ(-120));
		p = new ArmTurret(30);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["rthighjoint"].addChild(p, "rfoot", 80 ,ENGAGED ,matRotateZ(-120));
		p = new EnemyAppend(TubeShape.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["lhipjoint"].addChild(p, "lthigh", 80 ,ENGAGED ,matRotateZ(-120));
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,20 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["lthigh"].addChild(p, "lthighjoint", 60 ,ENGAGED ,matRotateZ(-120));
		p = new ArmTurret(30);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["lthighjoint"].addChild(p, "lfoot", 80 ,ENGAGED ,matRotateZ(-120));
		
		p = new EnemyAppend(TubeShape.getShape() ,30 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["ass"].addChild(p, "tail1", 80 ,ENGAGED ,matRotateZ(150));
		p = new EnemyAppend(new SH_Sphere(1.0 ,6) ,20 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["tail1"].addChild(p, "tailjoint", 60 ,ENGAGED ,matRotateZ(150));
		p = new TailTurret2(30);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision();
		childHash["tailjoint"].addChild(p, "tail2", 60 ,ENGAGED ,matRotateZ(150));
	}
	public void move(){
		super.move();
		double dx = 0.0;
		switch(state){
			case "start":
			if(rpos.x < 400){
				dx = 5 + (400 - rpos.x) /100;
			}else changeState("standby");
			break;
			case "standby":
			if(rpos.z < -800){
				pos.z += 2.0;
			}else changeState("attack1");
			break;
			case "attack1":
			if(-300 < rpos.x){
				dx = -1;
			}else changeState("attack2");
			if(nowStateCnt % 5 == 0){
				if("tail2" in childHash && childHash["tail2"].exists){
					new AttackRing(cast(Enemy)childHash["tail2"] ,"shot" ,30);
				}
			}
			switch(cnt % 240){
				case 0:
				if("rhand" in childHash && childHash["rhand"].exists){
					new AttackRing(cast(Enemy)childHash["rhand"] ,"shot" ,60);
				}
				break;
				case 60:
				if("lhand" in childHash && childHash["lhand"].exists){
					new AttackRing(cast(Enemy)childHash["lhand"] ,"shot" ,60);
				}
				break;
				case 120:
				if("rfoot" in childHash && childHash["rfoot"].exists){
					new AttackRing(cast(Enemy)childHash["rfoot"] ,"shot" ,60);
				}
				break;
				case 180:
				if("lfoot" in childHash && childHash["lfoot"].exists){
					new AttackRing(cast(Enemy)childHash["lfoot"] ,"shot" ,60);
				}
				break;
				default:break;
			}
			/*
			if(cnt % 500 == 0){
				if("head" in childHash && childHash["head"].exists){
					new AttackRing(cast(Enemy)childHash["head"] ,"shot" ,30);
				}
			}
			
			*/
			break;
			case "attack2":
			if(nowStateCnt == 120){
				if("head" in childHash && childHash["head"].exists){
					new AttackRing(cast(Enemy)childHash["head"] ,"eightway" ,30);
				}
			}
			if(nowStateCnt % 5 == 0){
				if("tail2" in childHash && childHash["tail2"].exists){
					new AttackRing(cast(Enemy)childHash["tail2"] ,"shot" ,30);
				}
			}
			
			if(nowStateCnt > 390){
				changeState("attack3");
			}
			break;
			case "attack3":
			if(rpos.x < 500){
				dx = 2;
			}else{
				 changeState("attack4");
				 childHash["tail1"].addAnimation(new RotateTo(20 ,BOTHZ , -30 ,0.5) ,"stand");
			}
			if(nowStateCnt % 5 == 0){
				if("tail2" in childHash && childHash["tail2"].exists){
					new AttackRing(cast(Enemy)childHash["tail2"] ,"shot" ,30);
				}
			}
			switch(cnt % 240){
				case 0:
				if("rhand" in childHash && childHash["rhand"].exists){
					new AttackRing(cast(Enemy)childHash["rhand"] ,"shot" ,60);
				}
				break;
				case 60:
				if("lhand" in childHash && childHash["lhand"].exists){
					new AttackRing(cast(Enemy)childHash["lhand"] ,"shot" ,60);
				}
				break;
				case 120:
				if("rfoot" in childHash && childHash["rfoot"].exists){
					new AttackRing(cast(Enemy)childHash["rfoot"] ,"shot" ,60);
				}
				break;
				case 180:
				if("lfoot" in childHash && childHash["lfoot"].exists){
					new AttackRing(cast(Enemy)childHash["lfoot"] ,"shot" ,60);
				}
				break;
				default:break;
			}
			/*
			if(cnt % 500 == 0){
				if("head" in childHash && childHash["head"].exists){
					new AttackRing(cast(Enemy)childHash["head"] ,"shot" ,30);
				}
			}
			*/
			break;
			case "attack4":
			if(nowStateCnt > 90 && nowStateCnt % 10 == 0){
				if("tail2" in childHash && childHash["tail2"].exists){
					new AttackRing(cast(Enemy)childHash["tail2"] ,"eightway" ,30);
				}
			}
			
			if(nowStateCnt > 390){
				childHash["tail1"].addAnimation(new RotateTo(20 ,BOTHZ , 0 ,0.5) ,"stand");
				changeState("attack1");
			}
			default:break;
		
		}
		
		pos.x += dx;
		speed = cast(int)(fmax(1.0 ,10 - 0.4 * dx));
		
		run(speed);
		
	}
	public void run(int speed){
		nowRunStateCnt ++;
		switch(runState){
			case "start":
			changeRunState("r4");
			
			break;
			/*
			case "1":
			if(nowStateCnt > 15){
				childHash["lhand"].addAnimation(new RotateTo(15 ,BOTHZ , 0 ) ,"walk");
				childHash["rfoot"].addAnimation(new RotateTo(15 ,BOTHZ , 0 ) ,"walk");
				
				changeRunState("2");
			}
			break;
			case "2":
			if(nowStateCnt > 15){
				childHash["rarm"].addAnimation(new RotateTo(30 ,BOTHZ , 0) ,"walk");
				childHash["lthigh"].addAnimation(new RotateTo(30 ,BOTHZ , 0 ) ,"walk");
				
				
				childHash["larm"].addAnimation(new RotateTo(30 ,BOTHZ , -60 ) ,"walk");
				childHash["lhand"].addAnimation(new RotateTo(30 ,BOTHZ , 60 ) ,"walk");
				childHash["rthigh"].addAnimation(new RotateTo(30 ,BOTHZ , 60 ) ,"walk");
				childHash["rfoot"].addAnimation(new RotateTo(30 ,BOTHZ , -60 ) ,"walk");
				
				
				changeRunState("3");
			}
			break;
			case "3":
			if(nowStateCnt > 15){
				childHash["rhand"].addAnimation(new RotateTo(15 ,BOTHZ , 0 ) ,"walk");
				childHash["lfoot"].addAnimation(new RotateTo(15 ,BOTHZ , 0 ) ,"walk");
				changeRunState("4");
			}
			break;
			case "4":
			if(nowStateCnt > 15){
				childHash["rarm"].addAnimation(new RotateTo(30 ,BOTHZ , -60 ) ,"walk");
				childHash["rhand"].addAnimation(new RotateTo(30 ,BOTHZ , 60 ) ,"walk");
				childHash["lthigh"].addAnimation(new RotateTo(30 ,BOTHZ , 60 ) ,"walk");
				childHash["lfoot"].addAnimation(new RotateTo(30 ,BOTHZ , -60 ) ,"walk");
				
				childHash["larm"].addAnimation(new RotateTo(30 ,BOTHZ , 0 ) ,"walk");
				childHash["rthigh"].addAnimation(new RotateTo(30 ,BOTHZ , 0 ) ,"walk");
				changeRunState("1");
			}
			
			break;
			
			*/
			case "r1":
			pos.y += 1.0;
			if(nowRunStateCnt >= speed-1){
				
				
				changeRunState("r2");
			}
			break;
			case "r2":
			if(nowRunStateCnt >= speed-1){
				childHash["rarm"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 20) ,"run");
				childHash["lthigh"].addAnimation(new RotateTo(speed*2 ,BOTHZ , -20 ) ,"run");
				childHash["larm"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 20 ) ,"run");
				childHash["rthigh"].addAnimation(new RotateTo(speed*2 ,BOTHZ , -20 ) ,"run");
				
				childHash["ass"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 0 ) ,"run");
				childHash["tail1"].addAnimation(new RotateTo(speed*2 ,BOTHZ , -10 ,0.5) ,"run");
				
				changeRunState("r3");
			}
			break;
			case "r3":
			pos.y -= 1.0;
			if(nowRunStateCnt >= speed-1){
				childHash["lhand"].addAnimation(new RotateTo(speed ,BOTHZ , 0 ) ,"run");
				childHash["rhand"].addAnimation(new RotateTo(speed ,BOTHZ , 0 ) ,"run");
				childHash["lfoot"].addAnimation(new RotateTo(speed ,BOTHZ , 0 ) ,"run");
				childHash["rfoot"].addAnimation(new RotateTo(speed ,BOTHZ , 0 ) ,"run");
				
//				childHash["tail1"].addAnimation(new RotateTo(20 ,BOTHZ , -30 ,0.5) ,"stand");
				
				changeRunState("r4");
			}
			break;
			case "r4":
			
			if(nowRunStateCnt >= speed-1){
				childHash["rarm"].addAnimation(new RotateTo(speed*2 ,BOTHZ , -80 ) ,"run");
				childHash["rhand"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 80 ) ,"run");
				childHash["lthigh"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 80 ) ,"run");
				childHash["lfoot"].addAnimation(new RotateTo(speed*2 ,BOTHZ , -80 ) ,"run");
				childHash["larm"].addAnimation(new RotateTo(speed*2 ,BOTHZ , -80 ) ,"run");
				childHash["lhand"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 80 ) ,"run");
				childHash["rthigh"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 80 ) ,"run");
				childHash["rfoot"].addAnimation(new RotateTo(speed*2 ,BOTHZ , -80 ) ,"run");
				
				childHash["ass"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 20 ) ,"run");
				childHash["tail1"].addAnimation(new RotateTo(speed*2 ,BOTHZ , 30 ,0.5) ,"run");
				
				
				changeRunState("r1");
			}
			
			break;
			default:break;
		}
	}
	public void changeRunState(char[] state){
		this.runState = state.dup;
		nowRunStateCnt = -1;
	}
}
public class Boss8:Boss{
	
	//import br.mainloop;
	private{
		double aim;
		static Shape baseShape;
		static  float[] a = 
   	    [-1.5 ,0.0 ,1.5]
				;
	 	static float[] b =
	      [0.0 	,1.0 	,0.0 ]
	      ;
	}
//	int[6] reload;
	bool right;
	double[6] speed;
	public this(double x,double y,double z,double aim){
		super(18);
		Matrix po =  matRotateY(90);
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;
		//super(pos ,po);
		//set(pos ,p);
		//setPoseBase(p);
		size =  50;
		collisionRange = 25;
		foreach(inout s;speed){
			s = 0.0;
		}
		
		
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b  ,6);
		}
		
   		 shape = cast(Shape)baseShape.clone();
		Parts p;//Parts p;
		
		p = new EnemyAppend(ArmShape2.getShape(),60 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(25);
		addChild(p, "arm11", 150 ,ENGAGED ,matRotateZ(0));
		p = new EnemyAppend(ArmShape2.getShape() ,60 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(25);
		addChild(p, "arm21", 150 ,ENGAGED ,matRotateZ(60));
		p = new EnemyAppend(ArmShape2.getShape() ,60 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(25);
		addChild(p, "arm31", 150 ,ENGAGED ,matRotateZ(120));
		p = new EnemyAppend(ArmShape2.getShape() ,60 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(25);
		addChild(p, "arm41", 150 ,ENGAGED ,matRotateZ(180));
		p = new EnemyAppend(ArmShape2.getShape() ,60 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(25);
		addChild(p, "arm51", 150 ,ENGAGED ,matRotateZ(-120));
		p = new EnemyAppend(ArmShape2.getShape() ,60 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(25);
		addChild(p, "arm61", 150 ,ENGAGED ,matRotateZ(-60));
		
		p = new JointTurret(30 ,10);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(20);
		childHash["arm11"].addChild(p, "arm12", 150 ,ENGAGED);
		p = new JointTurret(30 ,10);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(20);
		childHash["arm21"].addChild(p, "arm22", 150 ,ENGAGED);
		p = new JointTurret(30 ,10);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(20);
		childHash["arm31"].addChild(p, "arm32", 150 ,ENGAGED);
		p = new JointTurret(30 ,10);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(20);
		childHash["arm41"].addChild(p, "arm42", 150 ,ENGAGED);
		p = new JointTurret(30 ,10);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(20);
		childHash["arm51"].addChild(p, "arm52", 150 ,ENGAGED);
		p = new JointTurret(30 ,10);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(20);
		childHash["arm61"].addChild(p, "arm62", 150 ,ENGAGED);
		
		p = new EnemyAppend(NailShape2.getShape(),40 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(15);
		childHash["arm12"].addChild(p, "arm13", 120 ,ENGAGED);
		p = new EnemyAppend(NailShape2.getShape(),40 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(15);
		childHash["arm22"].addChild(p, "arm23", 120 ,ENGAGED);
		p = new EnemyAppend(NailShape2.getShape(),40 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(15);
		childHash["arm32"].addChild(p, "arm33", 120 ,ENGAGED);
		p = new EnemyAppend(NailShape2.getShape(),40 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(15);
		childHash["arm42"].addChild(p, "arm43", 120 ,ENGAGED);
		p = new EnemyAppend(NailShape2.getShape(),40 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(15);
		childHash["arm52"].addChild(p, "arm53", 120 ,ENGAGED);
		p = new EnemyAppend(NailShape2.getShape(),40 ,-1);
		(cast(Enemy)p).disableBorder();(cast(EnemyAppend)p).setCollision(15);
		childHash["arm62"].addChild(p, "arm63", 120 ,ENGAGED);
		
		
//		rotateAll(matRotateX(10));
	}
	
	public void move(){
		super.move();
		switch(state){
			case "start":
			if(rpos.z < -1200)pos.z += 0.4;
			else changeState("standby");
			if(nowStateCnt % 100 == 0)new AttackRing(this ,"circle",60);
			if(nowStateCnt > 200){
				switch(nowStateCnt % 360){
					case 0:new AttackRing(cast(Enemy)childHash["arm12"] ,"homing",60);break;
					case 60:new AttackRing(cast(Enemy)childHash["arm22"] ,"homing",60);break;
					case 120:new AttackRing(cast(Enemy)childHash["arm32"] ,"homing",60);break;
					case 180:new AttackRing(cast(Enemy)childHash["arm42"] ,"homing",60);break;
					case 240:new AttackRing(cast(Enemy)childHash["arm52"] ,"homing",60);break;
					case 300:new AttackRing(cast(Enemy)childHash["arm62"] ,"homing",60);break;
					
					default:break;
				}
			}
			break;
			case "standby":
			
//			else
			if(nowStateCnt >= 120){
				
				if("arm11" in childHash && childHash["arm11"].exists){
					childHash["arm11"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm21" in childHash && childHash["arm21"].exists){
					childHash["arm21"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm31" in childHash && childHash["arm31"].exists){
					childHash["arm31"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm41" in childHash && childHash["arm41"].exists){
					childHash["arm41"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm51" in childHash && childHash["arm51"].exists){
					childHash["arm51"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm61" in childHash && childHash["arm61"].exists){
					childHash["arm61"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				setNextMusic(music_kind.MUSIC8);
				changeState("tilt");
			}
			
			break;
			case "tilt":
			if(rpos.z < -1000)pos.z += 1.5;
			else{
				if(nowStateCnt >= 150){
					changeState("attack1");
				}
			}
			changeLastState();
			break;
			case "attack1":
			if(nowStateCnt < 100){
				if(nowStateCnt % 20 == 0 && nowStateCnt < 70){
					if("arm12" in childHash && childHash["arm12"].exists){
						new AttackRing(cast(Enemy)childHash["arm12"] ,"reflect" ,30);
					}
					
					if("arm22" in childHash && childHash["arm22"].exists){
						new AttackRing(cast(Enemy)childHash["arm22"] ,"reflect" ,30);
					}
					
					if("arm32" in childHash && childHash["arm32"].exists){
						new AttackRing(cast(Enemy)childHash["arm32"] ,"reflect" ,30);
					}
					
					if("arm42" in childHash && childHash["arm42"].exists){
						new AttackRing(cast(Enemy)childHash["arm42"] ,"reflect" ,30);
					}
					
					if("arm52" in childHash && childHash["arm52"].exists){
						new AttackRing(cast(Enemy)childHash["arm52"] ,"reflect" ,30);
					}
					
					if("arm62" in childHash && childHash["arm62"].exists){
						new AttackRing(cast(Enemy)childHash["arm62"] ,"reflect" ,30);
					}
				}
				
				
			}else{
				if("arm11" in childHash && childHash["arm11"].exists){
					childHash["arm11"].addAnimation(new RotateTo(150 ,BOTHY ,20 ,1.0) ,"tilt");
				}
				if("arm21" in childHash && childHash["arm21"].exists){
					childHash["arm21"].addAnimation(new RotateTo(150 ,BOTHY ,20 ,1.0) ,"tilt");
				}
				if("arm31" in childHash && childHash["arm31"].exists){
					childHash["arm31"].addAnimation(new RotateTo(150 ,BOTHY ,20 ,1.0) ,"tilt");
				}
				if("arm41" in childHash && childHash["arm41"].exists){
					childHash["arm41"].addAnimation(new RotateTo(150 ,BOTHY ,20 ,1.0) ,"tilt");
				}
				if("arm51" in childHash && childHash["arm51"].exists){
					childHash["arm51"].addAnimation(new RotateTo(150 ,BOTHY ,20 ,1.0) ,"tilt");
				}
				if("arm61" in childHash && childHash["arm61"].exists){
					childHash["arm61"].addAnimation(new RotateTo(150 ,BOTHY ,20 ,1.0) ,"tilt");
				}
				
				changeState("attack2");
				
			}
			changeLastState();
			break;
			case "attack2":
			if(nowStateCnt == 150){
				if("arm11" in childHash && childHash["arm11"].exists){
					childHash["arm11"].addAnimation(new RotateTo(90 ,BOTHY ,-45 ,1.0) ,"tilt");
				}
				if("arm21" in childHash && childHash["arm21"].exists){
					childHash["arm21"].addAnimation(new RotateTo(90 ,BOTHY ,-45 ,1.0) ,"tilt");
				}
				if("arm31" in childHash && childHash["arm31"].exists){
					childHash["arm31"].addAnimation(new RotateTo(90 ,BOTHY ,-45 ,1.0) ,"tilt");
				}
				if("arm41" in childHash && childHash["arm41"].exists){
					childHash["arm41"].addAnimation(new RotateTo(90 ,BOTHY ,-45 ,1.0) ,"tilt");
				}
				if("arm51" in childHash && childHash["arm51"].exists){
					childHash["arm51"].addAnimation(new RotateTo(90 ,BOTHY ,-45 ,1.0) ,"tilt");
				}
				if("arm61" in childHash && childHash["arm61"].exists){
					childHash["arm61"].addAnimation(new RotateTo(90 ,BOTHY ,-45 ,1.0) ,"tilt");
				}
				changeState("attack3");
			}
			changeLastState();
			break;
			case "attack3":
			if(rpos.z > -1050)pos.z -= 1.0;
			else{
				if(nowStateCnt % 60 == 0){
					if(nowStateCnt < 140){
						if("arm12" in childHash && childHash["arm12"].exists){
							new AttackRing(cast(Enemy)childHash["arm12"] ,"wave" ,30);
						}
					}else{
						if(nowStateCnt > 340 && nowStateCnt % 180 == 0){
							if("arm12" in childHash && childHash["arm12"].exists){
								new AttackRing(cast(Enemy)childHash["arm12"] ,"homing" ,60);
							}
						}
					}
					if(nowStateCnt < 390){
						if("arm22" in childHash && childHash["arm22"].exists){
							new AttackRing(cast(Enemy)childHash["arm22"] ,"wave" ,30);
						}
					}else{
						if(nowStateCnt > 590 && nowStateCnt % 180 == 60){
							if("arm22" in childHash && childHash["arm22"].exists){
								new AttackRing(cast(Enemy)childHash["arm22"] ,"homing" ,60);
							}
						}
					}
					if(nowStateCnt < 640){
						if("arm32" in childHash && childHash["arm32"].exists){
							new AttackRing(cast(Enemy)childHash["arm32"] ,"wave" ,30);
						}
					}else{
						if(nowStateCnt > 840 && nowStateCnt % 180 == 120){
							if("arm32" in childHash && childHash["arm32"].exists){
								new AttackRing(cast(Enemy)childHash["arm32"] ,"homing" ,60);
							}
						}
					}
					if(nowStateCnt < 140){	
						if("arm42" in childHash && childHash["arm42"].exists){
							new AttackRing(cast(Enemy)childHash["arm42"] ,"wave" ,30);
						}
					}else{
						if(nowStateCnt > 340 && nowStateCnt % 180 == 0){
							if("arm42" in childHash && childHash["arm42"].exists){
								new AttackRing(cast(Enemy)childHash["arm42"] ,"homing" ,60);
							}
						}
					}
					if(nowStateCnt < 390){
						if("arm52" in childHash && childHash["arm52"].exists){
							new AttackRing(cast(Enemy)childHash["arm52"] ,"wave" ,30);
						}
					}else{
						if(nowStateCnt > 540 && nowStateCnt % 180 == 60){
							if("arm52" in childHash && childHash["arm52"].exists){
								new AttackRing(cast(Enemy)childHash["arm52"] ,"homing" ,60);
							}
						}
					}
					if(nowStateCnt < 640){
						if("arm62" in childHash && childHash["arm62"].exists){
							new AttackRing(cast(Enemy)childHash["arm62"] ,"wave" ,30);
						}
					}else{
						if(nowStateCnt > 840 && nowStateCnt % 180 == 120){
							if("arm62" in childHash && childHash["arm62"].exists){
								new AttackRing(cast(Enemy)childHash["arm62"] ,"homing" ,60);
							}
						}
					}
				}
				if(nowStateCnt == 200){
					if("arm11" in childHash && childHash["arm11"].exists){
						childHash["arm11"].addAnimation(new RotateTo(200 ,BOTHY ,0 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 450){
					if("arm21" in childHash && childHash["arm21"].exists){
						childHash["arm21"].addAnimation(new RotateTo(200 ,BOTHY ,0 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 700){
					if("arm31" in childHash && childHash["arm31"].exists){
						childHash["arm31"].addAnimation(new RotateTo(200 ,BOTHY ,0 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 200){
					if("arm41" in childHash && childHash["arm41"].exists){
						childHash["arm41"].addAnimation(new RotateTo(200 ,BOTHY ,0 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 450){
					if("arm51" in childHash && childHash["arm51"].exists){
						childHash["arm51"].addAnimation(new RotateTo(200 ,BOTHY ,0 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 700){
					if("arm61" in childHash && childHash["arm61"].exists){
						childHash["arm61"].addAnimation(new RotateTo(200 ,BOTHY ,0 ,1.0) ,"tilt");
					}
				}
				
				
				if(nowStateCnt == 140){
					if("arm11" in childHash && childHash["arm11"].exists){
						childHash["arm11"].addAnimation(new RotateTo(60 ,BOTHY ,-50 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 390){
					if("arm21" in childHash && childHash["arm21"].exists){
						childHash["arm21"].addAnimation(new RotateTo(60 ,BOTHY ,-50 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 640){
					if("arm31" in childHash && childHash["arm31"].exists){
						childHash["arm31"].addAnimation(new RotateTo(60 ,BOTHY ,-50 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 140){
					if("arm41" in childHash && childHash["arm41"].exists){
						childHash["arm41"].addAnimation(new RotateTo(60 ,BOTHY ,-50 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 390){
					if("arm51" in childHash && childHash["arm51"].exists){
						childHash["arm51"].addAnimation(new RotateTo(60 ,BOTHY ,-50 ,1.0) ,"tilt");
					}
				}
				if(nowStateCnt == 640){
					if("arm61" in childHash && childHash["arm61"].exists){
						childHash["arm61"].addAnimation(new RotateTo(60 ,BOTHY ,-50 ,1.0) ,"tilt");
					}
				}
				
				if(nowStateCnt == 900){
					
					if("arm12" in childHash && childHash["arm12"].exists){
						new AttackRing(cast(Enemy)childHash["arm12"] ,"homing" ,60);
					}
					if("arm22" in childHash && childHash["arm22"].exists){
						new AttackRing(cast(Enemy)childHash["arm22"] ,"homing" ,60);
					}
					if("arm32" in childHash && childHash["arm32"].exists){
						new AttackRing(cast(Enemy)childHash["arm32"] ,"homing" ,60);
					}
					if("arm42" in childHash && childHash["arm42"].exists){
						new AttackRing(cast(Enemy)childHash["arm42"] ,"homing" ,60);
					}
					if("arm52" in childHash && childHash["arm52"].exists){
						new AttackRing(cast(Enemy)childHash["arm52"] ,"homing" ,60);
					}
					if("arm62" in childHash && childHash["arm62"].exists){
						new AttackRing(cast(Enemy)childHash["arm62"] ,"homing" ,60);
					}
				}
				if(nowStateCnt == 960){
					changeState("tilt2");
				}
				/*
					if("arm11" in childHash && childHash["arm11"].exists){
						childHash["arm11"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
					}
					
					
					if("arm21" in childHash && childHash["arm21"].exists){
						childHash["arm21"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
					}
					
					if("arm31" in childHash && childHash["arm31"].exists){
						childHash["arm31"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
					}
					if("arm41" in childHash && childHash["arm41"].exists){
						childHash["arm41"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
					}
					if("arm51" in childHash && childHash["arm51"].exists){
						childHash["arm51"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
					}
					if("arm61" in childHash && childHash["arm61"].exists){
						childHash["arm61"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
					}
					*/
//				}
			}
			changeLastState();
			break;
			case "tilt2":
			if(nowStateCnt > 0){
				if("arm11" in childHash && childHash["arm11"].exists){
					childHash["arm11"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm21" in childHash && childHash["arm21"].exists){
					childHash["arm21"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm31" in childHash && childHash["arm31"].exists){
					childHash["arm31"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm41" in childHash && childHash["arm41"].exists){
					childHash["arm41"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm51" in childHash && childHash["arm51"].exists){
					childHash["arm51"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				if("arm61" in childHash && childHash["arm61"].exists){
					childHash["arm61"].addAnimation(new RotateTo(150 ,BOTHY ,-30 ,1.0) ,"tilt");
				}
				changeState("tilt");
				
			}

			break;
			case "laststart":
			
			if(nowStateCnt > 200){
				if("arm11" in childHash && childHash["arm11"].exists){
						childHash["arm11"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm11"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm21" in childHash && childHash["arm21"].exists){
						childHash["arm21"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm21"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm31" in childHash && childHash["arm31"].exists){
						childHash["arm31"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm31"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm41" in childHash && childHash["arm41"].exists){
						childHash["arm41"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm41"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm51" in childHash && childHash["arm51"].exists){
						childHash["arm51"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm51"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm61" in childHash && childHash["arm61"].exists){
						childHash["arm61"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm61"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					changeState("laststandby1");
			}else{
				if("arm11" in childHash && childHash["arm11"].exists && childHash["arm11"].inAnimation){}
				else if("arm21" in childHash && childHash["arm21"].exists && childHash["arm21"].inAnimation){}
				else if("arm31" in childHash && childHash["arm31"].exists && childHash["arm31"].inAnimation){}
				else if("arm41" in childHash && childHash["arm41"].exists && childHash["arm41"].inAnimation){}
				else if("arm51" in childHash && childHash["arm51"].exists && childHash["arm51"].inAnimation){}
				else if("arm61" in childHash && childHash["arm61"].exists && childHash["arm61"].inAnimation){}
				else{
					if("arm11" in childHash && childHash["arm11"].exists){
						childHash["arm11"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm11"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm21" in childHash && childHash["arm21"].exists){
						childHash["arm21"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm21"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm31" in childHash && childHash["arm31"].exists){
						childHash["arm31"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm31"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm41" in childHash && childHash["arm41"].exists){
						childHash["arm41"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm41"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm51" in childHash && childHash["arm51"].exists){
						childHash["arm51"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm51"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					if("arm61" in childHash && childHash["arm61"].exists){
						childHash["arm61"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
						childHash["arm61"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
					}
					changeState("laststandby1");
				}
			}
			
			break;
			case "laststandby1":
			if(rpos.z > -1200)pos.z -= 1.5;
			if(nowStateCnt == 150)changeState("lastattack1");
			break;
			case "lastattack1":
			if(nowStateCnt % 10 == 0){
				new AttackRing(this ,"blaster",90);
			}
			if(nowStateCnt == 300){
				changeState("laststandby2");
			}
			break;
			case "laststandby2":
			if(nowStateCnt == 100){
//				Log_write("a");
				/*
				if("arm11" in childHash && childHash["arm11"].exists){
					childHash["arm11"].addAnimation(new RotateTo(150 ,POSEY ,0) ,"wall");
				}
				if("arm21" in childHash && childHash["arm21"].exists){
					childHash["arm21"].addAnimation(new RotateTo(150 ,POSEY ,0) ,"wall");
				}
				if("arm31" in childHash && childHash["arm31"].exists){
					
					childHash["arm31"].addAnimation(new RotateTo(150 ,POSEY ,0) ,"wall");
				}
				if("arm41" in childHash && childHash["arm41"].exists){
					
					childHash["arm41"].addAnimation(new RotateTo(150 ,POSEY ,0) ,"wall");
				}
				if("arm51" in childHash && childHash["arm51"].exists){
					
					childHash["arm51"].addAnimation(new RotateTo(150 ,POSEY ,0) ,"wall");
				}
				if("arm61" in childHash && childHash["arm61"].exists){
					
					childHash["arm61"].addAnimation(new RotateTo(150 ,POSEY ,0) ,"wall");
				}
				*/
			}
			/*
			if(nowStateCnt > 100){
				if("arm11" in childHash && childHash["arm11"].exists){
					if(childHash["arm11"].dist < 1000)childHash["arm11"].dist += 5.0;
				}
				if("arm21" in childHash && childHash["arm21"].exists){
					if(childHash["arm21"].dist < 1000)childHash["arm21"].dist += 5.0;
				}
				if("arm31" in childHash && childHash["arm31"].exists){
					if(childHash["arm31"].dist < 1000)childHash["arm31"].dist += 5.0;
				}
				if("arm41" in childHash && childHash["arm41"].exists){
					if(childHash["arm41"].dist < 1000)childHash["arm41"].dist += 5.0;
				}
				if("arm51" in childHash && childHash["arm51"].exists){
					if(childHash["arm51"].dist < 1000)childHash["arm51"].dist += 5.0;
				}
				if("arm61" in childHash && childHash["arm61"].exists){
					if(childHash["arm61"].dist < 1000)childHash["arm61"].dist += 5.0;
				}
					
			}
			*/
			if(nowStateCnt == 100){
				addAnimation(new RotateTo(150 ,POSEY ,60) ,"pose");
				for(int i=0;i<6;i++){
					if(i%2 == 0)speed[i] = -1.5;
					else speed[i] = -3.0;
				}
				if("arm11" in childHash && childHash["arm11"].exists){
					childHash["arm11"].addAnimation(new RotateTo(150 ,POSEY ,-60) ,"wall");
				}
				if("arm21" in childHash && childHash["arm21"].exists){
					childHash["arm21"].addAnimation(new RotateTo(150 ,POSEY ,-60) ,"wall");
				}
				if("arm31" in childHash && childHash["arm31"].exists){
					
					childHash["arm31"].addAnimation(new RotateTo(150 ,POSEY ,-60) ,"wall");
				}
				if("arm41" in childHash && childHash["arm41"].exists){
					
					childHash["arm41"].addAnimation(new RotateTo(150 ,POSEY ,-60) ,"wall");
				}
				if("arm51" in childHash && childHash["arm51"].exists){
					
					childHash["arm51"].addAnimation(new RotateTo(150 ,POSEY ,-60) ,"wall");
				}
				if("arm61" in childHash && childHash["arm61"].exists){
					
					childHash["arm61"].addAnimation(new RotateTo(150 ,POSEY ,-60) ,"wall");
				}
				changeState("laststandby3");
			}
			break;
			case "laststandby3":
			
			if("arm11" in childHash && childHash["arm11"].exists){
				if(childHash["arm11"].dist < 500)childHash["arm11"].dist += 5.0;
			}else childHash["arm11"].dist = 500;
			if("arm21" in childHash && childHash["arm21"].exists){
				if(childHash["arm21"].dist < 500)childHash["arm21"].dist += 5.0;
			}else childHash["arm21"].dist = 500;
			if("arm31" in childHash && childHash["arm31"].exists){
				if(childHash["arm31"].dist < 500)childHash["arm31"].dist += 5.0;
			}else childHash["arm31"].dist = 500;
			if("arm41" in childHash && childHash["arm41"].exists){
				if(childHash["arm41"].dist < 500)childHash["arm41"].dist += 5.0;
			}else childHash["arm41"].dist = 500;
			if("arm51" in childHash && childHash["arm51"].exists){
				if(childHash["arm51"].dist < 500)childHash["arm51"].dist += 5.0;
			}else childHash["arm51"].dist = 500;
			if("arm61" in childHash && childHash["arm61"].exists){
				if(childHash["arm61"].dist < 500)childHash["arm61"].dist += 5.0;
			}else childHash["arm61"].dist = 500;
			if(rpos.z < -800)pos.z += 1.0;
			else if(nowStateCnt > 200){
				changeState("lastattack2");
			}
//			moveWall();
			
			
			
			break;
			
			case "lastattack2":
			if(nowStateCnt % 60 == 0 && nowStateCnt <= 540)new AttackRing(this ,"bring" ,60);
//			if(nowStateCnt % 240 == 40)new AttackRing(this ,"ering" ,60);
			moveWall();
			if(nowStateCnt == 600){
				if("arm11" in childHash && childHash["arm11"].exists){
					childHash["arm11"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
					childHash["arm11"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
				}
				if("arm21" in childHash && childHash["arm21"].exists){
					childHash["arm21"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
					childHash["arm21"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
				}
				if("arm31" in childHash && childHash["arm31"].exists){
					childHash["arm31"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
					childHash["arm31"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
				}
				if("arm41" in childHash && childHash["arm41"].exists){
					childHash["arm41"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
					childHash["arm41"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
				}
				if("arm51" in childHash && childHash["arm51"].exists){
					childHash["arm51"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
					childHash["arm51"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
				}
				if("arm61" in childHash && childHash["arm61"].exists){
					childHash["arm61"].addAnimation(new RotateTo(150 ,LINKY ,0) ,"turret1");
					childHash["arm61"].addAnimation(new RotateTo(150 ,POSEY ,90) ,"turret2");
				}
				addAnimation(new RotateTo(150 ,POSEY ,0) ,"pose");
				changeState("laststandby4");
			}
			break;
			case "laststandby4":
			if(rpos.z > -900)pos.z -= 1.5;
			else{
				changeState("laststandby5");
			}
			break;
			case "laststandby5":
			if(rpos.z > -1200)pos.z -= 1.5;
			else if(nowStateCnt > 230)changeState("lastattack1");
			
			if("arm11" in childHash && childHash["arm11"].exists){
				if(childHash["arm11"].dist < 150 - 2.0)childHash["arm11"].dist +=2.0;
				else if(150 + 2.0<childHash["arm11"].dist)childHash["arm11"].dist -=2.0;
			}
			if("arm21" in childHash && childHash["arm21"].exists){
				if(childHash["arm21"].dist < 150 - 2.0)childHash["arm21"].dist +=2.0;
				else if(150 + 2.0<childHash["arm21"].dist)childHash["arm21"].dist -=2.0;
			}
			if("arm31" in childHash && childHash["arm31"].exists){
				if(childHash["arm31"].dist < 150 - 2.0)childHash["arm31"].dist +=2.0;
				else if(150 + 2.0<childHash["arm31"].dist)childHash["arm31"].dist -=2.0;
			}
			if("arm41" in childHash && childHash["arm41"].exists){
				if(childHash["arm41"].dist < 150 - 2.0)childHash["arm41"].dist +=2.0;
				else if(150 + 2.0<childHash["arm41"].dist)childHash["arm41"].dist -=2.0;
			}
			if("arm51" in childHash && childHash["arm51"].exists){
				if(childHash["arm51"].dist < 150 - 2.0)childHash["arm51"].dist +=2.0;
				else if(150 + 2.0<childHash["arm51"].dist)childHash["arm51"].dist -=2.0;
			}
			if("arm61" in childHash && childHash["arm61"].exists){
				if(childHash["arm61"].dist < 150 - 2.0)childHash["arm61"].dist +=2.0;
				else if(150 + 2.0<childHash["arm61"].dist)childHash["arm61"].dist -=2.0;
			}
			
			default:break;
		}
		rotateAll(matRotateZ(0.5));
		
	}
	private void moveWall(){
		if("arm11" in childHash && childHash["arm11"].exists){
			childHash["arm11"].dist += speed[0];
			if(childHash["arm11"].dist < 100){
				dist = 50.0;
				speed[0] = 2.0;//rand.nextFloat(1.5) + 0.5;
			}
			if(500 < childHash["arm11"].dist){
				dist = 500.0;
				speed[0] = -2.0;//(rand.nextFloat(1.5) + 0.5);
				
			}
		}
		if("arm21" in childHash && childHash["arm21"].exists){
			childHash["arm21"].dist += speed[1];
			if(childHash["arm21"].dist < 100){
				dist = 50.0;
				speed[1] = 2.0;//rand.nextFloat(1.5) + 0.5;
			}
			if(500 < childHash["arm21"].dist){
				dist = 500.0;
				speed[1] = -2.0;//(rand.nextFloat(1.5) + 0.5);
				
			}
		}
		if("arm31" in childHash && childHash["arm31"].exists){
			childHash["arm31"].dist += speed[2];
			if(childHash["arm31"].dist < 100){
				dist = 50.0;
				speed[2] = 2.0;//rand.nextFloat(1.5) + 0.5;
			}
			if(500 < childHash["arm31"].dist){
				dist = 500.0;
				speed[2] = -2.0;//(rand.nextFloat(1.5) + 0.5);
				
			}
		}
		if("arm41" in childHash && childHash["arm41"].exists){
			childHash["arm41"].dist += speed[3];
			if(childHash["arm41"].dist < 100){
				dist = 50.0;
				speed[3] = 2.0;//rand.nextFloat(1.5) + 0.5;
			}
			if(500 < childHash["arm41"].dist){
				dist = 500.0;
				speed[3] = -2.0;//(rand.nextFloat(1.5) + 0.5);
				
			}
		}
		if("arm51" in childHash && childHash["arm51"].exists){
			childHash["arm51"].dist += speed[4];
			if(childHash["arm51"].dist < 100){
				dist = 50.0;
				speed[4] = 2.0;//rand.nextFloat(1.5) + 0.5;
			}
			if(500 < childHash["arm51"].dist){
				dist = 500.0;
				speed[4] = -2.0;//(rand.nextFloat(1.5) + 0.5);
				
			}
		}
		if("arm61" in childHash && childHash["arm61"].exists){
			childHash["arm61"].dist += speed[5];
			if(childHash["arm61"].dist < 100){
				dist = 50.0;
				speed[5] = 2.0;//rand.nextFloat(1.5) + 0.5;
			}
			if(500 < childHash["arm61"].dist){
				dist = 500.0;
				speed[5] = -2.0;//(rand.nextFloat(1.5) + 0.5);
				
			}
		}
	}
	
	private void changeLastState(){
		bool child = false;
		if("arm12" in childHash && childHash["arm12"].exists)child = true;
		
		if("arm22" in childHash && childHash["arm22"].exists)child = true;
		
		if("arm32" in childHash && childHash["arm32"].exists)child = true;
		
		if("arm42" in childHash && childHash["arm42"].exists)child = true;
		
		if("arm52" in childHash && childHash["arm52"].exists)child = true;
		
		if("arm62" in childHash && childHash["arm62"].exists)child = true;
		if(!child){
			changeState("laststart");
		}
}
	public void reportRing(Ring ring){
		switch(ring.name){
			case "circle":
			double dx = 0,dy = 0;
//			dx = rand.nextFloat(0.3)-0.15;
//			dy = rand.nextFloat(0.3)-0.15;
			for(double theta=-PI;theta<PI;theta+=PI/16){
				new Bullet3D2(rpos ,true ,new Vector3((cos(theta)*0.2+dx)*5.0 ,(sin(theta)*0.2+dy)*5.0,2.0f));
			}
			break;
			case "blaster":
			Vector3 vel = vec3Normalize(ship.rpos - rpos);
			new Blaster(rpos ,vel ,10.0f);
			break;
			case "bring":
			for(double theta=-PI;theta<PI;theta+=PI/16){
				new StraightBullet(rpos ,true ,theta ,2.0);
			}
			break;
			case "ering":
			for(double theta=-PI;theta<PI;theta+=PI/16){
				new Enemy1(rpos ,theta ,2.0);
			}
			break;
			default:break;
		}
	}
}

public class Boss8imitate:Boss8{
	public this(double x,double y,double z,double aim){
		super(x ,y ,z ,aim);
		rotateAll(matRotateY(aim));
	}
	public void move(){
		rotateAll(matRotateZ(0.5));
	}
}

/*
public class Boss7:Boss{
	
	//import br.mainloop;
	private{
		double aim;
		static Shape baseShape;
		
	static float[] sz =
	[-1.0 ,-0.7 ,0.7 ,1.0];
	static float[] scale = 
	[0.7  ,1.0  ,1.0 ,0.7];

	}
	int[6] reload;
	bool right;
	public this(double x,double y,double z,double aim){
		super(18);
		Matrix po =  matRotateX(0);
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;
		//super(pos ,po);
		//set(pos ,p);
		//setPoseBase(p);
		size =  50;
		collisionRange = 25;

		
		if(baseShape is null){
			float[8] a,b;
			int i=0;
			for(double rad=-PI;rad<PI;rad+=PI*2.0/cast(float)a.length){
				a[i]=cos(rad);
				b[i]=sin(rad);
				i++;
			}
			baseShape = new SH_Pot(a ,b ,sz ,scale);
		}
   		 shape = cast(Shape)baseShape.clone();
		Parts p;//Parts p;
	
	}
	public void move(){
		super.move();
		switch(state){
			case "start":changeState("recovery1");break;
			case "rotateStart1":
			
			addAnimation(new Rotate(360 ,POSEZ ,1.0) ,"rotate");
			
			if("t1" in childHash && childHash["t1"].exists){
				childHash["t1"].addAnimation(new Rotate(360 ,BOTHZ ,1) ,"rotate");
				childHash["t1"].addAnimation(new Rotate(360 ,POSEZ ,1) ,"rotate2");
				childHash["t1"].addAnimation(new ExtendTo(180 ,100) ,"extend");
			}
			if("t2" in childHash && childHash["t2"].exists){
				childHash["t2"].addAnimation(new Rotate(360 ,BOTHZ ,1) ,"rotate");
				childHash["t2"].addAnimation(new Rotate(360 ,POSEZ ,1) ,"rotate2");
				childHash["t2"].addAnimation(new ExtendTo(180 ,100) ,"extend");
			}
			if("t3" in childHash && childHash["t3"].exists){
				childHash["t3"].addAnimation(new Rotate(360 ,BOTHZ ,1) ,"rotate");
				childHash["t3"].addAnimation(new Rotate(360 ,POSEZ ,1) ,"rotate2");
				childHash["t3"].addAnimation(new ExtendTo(180 ,100) ,"extend");
			}
			if("t4" in childHash && childHash["t4"].exists){
				childHash["t4"].addAnimation(new Rotate(360 ,BOTHZ ,1) ,"rotate");
				childHash["t4"].addAnimation(new Rotate(360 ,POSEZ ,1) ,"rotate2");
				childHash["t4"].addAnimation(new ExtendTo(180 ,100) ,"extend");
			}
			if("t5" in childHash && childHash["t5"].exists){
				childHash["t5"].addAnimation(new Rotate(360 ,BOTHZ ,1) ,"rotate");
				childHash["t5"].addAnimation(new Rotate(360 ,POSEZ ,1) ,"rotate2");
				childHash["t5"].addAnimation(new ExtendTo(180 ,100) ,"extend");
			}
			if("t6" in childHash && childHash["t6"].exists){
				childHash["t6"].addAnimation(new Rotate(360 ,BOTHZ ,1) ,"rotate");
				childHash["t6"].addAnimation(new Rotate(360 ,POSEZ ,1) ,"rotate2");
				childHash["t6"].addAnimation(new ExtendTo(180 ,100) ,"extend");
			}
			
			changeState("rotate1");
			break;
			case "rotate1":
			if(nowStateCnt % 5 == 0 && nowStateCnt < 360 - 30){
				if("t1" in childHash && childHash["t1"].exists){
					new AttackRing(cast(Enemy)childHash["t1"] ,"shot" ,30);
				}
				if("t2" in childHash && childHash["t2"].exists){
					new AttackRing(cast(Enemy)childHash["t2"] ,"shot" ,30);
				}
				if("t3" in childHash && childHash["t3"].exists){
					new AttackRing(cast(Enemy)childHash["t3"] ,"shot" ,30);
				}
				if("t4" in childHash && childHash["t4"].exists){
					new AttackRing(cast(Enemy)childHash["t4"] ,"shot" ,30);
				}
				if("t5" in childHash && childHash["t5"].exists){
					new AttackRing(cast(Enemy)childHash["t5"] ,"shot" ,30);
				}
				if("t6" in childHash && childHash["t6"].exists){
					new AttackRing(cast(Enemy)childHash["t6"] ,"shot" ,30);
				}
			}
			if(180 == nowStateCnt){
				if("t1" in childHash && childHash["t1"].exists){
					childHash["t1"].addAnimation(new ExtendTo(180 ,200) ,"extend");
				}
				if("t2" in childHash && childHash["t2"].exists){
					childHash["t2"].addAnimation(new ExtendTo(180 ,200) ,"extend");
				}
				if("t3" in childHash && childHash["t3"].exists){
				
					childHash["t3"].addAnimation(new ExtendTo(180 ,200) ,"extend");
				}
				if("t4" in childHash && childHash["t4"].exists){
					
					childHash["t4"].addAnimation(new ExtendTo(180 ,200) ,"extend");
				}
				if("t5" in childHash && childHash["t5"].exists){
				
					childHash["t5"].addAnimation(new ExtendTo(180 ,200) ,"extend");
				}
				if("t6" in childHash && childHash["t6"].exists){
					
					childHash["t6"].addAnimation(new ExtendTo(180 ,200) ,"extend");
				}
			}
			if(360 < nowStateCnt)changeState("recovery");
			break;
			case "recovery1":
			if(60 < nowStateCnt)changeState("rotateStart1");
			if(0 == nowStateCnt){
//				Log_write(cast(int)rposeZ);
				Parts p;
				if(!("t1" in childHash) || !childHash["t1"].exists){
					double aim = rposeZ+150;
					new ERing(this ,rpos + new Vector3(200.0* cos(aim*PI/180.0) ,200.0* sin(aim*PI/180.0) ,0) ,aim ,"t1" ,60);
					
				}
				if(!("t2" in childHash) || !childHash["t2"].exists){
					double aim = rposeZ+90;
					new ERing(this ,rpos + new Vector3(200.0* cos(aim*PI/180.0) ,200.0* sin(aim*PI/180.0) ,0) ,aim ,"t2" ,60);
				
				}
				if(!("t3" in childHash) || !childHash["t3"].exists){
					double aim = rposeZ+30;
					new ERing(this ,rpos + new Vector3(200.0* cos(aim*PI/180.0) ,200.0* sin(aim*PI/180.0) ,0) ,aim ,"t3" ,60);
					
				}
				if(!("t4" in childHash) || !childHash["t4"].exists){
					double aim = rposeZ-30;
					new ERing(this ,rpos + new Vector3(200.0* cos(aim*PI/180.0) ,200.0* sin(aim*PI/180.0) ,0) ,aim ,"t4" ,60);
					
				}
				if(!("t5" in childHash) || !childHash["t5"].exists){
					double aim = rposeZ-90;
					new ERing(this ,rpos + new Vector3(200.0* cos(aim*PI/180.0) ,200.0* sin(aim*PI/180.0) ,0) ,aim ,"t5" ,60);
				
				}
				if(!("t6" in childHash) || !childHash["t6"].exists){
					double aim = rposeZ-150;
					new ERing(this ,rpos + new Vector3(200.0* cos(aim*PI/180.0) ,200.0* sin(aim*PI/180.0) ,0) ,aim ,"t6" ,60);
				
				}
			}
			break;
			
			
			default:break;
		}
		if(120 < cnt){
			if(cnt % 200 == 0){
				new AttackRing(this ,"all1" ,60 );
			}
			if(cnt % 200 == 30){
				new AttackRing(this ,"all2" ,60 );
			}
		}
	}
	public void reportRing(Ring ring){
		switch(ring.name){
			case "all1":
			for(double r=-PI;r<PI;r+=PI/32.0){
				new StraightBullet(rpos ,true ,r ,2.0);
			}
			break;
			case "all2":
			for(double r=-PI;r<PI;r+=PI/32.0){
				new AccBullet(rpos ,true ,r ,0.0 ,4.0 ,0.05);
			}
			break;
			case "t1":case "t2":case "t3":case "t4":case "t5":case "t6":
			Parts p = new Turret3(40);
			(cast(Enemy)p).disableBorder();
			addChild(p, ring.name, 200 ,NORMAL ,new Matrix());p.linkZ = (cast(ERing)ring).aim;p.poseZ = (cast(ERing)ring).aim ;
			break;
			default:break;
		}
	}
	
}
*/
public class ERing:Ring{
//	public Vector3 pos;
	public double aim;
	
	public this(Caller caller ,Vector3 pos ,double aim ,char[] name ,int span ,double R=0.4 ,double G=0.6,double B=2.0,double alpha=1.0 ,double deg = 0.0){
		super(caller,pos,name,span,R,G,B,alpha ,deg);
//		this.pos = cast(Vector3)pos.clone();
		this.aim = aim;
	}
}
public class Bird:Boss{
	
	//import br.mainloop;
	private{
		double aim;
		static Shape baseShape;
		static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
 
  	];
	}
	
	public this(double x,double y,double z,double aim){
		super(10);
		Matrix po =  matRotate(-90 ,0 ,0 ,1) * matRotate(45 ,1 ,0 ,0);
		pos = new Vector3(x ,y ,z);
		this.rpos = cast(Vector3)this.pos.clone();
		setPoseBase(po);
		this.aim = aim;
		//super(pos ,po);
		//set(pos ,p);
		//setPoseBase(p);
		size =  30;
		collisionRange = 10;
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
		}
    shape = cast(Shape)baseShape.clone();
		Parts p;//Parts p;
		
		//wing
		p = new Append(BaseOfWing.getShape() ,45);//new BaseOfWing();
		
		//partsManager.add(wing1);
		addChild(p, "rWingBase", 60 ,NORMAL ,matRotateX(90) * matRotateX(-20));
		
		p = new Append(BaseOfWing.getShape() ,30);//p = new BaseOfWing();
		//partsManager.add(wing2);
		addChild(p, "lWingBase",60 ,NORMAL ,matRotateX(90) * matRotateZ(180)* matRotateX(- 20) );
		
		p = new Append(Tail.getShape() ,30);//p = new Tail();
		addChild(p, "tail_0", 60 ,ENGAGED ,matRotateX(90) * matRotateY(0) * matRotateZ(-90));
		p = new Append(Head.getShape() ,45);//p = new Head();
		addChild(p, "head" ,60 ,NORMAL ,matRotateX(90) * matRotateZ(90) ,matRotateZ(-30) * matRotateY(90));
		
		
		for(int i = 0;i < 5;i ++){
			char[] rw0 = "rWing_"~str.toString(i)~"_"~str.toString(0);
			char[] rw1 = "rWing_"~str.toString(i)~"_"~str.toString(1);
			char[] rw2 = "rWing_"~str.toString(i)~"_"~str.toString(2);
			char[] lw0 = "lWing_"~str.toString(i)~"_"~str.toString(0);
			char[] lw1 = "lWing_"~str.toString(i)~"_"~str.toString(1);
			char[] lw2 = "lWing_"~str.toString(i)~"_"~str.toString(2);
			p = new Append(Wing.getShape() ,30);//p = new Wing();
			//partsManager.add(append);
			childHash["rWingBase"].addChild(p ,rw0 ,60 ,ENGAGED ,matRotateX(90) * matRotateZ(30 * (i - 2)) * matRotateX(-20) );
			p = new Append(Wing.getShape() ,30);//p = new Wing();
			childHash[rw0].addChild(p ,rw1 ,60 , ENGAGED);//matRotateX(PI / 2.0) * matRotateZ(PI * (i - 2) / 6));
			p = new Append(Wing.getShape() ,30);//p = new Wing();
			//partsManager.add(append3);
			childHash[rw1].addChild(p ,rw2 ,60 , ENGAGED);
			p = new Append(Wing.getShape() ,30);//p = new Wing();
			//partsManager.add(append);
			childHash["lWingBase"].addChild(p ,lw0 ,60 ,ENGAGED ,matRotateX(90) * matRotateZ(180 - 30 * (i - 2.0)) * matRotateX(-20)) ;
			p = new Append(Wing.getShape() ,30);//p = new Wing();
			//partsManager.add(append2);
			childHash[lw0].addChild(p ,lw1 ,60 , ENGAGED);//matRotateX(PI / 2.0) * matRotateZ(PI * (1.0 + ((i - 2.0) / 6.0))));
			p = new Append(Wing.getShape() ,30);//p = new Wing();
			//partsManager.add(append3);
			childHash[lw1].addChild(p ,lw2 ,60 , ENGAGED);
		}
		
		
		for(int i = 1;i < 5;i ++){
			char[] t1 = "tail_"~str.toString(i-1);
			char[] t2 = "tail_"~str.toString(i);
			p = new Append(Tail.getShape() ,30);//p = new Tail();
			childHash[t1].addChild(p ,t2 ,60 ,ENGAGED);
			//append2 = append;
		}
		
		changeScale(1.0 ,true);
		rotateAll(matRotateY(90 ) );
		
		childHash["tail_0"].addAnimation(new Swing(200 ,BOTHZ ,-0.4 ,0.8 ,20 ,true) ,"swing");
		childHash["lWingBase"].addAnimation(new Swing(120 ,BOTHZ ,-0.7 ,0.9 ,20 ,true) ,"swing");
		childHash["rWingBase"].addAnimation(new Swing(120 ,BOTHZ ,-0.7 ,0.9 ,20 ,true) ,"swing");
		childHash["head"].addAnimation(new RotateTo(120 ,POSEZ ,-30 ,0.0 ) ,"nod");
	}
	public void move(){
		super.move();
		
		/*
		if(cnt > 200){
			Animation swing = childHash["tail_0"].animes["swing"];
			if(swing !is null && swing.count % swing.span == 0){
				swing.vanish();
				childHash["tail_0"].addAnimation(new Swing(200 ,BOTHZ ,-0.6 ,0.9 ,20 ,true) ,"swing");
			}
		}
		*/
	}
	
}
