一週間以上キャンバスを学習していますが、キャンバスは本当に楽しいと思います。 Canvas を学ぶ人はおそらく私と同じような考えを持っており、ゲームを書くという姿勢で Canvas を学習しています。したがって、運動学、衝突検出、およびいくつかの単純なアルゴリズムが基礎となります。これまでゲームを作ったことがなかった私にとって、学ぶのは本当に大変でした。今日は、キャンバスを使用して、最も単純な重力と衝突検出を使用して、最も単純な弾むボール ゲームを作成する方法について説明します。
まずデモに行きましょう: 弾むボールのデモ (キャンバス内の空白領域をクリックすると、ボールに新しい速度が与えられます)
【ボールオブジェクトの作成】
最初のステップは、ボール オブジェクトを作成し、ボールのコンストラクターを記述することです:
ボールの属性は非常に単純です。xy はボールの座標、vx と vy はボールの水平初速度と垂直初速度です。 radius はボールの半径、color はボールの色 (異なるボールを区別するため)、oldx と oldy は前のフレームでのボールの位置を記録し、ボール間の衝突後の位置補正に使用されます。後段で(実際には後で役に立たない) 上記については、oldx を使用して設定すると、位置補正が直接計算されますが、記録すると必然的に使用されます)。
ボールの属性を記述した後、ボールのプロトタイプにボールのアクションを記述します:
if(Math.abs(this.vx) < 0.01){
this.vx = 0;
}
else this.vx = this.vx>0?モカリ*t : モカリ*t;
this.vy = this.vy g * t;
this.x = t * this.vx * pxpm;
this.y = t * this.vy * pxpm;< /p>
if(this.y > Canvas.height - ballRadius || this.y < ballRadius){
this.y = this.y < ballRadius ? : (canvas.height - ballRadius);
this.vy = -this.vy*collarg
}
if(this.x > Canvas.width - ballRadius || this.x < ballRadius){
this.x = this .x < ballRadius ? ballRadius : (canvas.width - ballRadius);
this.derectionX = !this.derectionX;
this.vx = -this.vx*collarg;
}
this .paint();
},
}
ボールを動かす方法は 2 つしかありません。1 つ目は自分で描く方法で、2 つ目はボールの動きをコントロールする方法です。 t は、現在のフレームと前のフレーム間の時間差です。ボールの速度の増分を計算してボールの変位の増分を取得するために使用され、それによってボールの新しい位置を計算し、ボールを再描画します。新しい位置が得られると、ボールの新しい位置が壁を超えるかどうかも判断され、超えた場合にはボールが跳ね返るように速度が修正されます。
2 番目のメソッドの定数 ballRadius =30、g = 9.8、mocali = 0.5、balls = []、collarg = 0.8、pxpm = Canvas.width/20; 意味は明らかです。ballradius はボールの半径です。 、g は重力加速度、mocali は空気抵抗によって生じる水平方向の減速度、ball は小さな球体を格納するために使用される配列、collagen は弾性係数です。 pxpm はピクセルとメートルの間のマッピングであり、キャンバスを幅 20 メートルの領域として扱います。
【衝突検知】
ボール オブジェクトを作成したら、ボール間の衝突の記述を開始します。
//衝突後の速度の増分を取得します
var ax = ((b1.vx - b2.vx)*Math.pow((b1.x - b2.x) , 2) (b1.vy - b2.vy)*(b1.x - b2.x)*(b1.y - b2.y))/Math.pow(rc , 2)
var ay = ((b1.vy - b2.vy) )*Math.pow((b1.y - b2.y) , 2) (b1.vx - b2.vx)*(b1.x - b2.x) (b1.y - b2.y))/Math. pow(rc, 2)
// ボールに新しい速度を与えます
b1.vx = (b1.vx-ax)*collarg;
b1.vy = (b1.vy-ay)*collarg;
b2 .vx = (b2.vx ax)*collarg;
b2.vy = (b2.vy ay)*collarg;
//2 つのボールの斜めの切断位置を取得し、ねじりを加えます
var clength = ((b1.radius b2.radius)-rc)/2;
var cx = clength * (b1 .x-b2 .x)/rc;
var cy = clength * (b1.y-b2.y)/rc;
b1.x = b1.x cx;
b1.y = b1 .y cy;
b2.x = b2.x-cx;
b2.y = b2.y-cy;
}
}
}
}
}
具体的な原理については説明しません。原理を知りたい場合は、小球衝突のアルゴリズム設計 をクリックしてください。 次の段落は、衝突検出が繰り返されることでボールが正常に跳ね返るのを防ぐため、2 つのボールの中心間の距離を計算し、2 つのボールの斜めの位置を計算し、ボールの位置を計算します。 2つのボールが修正されました。
【モーションアニメーション】
最終ステップ:
canvas.onclick = function(event){
event =event ||
var x =event.clientX document.body.scrollLeft document.documentElement.scrollLeft - Canvas.offsetLeft;
var y=event.clientY document.body.scrollTop document.documentElement.scrollTop - Canvas.offsetTop;
balls.forEach(function(){
this.vx = (x - this.x)/20; //初速度 m/s
this.vy = (y - this.y) /20;
});
}
関数 animate(){
ctx.save();
ctx.fillStyle = "rgba(255,255,255,0.2)";
ctx.fillRect(0,0,canvas.width,canvas) .height)
ctx.restore();
// ctx.clearRect(0,0,canvas.width,canvas.height)
var t1 = new Date();
var t = (t1 - t0)/1000;
collision();
balls.forEach(function(){
this.run (t);
});
t0 = t1;
if("requestAnimationFrame" in window){
requestAnimationFrame(animate);
}
else if("webkitRequestAnimationFrame" in window){
webkitRequestAnimationFrame(animate);
}
else if("msRequestAnimationFrame" in window){
msRequestAnimationFrame(animate);
}
else if("mozRequestAnimationFrame" in window){
mozRequestAnimationFrame(animate);
}
}
}
キャンバスをクリックしてボールに初速度を与え、アニメーションの各フレームを実行するために使用される方法がアニメーションです。上記の ctx.fillStyle = "rgba(255,255,255,0.2)"; ctx.fillRect(0,0,canvas.width,canvas.height) は、ボールにゴースト シャドウを追加するものであると思います。それが気に入らない場合は、clearRect を使用して直接クリアしてください。次に、各フレームの時間差を計算し、小ボール配列内の小ボール配列をトラバースして再描画します。次に、衝突検出のための衝突メソッドを追加します。アニメーションは終了しました。
この時点で、ソースコードアドレス:
が書き込まれています。https://github.com/whxaxes/canvas-test/blob/gh-pages/src/Other-demo/shotBall.html