ボールとブロックの当たり判定
ブロックが表示できたら、ゲームに必要な当たり判定の処理を追加します。スカッシュではパドルとボールの衝突を判定するだけでしたが、ブロック崩しの場合はボールとすべてのブロックとの衝突も判定する必要があります。
判定にはパドルとボールの処理と同様にintersect()メソッドを使い、for文を使ってブロックの数だけ当たり繰り返します。ブロックとボールが当たっている場合はブロックのY座標を-9999に設定してブロックを非表示にします。-9999は画面に表示されない座標値であれば何でも構いません。この方法なら、ブロックを削除したり、ブロックの有無を示すフラグを用意したりせずに済みます。
ブロックとボールが当たったらスコアに5点を加算し、すべての当たり判定が終わった後にラベルのtextプロパティにスコアを設定します。
最後に、ブロックの総数を示す変数totalから1を引き、totalが0になったら再度ブロックを描画してゲームを継続させます。
function hitCheck_block_ball(){
for(var i=0; i<count; i++){
if (ball.intersect(block[i])){
ball.dy = -ball.dy; // 接触した場合はボールのY方向の移動量を逆にする
block[i].y = -9999; // 見えない場所に移動
game.score = game.score + 5; // スコアを加算(5点)
total = total - 1; // 総ブロック数から1を引く
if (total < 1){ // 全部消したか調べる
drawBlock(); // ブロックを再描画
}
}
}
scoreLabel.text = "SCORE : "+game.score;
}
以上でブロック崩しの基本的なプログラムができあがりました。実際のプログラムがサンプル3です。なお、今回はフレームレートを60に設定していますので、前回のスカッシュと比べてボールやパドルがスムーズに移動します。
■サンプル3
enchant(); // ライブラリーの初期化
window.onload = function(){
var game = new Game(240, 320); // 240×320画面(Canvas)を作成
game.fps = 60; // フレームレートの設定。60fpsに設定
// 画像データをあらかじめ読み込ませる
game.preload("images/pad.png","images/ball.png", "images/block.png");
game.rootScene.backgroundColor = "blue"; // ゲームの背景色を青色に設定
game.score = 0; // スコアを入れる変数を用意する
// スコアを表示するラベルを作成
var scoreLabel = new Label("SCORE : 0");
scoreLabel.font = "16px Tahoma";
scoreLabel.color = "white";
scoreLabel.x = 10; // X座標
scoreLabel.y = 5; // Y座標
game.rootScene.addChild(scoreLabel);
// ブロックの総数を入れるカウンタ変数
var count = 0;
// ブロックを格納する配列
var block = new Array();
// 消したブロックの総数を入れる変数
var total = 0;
// データの読み込みが完了したら処理
game.onload = function(){
// ボールの設定
var ball = new Sprite(16, 16);
ball.image = game.assets["images/ball.png"];
ball.x = 0; // X座標
ball.y = 130; // Y座標
ball.dx = 1.5; // X方向の移動量
ball.dy = 2.5; // Y方向の移動量
game.rootScene.addChild(ball);
// パドルの設定
var pad = new Sprite(32, 16);
pad.image = game.assets["images/pad.png"];
pad.x = game.width/2; // X座標
pad.y = game.height - 40; // Y座標
game.rootScene.addChild(pad);
// ブロックを描く
drawBlock();
// フレームイベントが発生したら処理
game.rootScene.addEventListener(Event.ENTER_FRAME, function(){
moveBall(); // ボールを移動させる
movePaddle(); // パドルを移動させる(キーボード対応)
hitCheck_paddle_ball(); // パドルとボールの接触判定
hitCheck_block_ball(); // ボールとブロックの接触判定
// =============== 各種処理 ==================
// ------------ ■ボールを移動させる -----------------
function moveBall(){
ball.x = ball.x + ball.dx; // X方向の移動量を加算
ball.y = ball.y + ball.dy; // Y方向の移動量を加算
// 画面外かどうか調べる
if ((ball.x < 0) || (ball.x > (game.width-ball.width))){ ball.dx = -ball.dx; }
if (ball.y < 0){ ball.dy = -ball.dy; }
// ボールが下まで行ったらゲームオーバー
if(ball.y > game.height){
game.stop();
alert("スコアは"+game.score+"点でした");
}
}
// ------------ ■パドルを移動させる -----------------
function movePaddle(){
var n = game.input.analogX / 4;
pad.x = pad.x + n; // パドルを移動
if (pad.x < 0){ pad.x = 0; } // 左端かどうか調べる
if (pad.x > (game.width-pad.width)){ pad.x = game.width-pad.width; } // 右端かどうか調べる
}
// ------------ ■パドルとボールの接触判定を行う -----------------
function hitCheck_paddle_ball(){
if (pad.intersect(ball)){
ball.dy = -ball.dy; // 接触した場合はボールのY方向の移動量を逆にする
ball.y = pad.y - ball.height - 1; // うまく跳ね返るように調整
game.score = game.score + 10; // スコアを加算(10点)
scoreLabel.text = "SCORE : "+game.score;
}
}
// ------------ ■ブロックとボールの接触判定を行う -----------------
function hitCheck_block_ball(){
for(var i=0; i<count; i++){
if (ball.intersect(block[i])){
ball.dy = -ball.dy; // 接触した場合はボールのY方向の移動量を逆にする
block[i].y = -9999; // 見えない場所に移動
game.score = game.score + 5; // スコアを加算(5点)
total = total - 1; // 総ブロック数から1を引く
if (total < 1){ // 全部消したか調べる
drawBlock(); // ブロックを再描画
}
}
}
scoreLabel.text = "SCORE : "+game.score;
}
});
}
// 傾きセンサーを設定(Android/iOS共通)
window.addEventListener("deviceorientation", function(evt){
game.input.analogX = evt.gamma; // 横方向の傾斜角度
}, false);
// ゲーム処理開始
game.start();
// ------------ ブロックを描く -----------------
function drawBlock(){
count = 0; // ブロックの総数を示すカウンタを0にする
// ボールの設定を縦横の数だけ繰り返し生成
for(var y=0; y<5; y++){
for(var x=0; x<7; x++){
block[count] = new Sprite(24, 12);
block[count].image = game.assets["images/block.png"];
block[count].x = x * 32+12; // X座標
block[count].y = y * 18 + 30; // Y座標
game.rootScene.addChild(block[count]);
count = count + 1; // ブロックの総数を示すカウンタを増やす
}
}
total = count; // 消すブロックの総数を変数に入れる
}
}