シューティングゲームの基本となる弾について学習しましょう。

等速直進弾

等速で直進する基本の弾です。_rotationの角度にspeedの距離ずつ直進します。

onClipEvent (load) {
  var speed = 5; // 移動速度
  var x=_x; // 次x座標
  var y=_y; // 次y座標
  _rotation=90; // ↓向き
}
onClipEvent (enterFrame) {
  // 等速直進弾
  // _rotationの角度にspeedだけ進む 
  x += speed*Math.cos(_rotation/180*Math.PI);
  y += speed*Math.sin(_rotation/180*Math.PI);
  _x=x;  _y=y;  // 移動
}

初期設定で変数speedの値を決め、クリップイベントループを使って移動します。speedの値は フレームレートと合わせて調整します。

次の位置を変数x,yに一度代入しているのは、画面端の処理などで変更する場合に備えてのことです。

_rotationの値は下方向(90度)に初期化していますが、他の方向にする場合には、 弾を画面に配置した後に設定します(後述)。自機狙い弾は、自機の方向を指定します。

加速弾

加速していく弾です。等速直進弾のspeedの値を徐々に増やします。

onClipEvent (load) {
  var speed = 5; // 移動速度
  var d_speed = 0.5; // 加速度
  var max_speed = 20; // 最大速度
  var x=_x; // 次x座標
  var y=_y; // 次y座標
  _rotation=90; // ↓向き
}
onClipEvent (enterFrame) {
  // 加速直進弾
  // _rotationの角度にspeedだけ進む 
  x += speed*Math.cos(_rotation/180*Math.PI);
  y += speed*Math.sin(_rotation/180*Math.PI);
  _x=x; _y=y; // 移動
  speed+=d_speed; // 加速
  speed=Math.min(speed, max_speed); //速度を上限に抑える
}

速度があまり早くなると、自機を通り抜けてしまうことがあります。

誘導弾

自機の方向に軌道を変えながら進む弾です。一定間隔で_rotationを自機方向に変化させながら移動します。

onClipEvent (load) {
  var speed = 5; // 移動速度
  var x=_x; // 次x座標
  var y=_y; // 次y座標
  _rotation=90; // ↓向き
  var count = 0; // カウンタ
  var max_count=10; // カウンタ上限
}
onClipEvent (enterFrame) {
  // 誘導弾
  if (count == max_count) { // カウンタ上限に達したら
    _rotation=Math.atan2(_parent.jiki_mc._y-_y, _parent.jiki_mc._x-_x)*180/Math.PI; // 自機方向
    count = 0;
  }
  count++;
  // _rotationの角度にspeedだけ進む 
  x += speed*Math.cos(_rotation/180*Math.PI);
  y += speed*Math.sin(_rotation/180*Math.PI);
  _x=x;  _y=y;  // 移動
}

あまり頻繁に角度を変えると追尾がきつくなるので、一定間隔になるように、変数countの値を1ずつふやしてmax_countの値 を等しくなったときに変えることにしています。

この誘導弾は、自機方向に角度を変更できるため、永遠に追いかけてきます。これでは 避けるのが大変なので、角度変更に制限を付けるのが一般的です。

角度制限付き誘導弾

誘導弾の角度変更に制限をつけます。

onClipEvent (load) {
  var speed = 5; // 移動速度
  var x=_x; // 次x座標
  var y=_y; // 次y座標
  _rotation=90; // ↓向き
  var count = 0; // カウンタ
  var max_count=10; // カウンタ上限
  var old_r=_rotation; // 前角度
  var d_r=0; // 回転角度
  var max_d_r=20; // 最大回転角度
}
onClipEvent (enterFrame) {
  // 回転角度制限付き誘導弾
  if (count == max_count) { // カウンタ上限に達したら
    old_r=_rotation; // 前角度保持
    _rotation=Math.atan2(_parent.jiki_mc._y-_y, _parent.jiki_mc._x-_x)*180/Math.PI; // 自機方向
    d_r=(_rotation-old_r+180)%360-180; // 回転角度-180〜180になるように補正
    d_r=Math.min( max_d_r,d_r); // 最大回転角度制限
    d_r=Math.max(-max_d_r,d_r); // 最小回転角度制限
    _rotation=old_r+d_r;
    count = 0;
  }
  count++;
  // _rotationの角度にspeedだけ進む 
  x += speed*Math.cos(_rotation/180*Math.PI);
  y += speed*Math.sin(_rotation/180*Math.PI);
  _x=x;  _y=y;  // 移動
}

弾の射出

弾を射出するプログラムを考えます。

準備としてjiki_mcと元となる上記の弾をb1_mc〜b4_mcなどでステージ上に作成しておきます。

フレーム1に以下のフレームアクションを設定します。ここでは、関数addBullet()を定義しているだけです。

n=0; // 弾数
function addBullet(type, x, y, r) { // type:種類, x:x座標, y:y座標, r:角度
  _root["b"+type+"_mc"].duplicateMovieClip("b"+n, 1000+n); // b[type]_mcをb[n]という名前で深度1000+nに複製
  _root["b"+n]._x=x; // x座標
  _root["b"+n]._y=y; // y座標
  _root["b"+n]._rotation=r; // 角度
  n++;
}

砲のムービークリップを作成し、ムービークリップアクションを設定します。

下向き弾の射出

on(release) {
  _root.addBullet(1, _x, _y, 90); // 下向き弾射出
}

クリックするとb1_mcの弾を下向きに射出します。typeの数字を変えれば異なる弾が射出されます。

自機狙い弾の射出

on(release) {
  _root.addBullet(1, _x, _y, Math.atan2(_parent.jiki_mc._y-_y, _parent.jiki_mc._x-_x)*180/Math.PI); // 自機狙い弾射出
}

クリックするとb1_mcの弾を自機方向に射出します。typeの数字を変えれば異なる弾が射出されます。

全方位弾の射出

on(release) {
  for (var i=0; i<12; i++) {
    _root.addBullet(1, _x, _y, i*30); // 全方位弾射出
  }
}

クリックするとb1_mcの弾を12方向に射出します。typeの数字を変えれば異なる弾が射出されます。

i*30をi*30+15に変えると角度をずらした弾になります。

i*30をi*30+Math.atan2(_parent.jiki_mc._y-_y, _parent.jiki_mc._x-_x)*180/Math.PIにすると、自機狙いになります。

上記例はクリックしたら射出するようになっていますが、ムービークリップのタイムラインのフレームアクションで 関数addBullet()を呼び出すことで、射出タイミングを設定することも可能です。