지난 글에서 여러 공들이 화면 안에서 튕기게 만들었는데, 이제 여기다가 중력을 가미해보자.
이 공들에 중력이 더해지면 아래와 같이 실제와 비슷한 운동을 보인다.
대부분 동일하고, 프레임마다 다르게 그려주는 update()함수에 가속도 요소를 넣어준다.
update(){ // 프레임마다 속성들을 변화시킴
this.y += this.weight; // y방향 움직임을 무게로 가정해서 설정
this.x += this.directionX;
this.weight += 0.1; // 프레임마다 떨어질때의 가속도 증가
this.directionX *= 0.997; // 가로방향 속도 감소. 가장 자연스러운 움직임을 보이는 수치로 찾은 값
if(this.y+this.size>canvas.height || this.y-this.size<0){ // 세로 방향 바운드 처리
this.weight *= -0.8; // y 방향을 바꿔주면서 점차 바운스가 감소하게
if(Math.abs(this.weight)<0.9){this.y = canvas.height-this.size; // 바운드가 어느 정도 이하가 되면 더 이상 바운드 안하게, 즉, 바닥에 붙게 한다.
this.weight =1;} else { this.y -=1 ;} //
};
if(this.x>canvas.width-this.size || this.x-this.size < 0 ) { // 가로 방향 바운드 처리
this.directionX *= -1; // x 방향 전환.
}
}
전체 코드 :
window.onload = function () {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth-15;
canvas.height = window.innerHeight-15;
balls=[];
ballNumber = 50;
class Ball{
constructor(x,y){ // ball의 기본 속성들을 정의
this.x = x;
this.y = y;
this.c = 'rgba('+Math.random()*255+','+Math.random()*255+','+Math.random()*255+')';
this.size = Math.random()*10+5;
this.angle = (Math.random()*360)*((Math.PI*2)/360);
this.power = Math.random()*3+2;
this.directionX = this.power * Math.cos(this.angle);
this.weight = this.power * Math.sin(this.angle);
}
update(){ // 프레임마다 속성들을 변화시킴
this.y += this.weight;
this.x += this.directionX;
this.weight += 0.1; // 프레임마다 떨어질때의 가속도 증가
this.directionX *= 0.997; // 가로방향 속도 감소.
if(this.y+this.size>canvas.height || this.y-this.size<0){ // 세로 방향 바운드 처리
this.weight *= -0.8; // y 방향을 바꿔주면서 점차 바운스가 감소하게
if(Math.abs(this.weight)<0.9){this.y = canvas.height-this.size; // 바운드가 어느 정도 이하가 되면 더 이상 바운드 안하게, 즉, 바닥에 붙게 한다.
this.weight =1;} else { this.y -=1 ;} //
};
if(this.x>canvas.width-this.size || this.x-this.size < 0 ) { // 가로 방향 바운드 처리
this.directionX *= -1; // x 방향 전환.
}
}
draw(){ // 넘어온 속성값대로 캔버스에 그림을 그려줌
ctx.fillStyle= this.c;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
ctx.strokeStyle = 'black';
ctx.strokeWidth = 4;
ctx.stroke();
}
}
function init(){
for(i=0;i<ballNumber;i++){
balls[i] = new Ball(canvas.width*0.5, canvas.height*0.5)
}
}
function animate(){ // 매 프레임마다 벌어지는 일들
ctx.fillStyle='rgba(255,255,255,0.51)';
ctx.fillRect(0,0,canvas.width,canvas.height);
for(i=0;i<ballNumber;i++){
balls[i].update();
balls[i].draw();
}
window.addEventListener('resize',function(){ // 화면 크기가 변하면 캔버스 크기도 변경해줌
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
})
requestAnimationFrame(animate);
}
init();
animate();
}
|
cs |
여기다가 좀 변화를 줘서, 공들을 360도 회전하면서 발사되게 해봤다.
공이 한꺼번에 생성되는 것이 아니라, 하나씩 생성되서 발사되야 하기 때문에 setInterval로 시간 간격을 두면서 공을 생성해야 한다. requestAnimationFrame으로는 공들이 순식간에 생성되서 그냥 동시에 터지는 것처럼 보인다.
setInterval이 호출될 때마다 공을 한개씩 생성한다.그리고 생성된 공이 시계방향으로 돌아가면서 발사되야하기 때문에, 공(ball)의 속성에 각도(angle)를 추가했다.
class Ball{
constructor(x,y,angle){ // ball의 기본 속성들을 정의
:
}
function init(){
if(num < ballNumber){ num++;} // 호출될 때마다 공을 1개씩 생성한다.
balls[num] = new Ball(canvas.width*0.5, canvas.height*0.5, Math.PI*2/360 + i) // 각도를 순차적으로 증가시키면서 공을 생성한다.
}
setInterval(init,100);
오늘은 여기까지....
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받을 수 있습니다.
'문과생의 coding' 카테고리의 다른 글
Javascript 오목 게임 만들기 (3) | 2021.02.20 |
---|---|
Javascript 마우스 드래그한 방향으로 공 날리기 (0) | 2021.02.13 |
Javascript 캔버스에서 튕기는 공들 (w/o 중력) (0) | 2021.02.07 |
Javascript 캔버스에서 튕기는 공 w 중력 (0) | 2021.01.10 |
Javascript 캔버스에서 움직이는 공 그리기 (0) | 2020.12.26 |