私は長い間 Canvas を使っていなかったので、小さなゲームの Tetris を書くことで再び Canvas に慣れました。ある程度の Canvas の基礎があれば、実装するのは難しくありません。
原理を詳しく解説ゲームの最終的なインターフェイスを見ると、次の主要な機能を実装する必要があることがわかります。
パネル全体は、左上隅(0,0)を原点とし、右上隅(12,0)、左下隅(0,20)、右下隅(12,20)の座標系です。 )各点の座標位置を決定できます。正方形が塗りつぶされているかどうかに関係なく、各正方形は配列要素として考えることができます。0 は塗りつぶされていないことを意味し、1 は塗りつぶされていることを意味します。 12 * 20 パネルは 2 つの配列層を使用します。つまり、長さ 12 の 20 個の配列が実装されます。
var マップ = [[0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,1,0 ,1,0], ...];
パネルを描画するコードは、最も基本的なキャンバス API を使用して実装できます。
//グリッド for(var i=0;i<12;i++){ for(var j=0;j<20;j++){ ctx.fillRect(i*40,j*40,40,40); strokeRect(i*40,j*40,40,40); if(this.maps[j][i]==1){//四角形はコンテンツで埋められました ctx.save(); ctx.lineWidth=4; ctx.fillStyle='hsla(200,100%,50%,.5)'; ctx.drawingStyle='hsla(200,100%,50%,.9)'; j*40,40,40); ctx.ストロークRect(i*40+2,j*40+2,38,38); ctx.restore() } } } //ボーダー ctx.ストロークスタイル='hsla(0,100%,0) %,.3)'; ctx.moveTo(0,0); ctx.lineTo(12*40,20*40);ブロックの実装
ゲーム内で使用されているグラフィックは以下の7種類です
上で紹介した座標系と組み合わせると、配列 [x1, y1, x2, y2, x3, y3, x4, y4] は、上のグラフィックの 4 つの点の座標のデータ表現になります。 7 つのグラフィックの座標は次のようになります。次のように:
変数配列 = [[4,0,4,1,5,1,6,1],[4,1,5,1,6,1,6,0],[4,0,5,0,5,1, 6,1],[4,1,5,0, 5,1,6,0]、[5,0,4,1,5,1,6,1]、[4,0,5,0,6,0,7,0]、[5,0, 6,0,5,1,6,1]];
ブロックを移動するには、配列全体を走査して変位ベクトルを追加するだけです。これは非常に簡単です。
class Shape {constructor(m){ this.m = Object.assign([],m); } move(x,y){ // 変位 var m = this.m, l = m.length| |0; for (var i=0;i<l;i=i+2){ m[i]+=x; }
ブロックの回転。 テトリスでは、上下左右に移動するだけでなく、ブロックも回転しますよね。少し考えれば、これは単なる行列変換、つまり図形が中心点を中心に 90 度回転するたびに行われることがわかります。配列内の 3 番目の点をグラフィックス変換の中心点として使用します。もちろん、この処理は完璧ではありません。
class Shape {transform(){//2 次元行列変換 var m =this.m, l = m.length, c = Math.ceil(l/2), x = m[c], y = m[c+ 1]、cos = Math.cos(Math.PI/180 * 90)、sin = Math.sin(Math.PI/180 * 90); for (var i=0;i<l;i=i+2) { if(i == c) 続行; var mx = m[i]- x、my = m[i+1] - y、nx = mx*cos - my*sin、ny = my*cos + mx*sin; m[i]=x+nx; m[i+1]=y+ny; }境界条件
主に以下の3つの側面が含まれます
配列を走査します (1) 任意の点の y 座標が 19 の場合は、その点が最下位に到達したことを意味します。 (2) マップ内の座標の y+1 位置に関する情報を取得します。それが 1 の場合、それは意味します。埋まってしまいました。どちらの場合も、移動ブロックの期間が終了したら、マップに対応する配列にブロックの座標を埋めるだけです。
座標の y+1 が埋められていて、現在の座標が 1 未満の場合、つまり、座標がすでにインターフェイスの上部にある場合、ゲームは終了です。
var isEnd = false,isOver=false,x,y;for(var i=0,sl=that.shape.m.length;i<sl;i=i+2){ x=that.shape.m[i ]; y=that.shape.m[i+1]; if(y >= 19){ // 一番下はEnd = true;break; 1 ){ // y+1 の位置が埋められました isEnd = true; if(y <= 1){isOver=true;} // ゲームは終了しました }}
ブロック移動サイクルの最後に、各層がいっぱいであるかどうかがチェックされ、正方形以降の処理がいっぱいになります。特定の配列のすべての要素が 1 の場合、グリッドがいっぱいであることを意味します。次に、その配列を削除し、同時に各要素が 0 の配列をリストの先頭にプッシュします。
checkPoint(){ var that = this,maps = that.maps; for(var i=0,l=maps.length;i<l;i++){ if(Math.min.apply(null,maps[i]) == 1){// レイヤーがいっぱいであることを示します that.maps.splice(i,1); //スコアを増やします。 that.maps.unshift([0,0,0,0,0,0,0,0,0,0,0,0]);バインドイベント
重要なのは、keydown イベントをバインドすることです。左シフト イベントと右シフト イベントには境界判定が含まれることに注意してください。
bindingEvent(){ var that = this; document.addEventListener('keydown',function(e){ switch(e.keyCode){ case 13: //cancelAnimationFrame(that.timer); that.init().update( ); ケース 80: //p that.pause = !that.pause; case 40: //down that.d = 0.5; //左 var over = false、maps = that.maps、shape = that.shape、m =shape.m; for(var i=0,l=m.length;i<l;i=i+2){ if(m[i]<=0 || マップ[m[i+1]][m[i]-1] == 1){ over = true;break } } if(!over)shape.move( -1,0); 39: //右 var over = false、shape = that.shape、maps = that.maps、m =shape.m; for(var i=0,l=m.length;i<l;i=i+2 ){ if(m[i]>=11 || マップ[m[i+1]][m[i]+1] == 1){ over = true;break; } if(!over) 形状。移動(1,0); case 32: //スペース that.shape.transform() } },false);}要約する
ここではテトリスの最も基本的な機能が実装されていますが、レベルなどの機能的な点は実装されていません。同時に、デモにはまだ修正が必要な不完全な点があります。
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。