이전 글에서는 공 하나가 화면 안에서 생각없이 튕기는 내용이었다.

 

 

Javascript 캔버스에서 움직이는 공 그리기

유튜브에서 브라우저에서 각종 도형의 움직임을 Javascript로 구현하는 걸 보고 반해서 바로 공부를 시작. 이제서야 조금씩 머리속에서 그림이 그려져가고 있다. bouncing-ball-3.bryanko555.repl.co 이건 그

mrkool.tistory.com

이번에는 컴퓨터의 강점을 살려, 공의 갯수를 확 늘리게되면 이제 좀 볼만해진다.

이전에는 ball 클래스를 만들어놓고 공을 하나만 만들었었는데, 이번에는 초기화 함수, init()에서 공을 여러개 생성하고,

animate() 함수에서 그 공들을 매 순간 업데이트 할 때마다 계산해준다.

 

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.8)'; // 전체 화면 지우기. 하얀색의 alpha값을 변경함에 따라 공의 잔상이 달라진다.

   ctx.fillRect(0,0,canvas.width,canvas.height);

   for(i=0;i<ballNumber;i++){

      balls[i].update();

      balls[i].draw();

    }

}

 

위 데모에서는 30개의 공을 그렸는데, requestAnimationFrame()이 1초에 60번 동작하고, 그 때마다 30개 공의 좌표를 이동시키고 그림을 그리고 벽에 닿았는지 판단해준다. 문돌이에게는 놀라운 일이다. ㅎ

 

다양성을 주기 위해서 각 공마다 랜덤 특성을 부여했다.

시작할때 공이 랜덤한 방향으로 날라가고,

    this.angle = (Math.random()*(Math.PI*2));

공의 색깔이 랜덤하게 생성되고, 

    this.c = 'rgba('+Math.random()*255+','+Math.random()*255+','+Math.random()*255+')';

공의 크기를 다르게 하고,

    this.size = 10+Math.random()*20;

공이 날라가는 속도를 다르게 했다. 

    

this.power = Math.random()*3+2;

 

아예 공의 수를 200개로...

 

이 공이 움직이는 것처럼 보이는 이유가, 매 프레임마다 캔버스 전체를 하얀색 상자를 그려서 덮어버리고 각 공들을 이동한 좌표로 그려주고, 다음 프레임에서 다시 다 지우고, 공들을 다시 그리고 ... 이렇게 반복함으로써 공들이 움직이는 것처럼 보이는 것인데...

캔버스를 덮을 하얀색의 투명도(alpha값)을 다르게 함에 따라서 공의 궤적을 다르게 볼 수 있다.

alpha =1 

alpha = 0.5

alpha = 0.1

 

전체 코드 :

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 = 20;
 
  class Ball{
    constructor(x,y){ // ball의 기본 속성들을 정의 
      this.x = x;
      this.y = y;
      this.c = 'rgba('+Math.random()*255+','+Math.random()*255+','+Math.random()*255+')'// 공의 색깔을 random으로 설정
      this.size = 10+Math.random()*20;
      this.angle = (Math.random()*(Math.PI*2));
      this.power = Math.random()*3+2;
      this.directionX = this.power * Math.cos(this.angle);
      this.directionY = this.power * Math.sin(this.angle);
    }
    update(){ // 프레임마다 속성들을 변화시킴 
      this.y += this.directionY; 
      this.x += this.directionX;
      if(this.y+this.size>canvas.height || this.y-this.size<0){ // 바운드 처리
        this.directionY *= -1;
        }
      if(this.x>canvas.width-this.size ) {
        this.x = canvas.width-this.size;
        this.directionX *= -1;
      } else if (this.x-this.size < 0){
        this.directionX *= -1;
      }
    }
    draw(){ // 넘어온 속성값대로 캔버스에 그림을 그려줌
       ctx.fillStyle= this.c;
       ctx.beginPath();
       ctx.arc(this.x, this.y, this.size, 0, Math.PI*2true);
       ctx.closePath();
       ctx.fill();
       ctx.lineWidth = 2;
       ctx.strokeStyle= 'black';
       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.1)'// 전체 화면 지우기. 하얀색의 alpha값을 변경함에 따라 공의 잔상이 달라진다.
    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

다음에는 중력까지 가미해보자.

 

 

자바스크립트를 깨우치다:객체로 풀어보는 JavaScript의 원리

COUPANG

www.coupang.com

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받을 수 있습니다.

+ Recent posts