캔버스를 일주일 넘게 배우고 있는데 캔버스가 정말 재미있는 것 같아요. Canvas를 배우는 사람들은 아마도 나와 비슷한 생각을 가지고 있을 것이다. 그들은 게임을 쓰는 자세로 Canvas를 배운다. 따라서 운동학, 충돌 감지 및 몇 가지 간단한 알고리즘이 기본입니다. 게임을 한번도 만들어본 적이 없어서 배우기가 정말 어려웠습니다. 오늘은 캔버스를 사용하여 가장 간단한 중력 및 충돌 감지 기능을 사용하여 가장 간단한 탄력 있는 볼 게임을 작성하는 방법에 대해 이야기하겠습니다.
먼저 DEMO로 이동합니다. 탄력 있는 공 DEMO (캔버스의 빈 영역을 클릭하면 공의 속도가 달라집니다.)
【공 객체 생성】
첫 번째 단계는 공 개체를 만들고 공의 생성자를 작성하는 것입니다.
공의 속성은 매우 간단합니다. xy는 공의 좌표이고, vx와 vy는 공의 초기 수평 속도와 초기 수직 속도입니다. radius는 공의 반경, color는 공의 색상(다른 공을 구별하기 위해), oldx 및 oldy는 이전 프레임에서 공의 위치를 기록하고 공 간의 충돌 후 위치 수정에 사용됩니다. 나중에는 (실제로는 쓸모가 없음) 위에서는 위치보정을 직접 계산하는데, oldx를 이용해서 설정하면 굉장히 느슨해지겠지만, 기록을 하면 필연적으로 사용하게 된다.
공의 속성을 작성한 후 공 프로토타입에 공의 동작을 작성합니다.
if(Math.abs(this.vx) < 0.01){
this.vx = 0;
}
else this.vx = this.vx>0? mocali*t : mocali*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();
},
}
공을 움직이는 방법은 두 가지뿐입니다. 첫 번째 방법은 직접 그리는 것이고, 두 번째 방법은 공의 움직임을 제어하는 것입니다. t는 현재 프레임과 이전 프레임 사이의 시간 차이입니다. 공의 변위 증분을 얻기 위해 공 속도의 증분을 계산하는 데 사용되며, 이를 통해 공의 새로운 위치를 계산하고 공을 다시 그립니다. 새로운 위치가 얻어지면 공의 새로운 위치가 벽을 초과하는지 여부도 판단됩니다. 이를 초과하면 공이 리바운드될 수 있도록 속도가 수정됩니다.
두 번째 방법의 일부 상수 ballRadius =30, g = 9.8, mocali = 0.5, ball = [], collarg = 0.8, pxpm = canvas.width/20 의미는 분명합니다. ballradius는 공의 반경입니다. , g는 중력 가속도, mocali는 공기 저항에 의한 수평 감속도, ball은 작은 공 물체를 저장하는 데 사용되는 배열, 콜라겐은 탄성 계수입니다. 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;
//두 볼의 비스듬한 절단 위치를 구하고 강제로 비틀기
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;
}
}
}
}
}
구체적인 원리에 대해서는 다루지 않겠습니다. 원리를 알고 싶다면 작은 공 충돌의 알고리즘 설계를 클릭하세요. 다음 문단은 반복되는 충돌 감지로 인해 공이 정상적으로 튕겨 나가는 것을 방지하기 위한 것이므로, 두 공의 중심 사이의 거리를 계산한 후, 두 공의 경사 위치를 계산하고, 공의 위치를 구한다. 두 개의 공이 수정되었습니다.
【모션 애니메이션】
마지막 단계:
canvas.onclick = function(event){
event = event || window.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;
});
}
함수 애니메이션(){
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;
충돌();
balls.forEach(function(){
this.run (t);
});
t0 = t1;
if(창의 "requestAnimationFrame"){
requestAnimationFrame(animate);
}
else if(창의 "webkitRequestAnimationFrame"){
webkitRequestAnimationFrame(animate);
}
else if(창의 "msRequestAnimationFrame"){
msRequestAnimationFrame(animate);
}
else if(창의 "mozRequestAnimationFrame"){
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