module br.boss;

private import util.parts;
private import util.particle;
private import util.collision;
private import util.animationImpl;
private import br.shapeImpl;
private import br.screen;
private import br.mainloop;
private import br.gamemanager;
private import br.bullet;
private import br.enemy;
private import br.wall;
private import br.sound;
private import br.ship;
private import br.particleImpl;

public class Boss:Enemy{
	char[] state;
	int sCnt;
	public this(int hp,Vector3 pos){
		super(hp ,pos);
		border = false;
		changeState("start");
	}
	public void changeState(char[] state){
		this.state = state.dup;
		sCnt = 0;
	}
	public void move(){
		super.move();
		sCnt ++;
	}
	public void destroyImpl(){
//		super.destroy();
		makeParticle(shape, size ,WIRE | POLYGON ,rpos ,new Vector3() ,rpose ,R ,G ,B ,R/2.0,G/2.0,B/2.0,alpha ,5.0f);
		makeParticle(shape, size ,WIRE | POLYGON ,rpos ,new Vector3() ,rpose ,R ,G ,B ,R/2.0,G/2.0,B/2.0,alpha ,10.0f);
		makeParticle(shape, size ,WIRE | POLYGON ,rpos ,new Vector3() ,rpose ,R ,G ,B ,R/2.0,G/2.0,B/2.0,alpha ,20.0f);

	}
}

public class Boss2:Boss{
	private:
	bool reload;
	int num;
	public this(Vector3 pos ,Vector3 vel){
		super(700 ,new Vector3(pos.x ,pos.y ,-1200));
		
		shape = OctaShape.getShape(1.6f ,1.6f);
		size = 30.0f;
		collisionRange = size / 2.0f;
		R = 1.0f;G = 0.6f;B = 0.8f;alpha = 1.0f;
		poseZ = 90;
		
		Parts p1 ,p2,p3;
		p3 = new RootAppend(Octahedron.getShape(),0 , -1,0.7f,0.8f,1.0f ,alpha);
		addChild(p3, "r1", 40 ,ENGAGED);
		p1 = new RootAppend(Octahedron.getShape(),20 , -1,0.7f,0.8f,1.0f ,alpha);
		p3.addChild(p1, "ra1", 0 ,ENGAGED);
		p2 = new EnemyAppend(OctaShape.getShape(1.0f ,6.0f),15 , -1,0.8f,0.9f,1.0f ,alpha);
		p1.addChild(p2, "fa1", 40 ,ENGAGED ,matRotateZ(0));
		p2 = new EnemyAppend(OctaShape.getShape(1.0f ,6.0f),15 , -1,0.8f,0.9f,1.0f ,alpha);
		p1.addChild(p2, "fb1", 40 ,ENGAGED ,matRotateZ(0));
		
		p3 = new RootAppend(Octahedron.getShape(),0 , -1,0.7f,0.8f,1.0f ,alpha);
		addChild(p3, "r2", 40 ,ENGAGED);
		p1 = new RootAppend(Octahedron.getShape(),20 , -1,0.7f,0.8f,1.0f ,alpha);
		p3.addChild(p1, "ra2", 0 ,ENGAGED);
		p2 = new EnemyAppend(OctaShape.getShape(1.0f ,6.0f),15 , -1,0.8f,0.9f,1.0f ,alpha);
		p1.addChild(p2, "fa2", 40 ,ENGAGED ,matRotateZ(0));
		p2 = new EnemyAppend(OctaShape.getShape(1.0f ,6.0f),15 , -1,0.8f,0.9f,1.0f,alpha);
		p1.addChild(p2, "fb2", 40 ,ENGAGED ,matRotateY(0));
		
		p3 = new RootAppend(Octahedron.getShape(),0 , -1,0.7f,0.8f,1.0f ,alpha);
		addChild(p3, "r3", 40 ,ENGAGED);
		p1 = new RootAppend(Octahedron.getShape(),20 , -1,0.7f,0.8f,1.0f ,alpha);
		p3.addChild(p1, "ra3", 0 ,ENGAGED);
		p2 = new EnemyAppend(OctaShape.getShape(1.0f ,6.0f),15 , -1,0.8f,0.9f,1.0f ,alpha);
		p1.addChild(p2, "fa3", 40 ,ENGAGED ,matRotateZ(0));
		p2 = new EnemyAppend(OctaShape.getShape(1.0f ,6.0f),15 , -1,0.8f,0.9f,1.0f,alpha);
		p1.addChild(p2, "fb3", 40 ,ENGAGED ,matRotateZ(0));
		
		p3 = new RootAppend(Octahedron.getShape(),0 , -1,0.7f,0.8f,1.0f ,alpha);
		addChild(p3, "r4", 40 ,ENGAGED);
		p1 = new RootAppend(Octahedron.getShape(),20 , -1,0.7f,0.8f,1.0f ,alpha);
		p3.addChild(p1, "ra4", 0 ,ENGAGED);
		p2 = new EnemyAppend(OctaShape.getShape(1.0f ,6.0f),15 , -1,0.8f,0.9f,1.0f ,alpha);
		p1.addChild(p2, "fa4", 40 ,ENGAGED ,matRotateZ(0));
		p2 = new EnemyAppend(OctaShape.getShape(1.0f ,6.0f),15 , -1,0.8f,0.9f,1.0f ,alpha);
		p1.addChild(p2, "fb4", 40 ,ENGAGED ,matRotateZ(0));
		
		childHash["r1"].linkY =0;
		childHash["r2"].linkY = 90;
		childHash["r3"].linkY = 180;
		childHash["r4"].linkY =  -90.0;
		childHash["fa1"].linkZ =childHash["fa2"].linkZ = childHash["fa3"].linkZ = childHash["fa4"].linkZ =  90.0;
		childHash["fb1"].linkZ =childHash["fb2"].linkZ = childHash["fb3"].linkZ = childHash["fb4"].linkZ = -60.0;
		
		addAnimation(new Rotate(360 ,LINKY ,mulsp(1) ,0.0 ,-1) ,"roll");
//		hp = 1000;

		reload = false;
		num = 0;
		
	}
	public void move(){
		super.move();
		
		switch(state){
			case "start":
			if(rpos.y < 160.0f)pos.y += mulsp(8.0f);
			else pos.y = 160.0f;
			double rad = cast(double)sCnt / divsp(60.0) * PI;
			pos.x = sin(rad)*200.0f;
			pos.z = -1000 - cos(rad)*200.0f;
			if(sCnt == divsp(60))changeState("a");
			break;
			case "a":
			if(sCnt == 1){
				childHash["r1"].addAnimation(new MoveDist(30 ,40),"pose");
				childHash["r2"].addAnimation(new MoveDist(30 ,40),"pose");
				childHash["r3"].addAnimation(new MoveDist(30 ,40),"pose");
				childHash["r4"].addAnimation(new MoveDist(30 ,40),"pose");
				childHash["ra1"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra2"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra3"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra4"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["fa1"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose");
				childHash["fa2"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose");
				childHash["fa3"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose");
				childHash["fa4"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose");
				childHash["fb1"].addAnimation(new Move(30 ,LINK ,0,0,-60),"pose");
				childHash["fb2"].addAnimation(new Move(30 ,LINK ,0,0,-60),"pose");
				childHash["fb3"].addAnimation(new Move(30 ,LINK ,0,0,-60),"pose");
				childHash["fb4"].addAnimation(new Move(30 ,LINK ,0,0,-60),"pose");
			}
			
			
			if(sCnt == divsp(31))changeState("a1");
			break;
			case "a1":
//			pos.x = sin(cast(double)(sCnt%300)/150.0*PI)*120.0f;
			if(sCnt  % 120 == 0){
//				double rad = (-90.0 + (25.0 + rand.nextFloat(25.0))*(1.0f-cast(float)((cnt/90)%2)*2.0f))*PI/180.0f;
				attack("r");
//				p = new ReflectBullet(rpos+v*5.0f ,v);
//				p = new ReflectBullet(rpos+v*10.0f ,v);
				
				
//				p1.addChild(p2, "2", 40 ,FOLLOW);
				
			}
			if(sCnt % divsp(30) == 0){
				attack("a");
			}
			if(sCnt % divsp(30) == divsp(15)){
				attack("b");
			}
			if(sCnt == divsp(450)){
				changeState("b");
				/*
				int next = rand.nextInt(3);
				switch(next){
					case 0:
					changeState("b");
					break;
					case 1:
					changeState("c");
					break;
					case 2:
					changeState("f");
					break;
					default:
					changeState("b");
					break;
				}
				*/
			}
			break;
			case "b":
			if(sCnt == 1){
				childHash["r1"].addAnimation(new MoveDist(30 ,50),"pose");
				childHash["r2"].addAnimation(new MoveDist(30 ,50),"pose");
				childHash["r3"].addAnimation(new MoveDist(30 ,50),"pose");
				childHash["r4"].addAnimation(new MoveDist(30 ,50),"pose");
				childHash["ra1"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra2"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra3"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra4"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["fa1"].addAnimation(new Move(30 ,LINK ,0,0,110),"pose");
				childHash["fa2"].addAnimation(new Move(30 ,LINK ,0,0,110),"pose");
				childHash["fa3"].addAnimation(new Move(30 ,LINK ,0,0,110),"pose");
				childHash["fa4"].addAnimation(new Move(30 ,LINK ,0,0,110),"pose");
				childHash["fb1"].addAnimation(new Move(30 ,LINK ,0,0,-110),"pose");
				childHash["fb2"].addAnimation(new Move(30 ,LINK ,0,0,-110),"pose");
				childHash["fb3"].addAnimation(new Move(30 ,LINK ,0,0,-110),"pose");
				childHash["fb4"].addAnimation(new Move(30 ,LINK ,0,0,-110),"pose");
			}
			if(sCnt >= divsp(61))pos.x = sin(cast(double)(sCnt%divsp(240))/divsp(120.0)*PI-PI/2.0)*120.0f;
			if((sCnt+divsp(61))  % divsp(240) == 0)attack("c");
			else if((sCnt+divsp(61))  % divsp(240) == divsp(120))attack("d");
			
			if(sCnt >= divsp(60) && sCnt%divsp(15) == 0){
				attack("e");
			}
			if(sCnt == divsp(540)){
				
				changeState("b1");
			}
			break;
			case "b1":
			if(rpos.x < -1.5f)pos.x += mulsp(1.5f);
			else if(rpos.x > 1.5f)pos.x -= mulsp(1.5f);
			else{
				pos.x = 0.0f;
				if(sCnt == divsp(90)){
					int next = rand.nextInt(2);
					switch(next){
						case 0:
						changeState("c");
						break;
						case 1:
						changeState("f");
						break;
						default:
						changeState("c");
						break;
					}
				}
				
			}
			break;
			case "c":
			if(sCnt == 1){
				childHash["r1"].addAnimation(new MoveDist(30 ,120),"pose");
				childHash["r2"].addAnimation(new MoveDist(30 ,120),"pose");
				childHash["r3"].addAnimation(new MoveDist(30 ,120),"pose");
				childHash["r4"].addAnimation(new MoveDist(30 ,120),"pose");
				childHash["ra1"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra2"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra3"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["ra4"].addAnimation(new Move(30 ,LINK ,0,0,0.0),"pose1");
				childHash["fa1"].addAnimation(new Move(30 ,LINK ,0,0,150),"pose");
				childHash["fa2"].addAnimation(new Move(30 ,LINK ,0,0,150),"pose");
				childHash["fa3"].addAnimation(new Move(30 ,LINK ,0,0,150),"pose");
				childHash["fa4"].addAnimation(new Move(30 ,LINK ,0,0,150),"pose");
				childHash["fb1"].addAnimation(new Move(30 ,LINK ,0,0,-150),"pose");
				childHash["fb2"].addAnimation(new Move(30 ,LINK ,0,0,-150),"pose");
				childHash["fb3"].addAnimation(new Move(30 ,LINK ,0,0,-150),"pose");
				childHash["fb4"].addAnimation(new Move(30 ,LINK ,0,0,-150),"pose");
			}
			if(sCnt == divsp(31)){
				addAnimation(new Rotate(360 ,LINKY ,1.6 ,0.0 ,-1) ,"roll");
				changeState("e");
			}
			break;
			case "e":
			int rel=0;
			if(fabs(childHash["ra1"].rpos.z+800) < mulsp(4.0f)){
				if(!reload){
					(cast(Enemy)childHash["ra1"]).attack("laser");
				}
				rel ++;
			}
			if(fabs(childHash["ra2"].rpos.z+800) < mulsp(4.0f)){
				if(!reload){
					(cast(Enemy)childHash["ra2"]).attack("laser");
				}
				rel ++;
			}
			if(fabs(childHash["ra3"].rpos.z+800) < mulsp(4.0f)){
				if(!reload){
					(cast(Enemy)childHash["ra3"]).attack("laser");
				}
				rel ++;
			}
		
			if(fabs(childHash["ra4"].rpos.z+800) < mulsp(4.0f)){
				if(!reload){
					(cast(Enemy)childHash["ra4"]).attack("laser");
				}
				rel ++;
			}
			if(sCnt == divsp(360)){
				/*
				childHash["ra1"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose1");
				childHash["ra2"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose1");
				childHash["ra3"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose1");
				childHash["ra4"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose1");
				
//				linkY = deglimit(linkY);
				addAnimation(new RotateTo(30 ,LINKY ,0.0 ) ,"roll");
				*/
				changeState("b");
				/*
				int next = rand.nextInt(2);
				switch(next){
					case 0:
					changeState("b");
					break;
					case 1:
					changeState("f");
					break;
					default:
					changeState("b");
					break;
				}
				*/
			}
			if(rel == 0)reload = false;
			else reload = true;
			break;
			case "f":
			if(sCnt == 1){
				childHash["r1"].addAnimation(new MoveDist(60 ,120),"pose");
				childHash["r2"].addAnimation(new MoveDist(60 ,120),"pose");
				childHash["r3"].addAnimation(new MoveDist(60 ,120),"pose");
				childHash["r4"].addAnimation(new MoveDist(60 ,120),"pose");
				childHash["fa1"].addAnimation(new Move(60 ,LINK ,0,0,150),"pose");
				childHash["fa2"].addAnimation(new Move(60 ,LINK ,0,0,150),"pose");
				childHash["fa3"].addAnimation(new Move(60 ,LINK ,0,0,150),"pose");
				childHash["fa4"].addAnimation(new Move(60 ,LINK ,0,0,150),"pose");
				childHash["fb1"].addAnimation(new Move(60 ,LINK ,0,0,-150),"pose");
				childHash["fb2"].addAnimation(new Move(60 ,LINK ,0,0,-150),"pose");
				childHash["fb3"].addAnimation(new Move(60 ,LINK ,0,0,-150),"pose");
				childHash["fb4"].addAnimation(new Move(60 ,LINK ,0,0,-150),"pose");
				childHash["ra1"].addAnimation(new Move(60 ,LINK ,0,0,rand.nextFloat(50)+40.0),"pose1");
				childHash["ra2"].addAnimation(new Move(60 ,LINK ,0,0,rand.nextFloat(50)+40.0),"pose1");
				childHash["ra3"].addAnimation(new Move(60 ,LINK ,0,0,rand.nextFloat(50)+40.0),"pose1");
				childHash["ra4"].addAnimation(new Move(60 ,LINK ,0,0,rand.nextFloat(50)+40.0),"pose1");
//				linkY = deglimit(linkY);
//				addAnimation(new RotateTo(60 ,LINKY ,0.0 ) ,"roll");
				deleteAnimation("roll");
			}
			if(sCnt == divsp(60)){
				addAnimation(new Rotate(360 ,LINKY ,1 ,0.0 ,-1) ,"roll");
				changeState("g");
				
			}
			
			break;
			case "g":
			int rel=0;
			if(fabs(childHash["ra1"].rpos.z+800) < mulsp(4.0f)){
				if(!reload){
					(cast(Enemy)childHash["ra1"]).attack("balkan");
				}
				rel ++;
			}
			if(fabs(childHash["ra2"].rpos.z+800) < mulsp(4.0f)){
				if(!reload){
					(cast(Enemy)childHash["ra2"]).attack("rock");
				}
				rel ++;
			}
			if(fabs(childHash["ra3"].rpos.z+800) < mulsp(4.0f)){
				if(!reload){
					(cast(Enemy)childHash["ra3"]).attack("elaser");
				}
				rel ++;
			}
		
			if(fabs(childHash["ra4"].rpos.z+800) < mulsp(4.0f)){
				if(!reload){
					(cast(Enemy)childHash["ra4"]).attack("balkan");
				}
				rel ++;
			}
			if(rel == 0)reload = false;
			else reload = true;
			if(sCnt == divsp(360)){
				num ++;
				
				if(1 <= num){
					num = 0;
					changeState("h");
					
				}else changeState("f");
			}
			break;
			case "h":
			if(sCnt == divsp(60))changeState("b");
			/*
			int next = rand.nextInt(2);
			switch(next){
				case 0:
				changeState("b");
				break;
				case 1:
				changeState("c");
				break;
				default:
				changeState("b");
				break;
			}
			*/
			break;
			/*
			case "end":
			if(sCnt == 30){
				childHash["r1"].addAnimation(new MoveDist(30 ,40),"pose");
				childHash["r2"].addAnimation(new MoveDist(30 ,40),"pose");
				childHash["r3"].addAnimation(new MoveDist(30 ,40),"pose");
				childHash["r4"].addAnimation(new MoveDist(30 ,40),"pose");
				childHash["fa1"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose");
				childHash["fa2"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose");
				childHash["fa3"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose");
				childHash["fa4"].addAnimation(new Move(30 ,LINK ,0,0,90),"pose");
				childHash["fb1"].addAnimation(new Move(30 ,LINK ,0,0,-60),"pose");
				childHash["fb2"].addAnimation(new Move(30 ,LINK ,0,0,-60),"pose");
				childHash["fb3"].addAnimation(new Move(30 ,LINK ,0,0,-60),"pose");
				childHash["fb4"].addAnimation(new Move(30 ,LINK ,0,0,-60),"pose");
				changeState("end2");
			}
			break;
			case "end2":
			if(sCnt == 30)changeState("a");
			
			
			break;
			*/
			default:break;
		}
		if(cnt > 60 && cnt % divsp(10) == 0){
			makeWall("1" ,new Vector3(-180.0f,screen.GAME_UP,-800.0f) ,new Vector3(0,-4,0));
			makeWall("1" ,new Vector3(180.0f,screen.GAME_UP,-800.0f) ,new Vector3(0,-4,0));
		}
		poseX ++;
	}
	public void attack(char[] type){
		switch(type){
			case "a":
			float dx = rand.nextFloat(1.0f);
			new Enemy1(rpos ,vec3Normalize(ship.rpos - rpos)*3.0f+new Vector3(dx,0.0f,0.0f));
			new Enemy1(rpos ,vec3Normalize(ship.rpos - rpos)*3.0f+new Vector3(-dx,0.0f,0.0f));
			break;
			case "b":
			float dx = rand.nextFloat(1.0f);
			new Enemy1(rpos ,vec3Normalize(ship.rpos - rpos)*3.0f+new Vector3(dx,0.0f,0.0f));
			break;
			case "c":
			new BlastBullet(rpos ,new Vector3(5.0f ,0.0f ,0.0f));
			break;
			case "d":
			new BlastBullet(rpos ,new Vector3(-5.0f ,0.0f ,0.0f));
			break;
			case "e":
			new Missile(rpos ,new Vector3() ,new Vector3(0.0f,-0.1f,0.0f));
			break;
			case "r":
			double rad = -PI/2.0 + (20.0 + rand.nextFloat(40.0))*(1.0f-cast(float)((sCnt/120)%2)*2.0f)*PI/180.0;
			Vector3 vel = new Vector3(cos(rad),sin(rad),0.0f)*6.0f;
//			float x = 0.0f + (2.0f + rand.nextFloat(4.0f))*(1.0f-cast(float)((sCnt/120)%2)*2.0f);

//			Vector3 v = new Vector3(x ,-4.0f ,0.0f);//new Vector3(cos(rad)*6.0f ,-4.0f ,0.0f);//sin(rad)*6.0f,0.0f);;
			Parts p = new ReflectBullet(rpos ,vel);
			Parts p1 = new BulletAppend();
//			Parts p2 = new BulletAppend();
			p.addChild(p1, "1", 40 ,FOLLOW);
			break;
			
			default:break;
		}
	}	
	public void destroy(){
		super.destroy();
//		Sound_PlaySe(se_kind.BOMB);
	}
	
	
	
}

public class Boss1:Boss{
	bool right;
	public this(Vector3 pos ,Vector3 vel){
		super(400 ,pos);
		
		shape = new SH_Sphere(6);
		size = 40.0f;
		collisionRange = 45.0f;
		
		setBossColor();
		Parts p1 ,p2 ,p3 ,p4 ,p5 ,p6 ,p7 ,p8 ,p9 ,p10;
		p1 = new EnemyAppend(new SH_Sphere(6 ,1.0f),20 , -1,R ,G ,B ,alpha);
		addChild(p1, "larm1", 60 ,ENGAGED);
		p2 = new EnemyAppend(new SH_Sphere(4 ,2.5f),20 , -1,R ,G ,B ,alpha);
		p1.addChild(p2, "larm2", 70 ,ENGAGED);
		p3 = new EnemyAppend(new SH_Sphere(6 ,1.0f),20 , -1,R ,G ,B ,alpha);
		p2.addChild(p3, "larm3", 70 ,ENGAGED);
		p4 = new EnemyAppend(new SH_Sphere(4 ,2.5f),20 , -1,R ,G ,B ,alpha);
		p3.addChild(p4, "larm4", 70 ,ENGAGED);
		p5 = new EnemyAppend(new SH_Sphere(4 ,3.0f),20 , -1,R ,G ,B ,alpha);
		p4.addChild(p5, "larm5", 70 ,ENGAGED ,new Matrix() ,matRotateZ(90));
		p6 = new Hammer(new SH_Sphere(6 ,1.5f),40 , -1,R ,G ,B ,alpha);
		p5.addChild(p6, "lham", 80 ,ENGAGED ,matRotateZ(-90) ,matRotateZ(90));
		
		p1 = new EnemyAppend(new SH_Sphere(6 ,1.0f),20 , -1,R ,G ,B ,alpha);
		addChild(p1, "rarm1", 70 ,ENGAGED ,matRotateZ(180)*matRotateX(180));
		p2 = new EnemyAppend(new SH_Sphere(4 ,2.5f),20 , -1,R ,G ,B ,alpha);
		p1.addChild(p2, "rarm2", 70 ,ENGAGED);
		p3 = new EnemyAppend(new SH_Sphere(6 ,1.0f),20 , -1,R ,G ,B ,alpha);
		p2.addChild(p3, "rarm3", 70 ,ENGAGED);
		p4 = new EnemyAppend(new SH_Sphere(4 ,2.5f),20 , -1,R ,G ,B ,alpha);
		p3.addChild(p4, "rarm4", 70 ,ENGAGED);
		p5 = new EnemyAppend(new SH_Sphere(6 ,1.0f),20 , -1,R ,G ,B ,alpha);
		p4.addChild(p5, "rarm5", 70 ,ENGAGED);
		p6 = new Finger(new SH_Sphere(6 ,2.0f),7 , -1,R ,G ,B ,alpha);
		p5.addChild(p6, "rfin1", 40 ,ENGAGED ,matRotateZ(50));
		p7 = new Finger(new SH_Sphere(6 ,2.0f),7 , -1,R ,G ,B ,alpha);
		p5.addChild(p7, "rfin2", 40 ,ENGAGED ,matRotateZ(25));
		p8 = new Finger(new SH_Sphere(6 ,2.0f),7 , -1,R ,G ,B ,alpha);
		p5.addChild(p8, "rfin3", 40 ,ENGAGED ,matRotateZ(0));
		p9 = new Finger(new SH_Sphere(6 ,2.0f),7 , -1,R ,G ,B ,alpha);
		p5.addChild(p9, "rfin4", 40 ,ENGAGED ,matRotateZ(-25));
		p10 = new Finger(new SH_Sphere(6 ,2.0f),7 , -1,R ,G ,B ,alpha);
		p5.addChild(p10, "rfin5", 40 ,ENGAGED ,matRotateZ(-50));
		
		linkZ = 180.0f;
		childHash["larm2"].linkZ = -60.0f;
		childHash["larm4"].linkZ = -110.0f;
		
		addAnimation(new Move(30 ,LINK | POSE ,0.0f ,0.0f ,360.0f ,0.0f ,0.0f ,360.0f) ,"bam");
		childHash["larm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,0.0f) ,"bam");
		childHash["larm4"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,0.0f) ,"bam");
		childHash["larm5"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,50.0f) ,"bam");
		/*
		childHash["rarm2"].linkZ = -30.0f;
		childHash["rarm4"].linkZ = -90.0f;
		childHash["larm4"].linkX = 90.0f;
		childHash["larm2"].linkZ = -60.0f;
		childHash["larm4"].linkZ = 140.0f;
		*/
		/*
		childHash["rarm2"].addAnimation(new Move(60 ,LINK ,0.0f ,0.0f ,-30.0f) ,"pose");
		childHash["rarm4"].addAnimation(new Move(60 ,LINK ,0.0f ,0.0f ,-90.0f) ,"pose");
		childHash["larm2"].addAnimation(new Move(60 ,LINK ,0.0f ,0.0f ,-60.0f) ,"pose");
		childHash["larm4"].addAnimation(new Move(60 ,LINK ,90.0f ,0.0f ,140.0f) ,"pose");
		*/
//		childHash["larm4"].addAnimation(new Swing(60 ,LINKY ,15.0 ,0.0 ,-30 ,-1) ,"swing");
//		hp = 1000;
		right = true;
	
	}
	public void move(){
		super.move();
		
		switch(state){
			case "start":
			if(180.0f < rpos.y)pos.y -= mulsp(4.0f);
			if(sCnt == divsp(30)){
				childHash["larm5"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,0.0f) ,"bam");
				childHash["larm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-30.0f) ,"bam");
				childHash["larm4"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,110.0f) ,"bam");
				childHash["rarm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-20.0f) ,"pose");
				childHash["rarm4"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-100.0f) ,"pose");
			}
			if(sCnt == divsp(60)){
				childHash["rarm2"].addAnimation(new Swing(120 ,LINKZ ,0.5 ,0.0 ,0 ,-1) ,"swing");
				childHash["rarm4"].addAnimation(new Swing(120 ,LINKZ ,0.5 ,0.0 ,0 ,-1) ,"swing");
				changeState("a");
			}
			break;
			case "a":
			if(cnt % divsp(30) == 0){
				(cast(Enemy)childHash["rfin1"]).attack("a");
				(cast(Enemy)childHash["rfin2"]).attack("a");
				(cast(Enemy)childHash["rfin3"]).attack("a");
				(cast(Enemy)childHash["rfin4"]).attack("a");
				(cast(Enemy)childHash["rfin5"]).attack("a");
			}
			
			if(sCnt == divsp(200)){
				childHash["rarm2"].addAnimation(new Move(120 ,LINK ,0.0f ,0.0f ,10.0f) ,"pose");
				childHash["rarm4"].addAnimation(new Move(120 ,LINK ,0.0f ,0.0f ,-120.0f) ,"pose");
				changeState("b");
			}
			
			break;
			case "b":
			if(cnt % divsp(30) == 0){
				(cast(Enemy)childHash["rfin1"]).attack("a");
				(cast(Enemy)childHash["rfin2"]).attack("a");
				(cast(Enemy)childHash["rfin3"]).attack("a");
				(cast(Enemy)childHash["rfin4"]).attack("a");
				(cast(Enemy)childHash["rfin5"]).attack("a");
			}
			if(cnt % divsp(110) == 0){
				(cast(Enemy)childHash["rfin3"]).attack("b");
			}
			if(sCnt == divsp(180)){
				childHash["larm2"].addAnimation(new Move(60 ,LINK ,0.0f ,0.0f ,30.0f) ,"pose");
				childHash["larm4"].addAnimation(new Move(60 ,LINK ,90.0f ,0.0f ,70.0f) ,"pose");
			}
			if(sCnt == divsp(240)){
				childHash["larm1"].addAnimation(new Move(30 ,LINK ,180.0f ,0.0f ,0.0f) ,"bam");
				childHash["larm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,70.0f) ,"bam");
				childHash["larm4"].addAnimation(new Move(30 ,LINK ,90.0f ,0.0f ,20.0f) ,"bam");
				childHash["larm5"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,50.0f) ,"bam");
				changeState("c");
				
			}
			break;
			case "c":
			if(150.0f < rpos.y)pos.y -= mulsp(2.0f);
			if(sCnt == divsp(30)){
				childHash["larm1"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,0.0f) ,"bam");
				childHash["larm5"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,0.0f) ,"bam");
				childHash["larm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-30.0f) ,"bam");
				childHash["larm4"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,110.0f) ,"bam");
				childHash["rarm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-20.0f) ,"pose");
				childHash["rarm4"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-100.0f) ,"pose");
				
			}
			if(sCnt == divsp(60)){
				addAnimation(new Move(30 ,LINK | POSE ,0.0f ,180.0f ,360.0f ,0.0f ,180.0f ,360.0f) ,"pose");
				
				right = false;
				changeState("e");
			}
			break;
			
			case "e":
			if(sCnt == divsp(35))changeState("g");
			
			break;
			case "g":
			if(cnt % divsp(30) == 0){
				(cast(Enemy)childHash["rfin1"]).attack("a");
				(cast(Enemy)childHash["rfin2"]).attack("a");
				(cast(Enemy)childHash["rfin3"]).attack("a");
				(cast(Enemy)childHash["rfin4"]).attack("a");
				(cast(Enemy)childHash["rfin5"]).attack("a");
			}
			if(cnt % divsp(110) == 0){
//				(cast(Enemy)childHash["rfin3"]).attack("b");
			}
			if(sCnt == divsp(200)){
				childHash["rarm2"].addAnimation(new Move(120 ,LINK ,0.0f ,0.0f ,10.0f) ,"pose");
				childHash["rarm4"].addAnimation(new Move(120 ,LINK ,0.0f ,0.0f ,-120.0f) ,"pose");
				changeState("h");
			}
			
			break;
			case "h":
			if(cnt % divsp(30) == 0){
				(cast(Enemy)childHash["rfin1"]).attack("a");
				(cast(Enemy)childHash["rfin2"]).attack("a");
				(cast(Enemy)childHash["rfin3"]).attack("a");
				(cast(Enemy)childHash["rfin4"]).attack("a");
				(cast(Enemy)childHash["rfin5"]).attack("a");
			}
			if(cnt % divsp(110) == 0){
				(cast(Enemy)childHash["rfin3"]).attack("b");
			}
			if(sCnt == divsp(180)){
				childHash["larm2"].addAnimation(new Move(60 ,LINK ,0.0f ,0.0f ,30.0f) ,"pose");
				childHash["larm4"].addAnimation(new Move(60 ,LINK ,90.0f ,0.0f ,70.0f) ,"pose");
			}
			if(sCnt == divsp(240)){
				childHash["larm1"].addAnimation(new Move(30 ,LINK ,-180.0f ,0.0f ,0.0f) ,"bam");
				childHash["larm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,70.0f) ,"bam");
				childHash["larm4"].addAnimation(new Move(30 ,LINK ,90.0f ,0.0f ,20.0f) ,"bam");
				childHash["larm5"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,50.0f) ,"bam");
				changeState("i");
			}
			break;
			case "i":
			if(150.0f < rpos.y)pos.y -= mulsp(2.0f);
			if(sCnt == divsp(30)){
				childHash["larm1"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,0.0f) ,"bam");
				childHash["larm5"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,0.0f) ,"bam");
				childHash["larm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-30.0f) ,"bam");
				childHash["larm4"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,110.0f) ,"bam");
				childHash["rarm2"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-20.0f) ,"pose");
				childHash["rarm4"].addAnimation(new Move(30 ,LINK ,0.0f ,0.0f ,-100.0f) ,"pose");
				
			}
			if(sCnt == divsp(60)){
				addAnimation(new Move(30 ,LINK | POSE ,0.0f ,0.0f ,360.0f ,0.0f ,0.0f ,360.0f) ,"pose");
				right = true;
				changeState("j");
			}
			break;
			case "j":
			if(sCnt == divsp(35))changeState("a");
			
			break;
			default:break;
		}
//		poseZ += 1;
//		childHash["larm4"].linkY -= 1.0f;
	}
	public void destroy(){
		super.destroy();
//		Sound_PlaySe(se_kind.BOMB);
	}
	
	
	
	
}

public Shape BOSS3SHAPE;
public class Boss3:Boss{
	private:
	double buldeg;
	int reload;
	int reloadB;
	bool right;
	int num;
	
	int numB;
	
	public this(Vector3 pos ,Vector3 vel){
		super(1000 ,new Vector3(pos.x ,pos.y ,-800));
		
		if(BOSS3SHAPE is null){
			BOSS3SHAPE = new SH_Sphere(16);
		}
		shape = cast(Shape)BOSS3SHAPE.clone();
		size = 0.1f;
		collisionRange = size;
		R = 0.05f;G = 0.05f;B = 0.05f;alpha = 1.0f;
		poseZ = 90;
		
		drawing = POLYGON;
		
		
		
		buldeg =0;
		right = false;
		reload = 0;
		reloadB = 0;
		num = 0;
		numB = 0;
		
//		addAnimation(new Pulse(120 ,1.0f ,-1) ,"mag");
		/*
		Parts p1 ,p2 ,p3 ,p4 ,p5 ,p6 ,p7 ,p8 ,p9 ,p10;
		p1 = new EnemyAppend(BOSS3SHAPE,100 , -1,R ,G ,B ,alpha);
		addChild(p1, "larm1", 80 ,ENGAGED);
		p2 = new EnemyAppend(BOSS3SHAPE,80 , -1,R ,G ,B ,alpha);
		p1.addChild(p2, "larm2", 60 ,ENGAGED);
		p3 = new EnemyAppend(BOSS3SHAPE,60 , -1,R ,G ,B ,alpha);
		p2.addChild(p3, "larm3", 40 ,ENGAGED);
		*/
	}
	public void move(){
		super.move();
		collisionRange = size;
		switch(state){
			case "start":
			
			if(sCnt == divsp(60)){
				addAnimation(new Magnification(500 ,100.0f) ,"mag");
				changeState("startA");
			}
			
			reloadB = 0;
			reload = 0;
			numB = 0;
			break;
			case "startA":
			if(reload <= 0){
	//			double deg = cast(double)((cnt/divsp(20))%divsp(90))*mulsp(2.0f);// *22.5;
				float hp = fmax(3 ,fmin(10.0f ,sCnt / divsp(50)))+rand.nextFloat(fmax(0.0f,fmin(7 ,10.0f - sCnt / divsp(50.0))));
				double rad;
				double speed = fmin(3.0f ,fmax(1.0f,1.0f+sCnt *mulsp(0.005)));
				Vector3 vel;
				for(double d = 0.0;d<360.0;d+=45.0){
					rad = (d+buldeg)*PI/180.0;
					vel = new Vector3(cos(rad),sin(rad),0.0f)*speed;
					new Mylmidon1(rpos -vel,vel ,hp);
				}
				reload = divsp(cast(int)fmax(20.0f ,40.0f - cast(float)sCnt*0.04f));
				buldeg = deglimit(buldeg+fmax(22.5 ,fmin(95.0f ,sCnt / divsp(5.0f))));
			}
			if(reloadB <= 0){
				
				double rad;
				double speed = fmin(3.0f ,fmax(2.0f,1.5f+sCnt *mulsp(0.01)));
				Vector3 vel;
				
				for(double d = cast(real)(numB%2)*45.0+45.0;d<360.0+cast(real)(numB%2)*45.0 + 45.0;d+=90.0){
					for(double dd = d;dd<d+45.0;dd+=5.0){
						
						rad = dd*PI/180.0;
						vel = new Vector3(cos(rad),sin(rad),0.0f)*speed;
						new Bullet1(rpos -vel,vel);
						
					}
				}
				
				reloadB = divsp(cast(int)fmax(75.0f ,150.0f - cast(float)sCnt*0.06f));
				numB ++;
				
			}
			reload --;
			reloadB --;
			if(sCnt == divsp(840)){
				changeState("a0");
			}
			break;
			case "a0":
			if(sCnt == divsp(45))changeState("a");
			break;
			case "a":
			if(sCnt % divsp(30) == 0){
				double rad = -PI/2.0 + (10.0 + rand.nextFloat(60.0) )*PI /180.0;
				float speed = 3.0f  + rand.nextFloat(1.5f - 1.5*sin(rad));
				float si =sin(rad)*speed;
				float co = cos(rad)*speed;
				new MylmidonBomb(rpos ,new Vector3(co,si,0.0f),8 ,30);
				new MylmidonBomb(rpos ,new Vector3(-co,si,0.0f),8 ,30);
			}
			if(sCnt == divsp(600)){
				changeState("b0");
			}
			break;
			case "b0":
			if(sCnt == divsp(120)){
				changeState("b1");
			}
			break;
			case "b1":
			if(sCnt == divsp(500)){
				changeState("f0");
			}
			if(sCnt == 1){
				Parts p;
				
				p = new MylmidonCell(new Vector3(),0.0 ,1,15,15 ,40);
				addChild(p,"0",size-20 ,NORMAL ,matRotateZ(0.0));
				childHash["0"].addAnimation(new RotateTo(300 ,LINKZ ,360) ,"roll");
//				p.linkZ -= poseZ;
				
			}
			
			if(sCnt == divsp(240)){
				Parts p;
				
				p = new MylmidonCell(new Vector3(),0.0 ,-1,15,15 ,40);
				addChild(p,"1",size-20 ,NORMAL ,matRotateZ(90.0));
				childHash["1"].addAnimation(new RotateTo(300 ,LINKZ ,-360) ,"roll");
//				p.linkZ -= poseZ;
				
			}
			
//			linkZ += 0.1;
			break;
			case "c0":
			if(sCnt == divsp(60)){
				changeState("c1");
			}
			break;
			case "c1":
			
			break;
			case "f0":
			if(sCnt == 1){
				num=0;
				reload =0;
				reloadB =0;
				right=true;
				changeState("f1");
			}
			break;
			case "f1":
			
			if(reload <= 0 && sCnt > divsp(60)){
				num++;
				reload = cast(int)divsp(fmax(25.0f ,120.0f - cast(float)sCnt / 900.0f * 95.0f)*1.5f);
				Parts p,p1,p2,p3,p4;
				Vector3 t;
				if(right){
					t = new Vector3(Ship.RIGHTX,Ship.POSY,-800);
				}else{
					t = new Vector3(Ship.LEFTX,Ship.POSY,-800);
				}
				right ^= true;
				for(double rad = -PI;rad<PI;rad += PI/2.0){
					p=new LockBullet(rpos ,new Vector3(2.5*cos(rad),2.5,2.5*sin(rad)),t,fmax(0.8f, 2.0f - reload /120.0f));
					p1=new BulletAppend(20,null,rpos);
					p.addChild(p1,"",40,FOLLOW);
					p2=new BulletAppend(20,null,rpos);
					p1.addChild(p2,"",40,FOLLOW);
					p3=new BulletAppend(20,null,rpos);
					p2.addChild(p3,"",40,FOLLOW);
//					p4=new BulletAppend(20,null,rpos);
//					p3.addChild(p4,"",40,FOLLOW);
				}
				
			}
			if(reloadB <= 0){
				double rad;
				Vector3 vel;
				double dddeg = 10.0*sin(cast(real)sCnt/120.0*PI);
				for(double d = dddeg -90 - 30.0;d<dddeg -90+30.0+10.0;d+=10.0){
					rad = d*PI/180.0;
					vel = new Vector3(cos(rad),sin(rad),0.0f)*fmax(0.125f ,0.01f + cast(float)num * 0.01f);
					new Mylmidon1acc(rpos -vel,vel ,2);
				}
				reloadB = cast(int)divsp(fmax(24.0f ,48.0f - cast(float)num * 2.0f));
			}
			
			reload --;
			reloadB --;
			break;
			
			default:break;
		}
		/*
		if(cnt == divsp(60))addAnimation(new Magnification(500 ,100.0f) ,"mag");
		if(cnt < divsp(900)){
			if(reload <= 0){
	//			double deg = cast(double)((cnt/divsp(20))%divsp(90))*mulsp(2.0f);// *22.5;
				float hp = fmax(3 ,fmin(10.0f ,cnt / divsp(50)))+rand.nextFloat(fmax(0.0f,fmin(7 ,10.0f - cnt / divsp(50.0))));
				double rad;
				double speed = fmin(3.0f ,fmax(1.0f,1.0f+cnt *mulsp(0.005)));
				Vector3 vel;
				for(double d = 0.0;d<360.0;d+=45.0){
					rad = (d+buldeg)*PI/180.0;
					vel = new Vector3(cos(rad),sin(rad),0.0f)*speed;
					new Mylmidon1(rpos -vel,vel ,hp);
				}
				reload = divsp(cast(int)fmax(20.0f ,40.0f - cast(float)cnt*0.04f));
				buldeg = deglimit(buldeg+fmax(22.5 ,fmin(95.0f ,cnt / divsp(5.0f))));
			}
			reload --;
			
		}
		*/
		poseZ += 1.0f;
		dam = 0.0;
			
	}
	public override void reportCollision(int kind ,Parts p){
//		if(state.cmp("startA") != 0){
			super.reportCollision(kind ,p);
			dam = 0;
//		}
	}
	public void size(double s){
		super.size(s);
		collisionRange = size *3.0f / 4.0f;
	}
	public double size(){
		return super.size();
	}
}
public Shape BOSS4SHAPE;
public class Boss4:Boss{
	private:
	double buldeg;
	int reload;
	bool right;
	int num;
	
	public this(Vector3 pos ,Vector3 vel){
		super(700 ,new Vector3(pos.x ,pos.y ,-800));
		
		if(BOSS4SHAPE is null){
			BOSS4SHAPE = new SH_Sphere(16);
		}
		shape = cast(Shape)BOSS4SHAPE.clone();
		size = 0.0f;
		collisionRange = size * 3.0f / 4.0f;
		R = 0.05f;G = 0.05f;B = 0.05f;alpha = 1.0f;
		poseZ = 90;
		
		drawing = POLYGON;
		
		
		
		buldeg =0;
		right = false;
		reload = 0;
		
//		addAnimation(new Pulse(120 ,1.0f ,-1) ,"mag");
		
		Parts p1 ,p2 ,p3 ,p4 ,p5 ,p6 ,p7 ,p8 ,p9 ,p10;
		p1 = new EnemyAppend(BOSS4SHAPE,60 , -1,R ,G ,B ,alpha);
		addChild(p1, "larm1", 60 ,ENGAGED ,matRotateZ(0));
		p2 = new EnemyAppend(BOSS4SHAPE,50 , -1,R ,G ,B ,alpha);
		p1.addChild(p2, "larm2", 50 ,ENGAGED);
		p3 = new EnemyAppend(BOSS4SHAPE,40 , -1,R ,G ,B ,alpha);
		p2.addChild(p3, "larm3", 40 ,ENGAGED);
		
		p1 = new EnemyAppend(BOSS4SHAPE,60 , -1,R ,G ,B ,alpha);
		addChild(p1, "larm1", 60 ,ENGAGED ,matRotateZ(-30));
		p2 = new EnemyAppend(BOSS4SHAPE,50 , -1,R ,G ,B ,alpha);
		p1.addChild(p2, "larm2", 50 ,ENGAGED);
		p3 = new EnemyAppend(BOSS4SHAPE,40 , -1,R ,G ,B ,alpha);
		p2.addChild(p3, "larm3", 40 ,ENGAGED);
		
		p1 = new EnemyAppend(BOSS4SHAPE,60 , -1,R ,G ,B ,alpha);
		addChild(p1, "larm1", 60 ,ENGAGED ,matRotateZ(-60));
		p2 = new EnemyAppend(BOSS4SHAPE,50 , -1,R ,G ,B ,alpha);
		p1.addChild(p2, "larm2", 50 ,ENGAGED);
		p3 = new EnemyAppend(BOSS4SHAPE,40 , -1,R ,G ,B ,alpha);
		p2.addChild(p3, "larm3", 40 ,ENGAGED);
		
		p1 = new EnemyAppend(BOSS4SHAPE,60 , -1,R ,G ,B ,alpha);
		addChild(p1, "larm1", 60 ,ENGAGED ,matRotateZ(-90));
		p2 = new EnemyAppend(BOSS4SHAPE,50 , -1,R ,G ,B ,alpha);
		p1.addChild(p2, "larm2", 50 ,ENGAGED);
		p3 = new EnemyAppend(BOSS4SHAPE,40 , -1,R ,G ,B ,alpha);
		p2.addChild(p3, "larm3", 40 ,ENGAGED);
		
		p1 = new EnemyAppend(BOSS4SHAPE,60 , -1,R ,G ,B ,alpha);
		addChild(p1, "larm1", 60 ,ENGAGED ,matRotateZ(-120));
		p2 = new EnemyAppend(BOSS4SHAPE,50 , -1,R ,G ,B ,alpha);
		p1.addChild(p2, "larm2", 50 ,ENGAGED);
		p3 = new EnemyAppend(BOSS4SHAPE,40 , -1,R ,G ,B ,alpha);
		p2.addChild(p3, "larm3", 40 ,ENGAGED);
		
	}
	public void move(){
		super.move();
		switch(state){
			case "start":
			
			if(sCnt == divsp(60)){
				addAnimation(new Magnification(500 ,100.0f) ,"mag");
				changeState("startA");
			}
			default:break;
		}
		
		dam = 0;
			
	}
	public override void reportCollision(int kind ,Parts p){
		super.reportCollision(kind ,p);
		dam = 0;
	}
	public void size(double s){
		super.size(s);
		collisionRange = size *3.0f / 4.0f;
	}
	public double size(){
		return super.size();
	}
}

public double deglimit(double deg){
	while(deg<-PI)deg += 180.0;
	while(PI<deg)deg -= 180.0;
	return deg;
}

