[ cocos2d-html ] ブロック崩し -画面の境界線作成-

前回に引き続き、ブロック崩しの作成について、説明していきます。

現時点では、物理オブジェクトとして設定しているものはブロック及びバーの2種類です。
その為、ボールが左右へ行っても画面外へ出てしまうので、上下左右にBox2dを設定し
ボールが画面内に留まるようにします。

グローバル変数の追加及び、init内Box2dワールドを生成した後に以下を追加します。
グローバル変数

  1. //画面上部の境界線
  2. var spr_disp_upper = null;
  3. //画面下部の境界線
  4. var spr_disp_bottom = null;
  5. //画面左側の境界線
  6. var spr_disp_left = null;
  7. //画面右側の境界線
  8. var spr_disp_right = null;

init内

  1. var fixDef = new b2FixtureDef;
  2. fixDef.density = 1.0;
  3. //摩擦係数
  4. fixDef.friction = 0;
  5. //反発係数
  6. fixDef.restitution = 1;
  7. var bodyDef = new b2BodyDef;
  8. //create ground
  9. bodyDef.type = b2Body.b2_staticBody;
  10. fixDef.shape = new b2PolygonShape;
  11. //上下の境界線の幅と高さ設定
  12. fixDef.shape.SetAsBox(320.0 / PTM_RATIO, 1 / PTM_RATIO);
  13. //upper
  14. //ダミーでsprite設定
  15. //表示は行わない
  16. //CB関数用の変数となります
  17. spr_disp_upper = cc.Sprite.create( “res/boll.png” );
  18. bodyDef.position.Set(320.0 / PTM_RATIO / 2, 380.0 / PTM_RATIO);
  19. bodyDef.userData = spr_disp_upper;
  20. world.CreateBody(bodyDef).CreateFixture(fixDef);
  21. //bottom
  22. //ダミーでsprite設定
  23. //表示は行わない
  24. //CB関数用の変数となります
  25. spr_disp_bottom = cc.Sprite.create( “res/boll.png” );
  26. bodyDef.position.Set(320.0 / PTM_RATIO / 2, -1);
  27. bodyDef.userData = spr_disp_bottom;
  28. world.CreateBody(bodyDef).CreateFixture(fixDef);
  29. //左右の境界線の幅と高さ設定
  30. fixDef.shape.SetAsBox(1 / PTM_RATIO, 380.0 / PTM_RATIO);
  31. //left
  32. //ダミーでsprite設定
  33. //表示は行わない
  34. //CB関数用の変数となります
  35. spr_disp_left = cc.Sprite.create( “res/boll.png” );
  36. bodyDef.position.Set(0, 380.0 / PTM_RATIO / 2);
  37. bodyDef.userData = spr_disp_left;
  38. world.CreateBody(bodyDef).CreateFixture(fixDef);
  39. //right
  40. //ダミーでsprite設定
  41. //表示は行わない
  42. //CB関数用の変数となります
  43. spr_disp_right = cc.Sprite.create( “res/boll.png” );
  44. bodyDef.position.Set(320.0 / PTM_RATIO, 380.0 / PTM_RATIO / 2);
  45. bodyDef.userData = spr_disp_right;
  46. world.CreateBody(bodyDef).CreateFixture(fixDef);

境界線を設定するために必要なFixtureDef、b2BodyDefのインスタンスを生成します。
摩擦係数や密度の初期化を行います。

生成したFixtureDefを使用して幅と高さをしているのが
fixDef.shape.SetAsBox(320.0 / PTM_RATIO, 1 / PTM_RATIO);
になります。

前回の記事でも説明したとおり、Box2Dの世界では長さの単位にM(メートル)を使用します。
そのため、実際に指定する幅・高さを PTM_RATIO で割る形になっています。

bodyDefインスタンスのポジションセットにより、fixtureDefで設定した境界線を設置する場所を指定します。
bodyDef.position.Set(320.0 / PTM_RATIO / 2, 380.0 / PTM_RATIO);

上記までが境界線の設定となり
実際に境界線の生成を行っているのが以下になります。
world.CreateBody(bodyDef).CreateFixture(fixDef);

それぞれの引数に「bodyDef」「fixDef」を指定することによって
先ほど設定した幅高さの境界線(※1)が指定した箇所(※2)に生成されることになります。
※1.FixtureDefにより設定
※2.BodyDefにより設定

これで、ボールが画面内に収まるようになりました。
残りは当たったブロックを消去する処理が必要になります。
上記を可能にするために、衝突イベント時リスナーを登録します。
追記する場所は、init内になります。

  1. var listener = new Box2D.Dynamics.b2ContactListener;
  2. listener.BeginContact = function (contact) {
  3.   var contactA = contact.GetFixtureA().GetBody().GetUserData();
  4.   var contactB = contact.GetFixtureB().GetBody().GetUserData();
  5.   
  6.   if (contactA == spr_disp_upper || contactB == spr_disp_upper) {
  7.     //上の壁
  8.   }
  9.   else if (contactA == spr_disp_bottom || contactB == spr_disp_bottom) {
  10.     //下の壁
  11.   }
  12.   else if (contactA == spr_disp_left  || contactB == spr_disp_left) {
  13.     //左の壁
  14.   }
  15.   else if (contactA == spr_disp_right || contactB == spr_disp_right) {
  16.     //右の壁
  17.   }
  18.   else {
  19.     //その他
  20.   }
  21. };
  22. listener.EndContact = function (contact) {
  23. };
  24. world.SetContactListener(listener);

ブロック衝突時処理のため、今回はその他の部分に追記することになりますが
初めに、ブロック消去処理に必要となる変数を追加しましょう。

グローバル変数定義部に追加

  1. //ブロックが存在するかどうか
  2. var appear_block = new Array();
  3. //ブロックの残数
  4. var block_count   = 0;

ブロック生成部に追加

  1. //ブロックが存在するかどうか
  2. appear_block[i * 8 + j] = true;
  3. block_count++;

その後、以下の処理をその他内に記載して下さい。

  1. for (var i = 0; i < spr_block.length; i++) {
  2.   if (contactA == spr_block[i] || contactB == spr_block[i]) {
  3.     layer.removeChild(spr_block[i]);
  4.     //gamestart対処 Start
  5.     //ブロックの数マイナス
  6.     appear_block[i] = false;
  7.     block_count–;
  8.     //破壊する
  9.     //layer.removeChild(spr_block[i]);
  10.     setTimeout(function () {world.DestroyBody(body_block[i]);}, 1);
  11.     break;
  12.   }
  13. }

これにより、ブロック崩しとして一通りの動作が可能になりました。
しかし現在の状態では、初回の弾を発射後でもクリックをすると
ボールの物理オブジェクトが生成されてしまいます。
それを防ぐため、次の処理を追記します。

var ball_moved   = false;
※グローバル変数に追加

上記変数を追加後
onTouchesEnded関数内の処理を以下のように変更します。

  1. if (ball_moved == false) {
  2. var size = cc.Director.getInstance().getWinSize();
  3. body_ball = this.addNewSpriteWithCoords(spr_ball, cc.p( size.width / 2 – 5, BAR_Y + BAR_HEIGHT / 2 + BALL_HEIGHT / 2 ), BALL_WIDTH, BALL_HEIGHT, true);
  4. var b2Vec2 = Box2D.Common.Math.b2Vec2;
  5. //弾の発射角度を調整 Start
  6. var ball_angle_work = Math.random() * 40;
  7. if (ball_angle_work < 20) {
  8.    ball_angle_work = -1 * ball_angle_work – 20;
  9. } else {
  10.    ball_angle_work = ball_angle_work;
  11. }
  12. ball_angle = ball_angle_work / 180;
  13. body_ball.SetLinearVelocity(new b2Vec2(-1 * ball_velocity * Math.sin(ball_angle), ball_velocity * Math.cos(ball_angle)));
  14. ball_moved = true;
  15. }

※上記の太字箇所を追加

以上で、本記事は終了となります。

今回の処理を追記したソースコードはこちら

<次回以降の更新について>
次回は、プレイヤーの残機設定や速度調整等の細かな部分の修正や追加について、
引き続き説明していきます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*