demo
GitHubにも公開してあります。
GitHub - naoyashiga/BreakBrick: using Paper.js
このブロック崩しを作るのが簡単である理由
ゲーム終了がない
ゲーム終了処理を作るのが面倒だったので、下に壁を作りました。下に壁があるためゲームオーバーになりません!!
開始、終了画面がない
いきなり始まります。終了もしないので、レンガ(ブロック)がすべてなくなっても終了しません。自ら終わる必要があります。
当たり判定が適当
後述しますが、弾丸の下辺中央座標がプレイヤー(操作バー)に当たると跳ね返ります。だからプレイヤーの角が弾丸の左端に当たっても、跳ね返りません。厳密な当たり判定は難しいと思ったので、簡単に書いてます。
使用したライブラリ
Canvasに簡単に描画するためにPaper.jsを使っています。
http://paperjs.org/
ですので、タイトルには「Javascript」と書いてありますが、正確にはJavascriptの拡張版「PaperScript」を使用しています。canvasを用いて、ベクターグラフィックをjsを簡単に描画できるようにしたライブラリです。
Paper.jsについては詳しくはこちらを見てください。
Paper.jsで使うPaperScriptの特徴と、直接Javascriptで実行するときの違い - not good but great
コード解説
以下に書いたコードについて説明していこうと思います。
レンガ
レンガを作成
//レンガを作成 var brick = new Rectangle(); brick.size = new Size(brickWidth, brickHeight); //レンガのパス var path = new Path.Rectangle(brick); path.fillColor = '#444';
RectangleにSizeを指定して長方形を作成します。その長方形をパスに渡して、パスを作成します。
長方形やその他の図形の作り方はこちらを参照して下さい。
Paper.jsで長方形、円、角丸、多角形を描いてみる - not good but great
シンボル化
//レンガをシンボル化 var symbol = new Symbol(path);
同じ形のレンガを一つずつ作成するのはメモリを無駄に使います。メモリ節約のためにシンボル化します。
シンボルについてはこちらを参照して下さい。
Paper.jsでアイテムをたくさん複製したい時はSymbolを使おう - not good but great
レンガを並べる
//レンガを並べる for(var y = 0;y < rows;y++){ for(var x = 0;x < cols;x++){ var center = new Point(x, y) * [brick.size.width + xMargin,brick.size.height + yMargin]; var placedSymbol = symbol.place(center); } }
symbol.placeで位置を指定すれば、どんどんシンボルが複製されていきます。
レンガを移動
//レンガのレイヤーを中央に移動 project.activeLayer.position = [view.size.width / 2,view.size.height / 4];
レンガのレイヤーごと一気に移動させます。
レイヤー構成
/*----------------------------------- レイヤー構成 -レイヤー0 --レンガ -レイヤー1 --弾丸 --プレイヤー -----------------------------------*/ //レイヤー1を新規作成 var secondLayer = new Layer(); //レイヤー0のレンガを取得 var brickChildren = project.layers[0].children;
レンガ、弾丸、プレイヤーを扱いやすくするために、レイヤーに分けます。
レイヤーについてはこちらを参照して下さい。
Paper.jsでレイヤーの細かい指定、グループ化をやってみる - not good but great
弾丸
/*----------------------------------- 弾丸 -----------------------------------*/ var bullet = new Path.Circle({ center:[view.size.width / 2,view.size.height - 50], radius:bulletRadius, fillColor:"#f39c12" });
弾丸は円で描画します。一つしかないのでシンボルにはしません。
プレイヤー
/*----------------------------------- プレイヤー(バー) -----------------------------------*/ var playerRect = new Rectangle(); playerRect.size = new Size(100, 10); playerRect.center = new Point(view.size.width / 2,view.size.height - 50); var player = new Path.Rectangle(playerRect); player.fillColor = '#444';
プレイヤー(操作バー)を長方形で描画します。
プレイヤーを動かす
/*----------------------------------- マウスの動きに合わせてプレイヤーが移動 -----------------------------------*/ function onMouseMove(event){ player.position.x = event.point.x; //垂直方向の壁 if(player.bounds.left < 0){//左の壁 player.position.x = player.bounds.width / 2; }else if(player.bounds.right > view.size.width){//右の壁 player.position.x = view.size.width - player.bounds.width / 2; } }
onMouseMoveはPaper.jsに始めから用意されている関数です。
長方形の細かい位置を取得
playerは長方形となります。長方形の角の座標を取得するにはboundsが便利です。
center
topLeft
topRight
bottomLeft
bottomRight
leftCenter
topCenter
rightCenter
bottomCenter
上のように左端、右端、下辺の中央など細かい座標を取ることが出来ます。
当たり判定
//プレイヤーに対する弾丸の当たり判定 var hitResult = player.hitTest(bullet.bounds.bottomCenter); if(hitResult){ if(hitResult.type == "fill"){ //跳ね返る vy *= -1; } }
プレイヤーに対する弾丸の当たり判定のコードになります。前述の通り、boundsを使い下辺の中央座標を取得します。当たり判定にはhitTestを使用します。指定した下辺の中央座標がplayerに当たったら、trueを返します。細かい当たり判定を考えると、下辺の中央座標を当たり判定に使うのは違うとは思いますが、そこまでは今回は考慮しないことにします。
当たり判定についての以前書いたエントリはこちらになります。
当たり判定をしてドラッグでアンカーポイントを動かす - not good but great
これからの展望
やっぱり音がないと楽しくありませんね笑。WebAudioで効果音とか作れないんですかね。