トップ


大ボスをつける2

多重継承と継承の継承

Bossのプログラムを覗いて見ると、Enemyを継承して、appearShootメソッドを持っているということが共通しています。何も、BossはEnemyをいつも継承しなくてはならないわけではありません。middleBossを継承しましょう。

Boss.tonyu
extends middleBoss;

function involute(sx,sy,ang,rate) {
  x=sx+cos(ang)+ang/rate*3.14156*sin(ang);
  y=sy+sin(ang)-ang/rate*3.14156*cos(ang);
}
function lemniscate(sx,sy,ang,rate) {
  if(1+sin(ang)==0) ang++;
  x=sx+rate*(cos(ang)/(1 +(sin(ang))*(sin(ang))));
  y=sy+rate*(sin(ang)*cos(ang)/(1 +sin(ang))*(1 +sin(ang)));
}
ang=5000;
while(ang>0){
  involute($screenWidth/2-15,100,ang,60);
  ang-=10;
  update();
}
vx=2;
life=500;
mark=1000;
sx=x;
sy=y;
ang=90;
while(1){
  ang++;
  lemniscate(sx,sy,ang,150);
  if(x<80 || x>$screenWidth-80) vx=-vx;
  appearShoot();
  atariHantei();
  update();
}

これでも、以前と同じ結果が得られます。Enemyを継承したmiddleBossをさらに継承することをそのまま「継承の継承」と呼びEnemyとmiddleBossのメソッドを共有できます。

Bossの移動方法がレムニスケート曲線だけではなにやら物足りません。Greenクラスのアステロイド曲線も使用してみたくなりました。都合の良いことにアステロイド曲線はもうすでにメソッドとして用意しておきました。
しかし、GreenはEnemyは継承していますが、middleBossは継承していません。よって、BossがGreenを継承した場合appearShootメソッドがないというエラーが出てしまいます。
GreenとmiddleBossの両方を継承できないのでしょうか。残念ながら2つのクラスを継承すること(多重継承)はTonyuではできません。
しかし、Greenクラスのメソッドを継承を使用することなくBossクラスが使用することはできます。
条件としては、Greenが画面上に表示されていなければなりません。また、returnを使用して値を得なくてはなりません。よって、Greenは、

Green.tonyu
extends Enemy;

function asteroidX(ax,ang,maxis,frate){
  xx=ax+maxis*cos(ang)*cos(ang)*cos(ang);
  return xx;
}
function asteroidY(ay,ang,maxis,frate){
  yy=ay+maxis*frate+maxis*frate*sin(ang)*sin(ang)*sin(ang);
  return yy;
}
mark=100;
life=5;
sx=x;
sy=y;
angle=270;
majorAxis=100;
flatRate=1/2;
i=0;
animationOn=0;
vp=0;
if (x>$myChar.x) vx=2; else vx=-2;
while (y<$screenHeight+15) {
  i++;
  x=asteroidX(sx,angle,majorAxis,flatRate);
  y=asteroidY(sy,angle,majorAxis,flatRate);
  angle+=3;
  if(x<15 || x>$screenWidth-15) d=-d;
  atariHantei();
  if(rnd(50)==0 && animationOn==0) {
    vp=1;
    animationOn=1;
  }
  if(p==$pat_Sample+21 && vp==1) {
    vp=-1;
    appear(new Electoron(x,y,$pat_Sample+24));
  }
  else if(p==$pat_Sample+19 && vp==-1) {
    vp=0;
    animationOn=0;
  }
  if(i%20==0) p=p+vp;
  update();
}

さらに、Bossではappear関数で、
appear(new Green(x+1000,y+20,$pat_Sample+19));
でのように、Greenを画面外に表示させて、存在させておく必要性があります。
これでは、さすがに見にくいと思います。むしろ、GreenにあったasteroidメソッドをEnemyに入れてみましょう。

Enemy.tonyu
extends SpriteChar;

function onDie() {
  appear(new Bomb(x , y ,$pat_Sample+4,3));
}
function atariHantei() {
  for (t in $chars) {
   if ( t is Tama && crashTo(t) )  {
     life=life-1;
     if(life<=0) {
       die();
       if(mark==200) $UFO.stop=3;
       $score=$score+mark;
       $mplayer.play($se_bomb,0,60);
     }
     t.die();
   }
  }
  if (crashTo($myChar)) $myChar.die();
}
function asteroid(ax,ay,ang,maxis,frate){
  x=ax+maxis*cos(ang)*cos(ang)*cos(ang);
  y=ay+maxis*frate+maxis*frate*sin(ang)*sin(ang)*sin(ang);
}
Green.tonyu
extends Enemy;

mark=100;
life=5;
sx=x;
sy=y;
angle=270;
majorAxis=100;
flatRate=1/2;
i=0;
animationOn=0;
vp=0;
if (x>$myChar.x) vx=2; else vx=-2;
while (y<$screenHeight+15) {
  i++;
  asteroid(sx,sy,angle,majorAxis,flatRate);
  angle+=3;
  if(x<15 || x>$screenWidth-15) d=-d;
  atariHantei();
  if(rnd(50)==0 && animationOn==0) {
    vp=1;
    animationOn=1;
  }
  if(p==$pat_Sample+21 && vp==1) {
    vp=-1;
    appear(new Electoron(x,y,$pat_Sample+24));
  }
  else if(p==$pat_Sample+19 && vp==-1) {
    vp=0;
    animationOn=0;
  }
  if(i%20==0) p=p+vp;
  update();
}
Boss.tonyu
extends middleBoss;

function involute(sx,sy,ang,rate) {
  x=sx+cos(ang)+ang/rate*3.14156*sin(ang);
  y=sy+sin(ang)-ang/rate*3.14156*cos(ang);
}
function lemniscate(sx,sy,ang,rate) {
  if(1+sin(ang)==0) ang++;
  x=sx+rate*(cos(ang)/(1 +(sin(ang))*(sin(ang))));
  y=sy+rate*(sin(ang)*cos(ang)/(1 +sin(ang))*(1 +sin(ang)));
}
ang=5000;
while(ang>0){
  involute($screenWidth/2-15,100,ang,60);
  ang-=10;
  update();
}
life=500;
mark=1000;
sx=x;
sy=y;
ang=90;
circle=0;
while(1){
  r=rnd(3);
  ang++;
  if(circle==0 && (ang%360==90 || ang%360==270)&& r==0) {
    ang=270;
    circle=1;
  }
  if (circle==0) lemniscate(sx,sy,ang,150);
  if(circle==1) asteroid(sx,sy,ang,100,1);
  if(circle==1 && ang%720==630) {
    circle=0;
    ang=90;
  }
  appearShoot();
  atariHantei();
  update();
}

レニムスケート曲線の時はcircle==0、アステロイド曲線の時にはcircle==1という条件にしました。
また、アステロイド曲線は一周だけすることにして、その後はレニムスケート曲線に戻すようにしてあります。
レニムスケート曲線からアステロイド曲線に移るときにの条件が2つ(ang%360==90、ang%360==270)ありますが、これは、右から左へ行くときと左から右へ行くとき<の2条件あるからです。

これで、アステロイド曲線も使用できるようになりました。

次はBossにレーザーを撃たせて見ましょう。

  トップ