LOL의 미스포츈의 궁처럼 공을 날려 보내봐야겠다.
결과물은 아래와 같다.
deuraegeuhan-banghyangeuro-gong-ssogi-p5js.bryanko555.repl.co
이번에는 p5.js를 써봤다.
내가 경험한 바로 말하면, p5.js는 그래픽에 도움되는 여러 Javascript명령을 손쉽게 구현할 수 있는 명령으로 대신할 수 있게 해준다.
예를 들어, 아래와 같은 식이다.
vanila Javascript 원 그리기 | p5.js 원 그리기 |
ctx.beginPath(); ctx.arc(x좌표,y좌표,반지름,0,Math.PI*2) ctx.stroke(); |
circle(x좌표,y좌표,반지름); |
p5.js를 사용하더라도 Javascript의 기본 개념은 변함 없다.
p5.js를 사용하려면, html 첫 머리에 코드를 삽입해준다.
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js"></script>
위와 같이 공을 날리기 위해서 필요한 요소들이다.
- 드래그 시작점
- 드래그 종료점
- 시작점과 종료점의 거리 (이 거리의 길이를 공의 속도로 사용했다)
- 시작점과 종료점의 각도 (이 각도를 중심으로 공이 랜덤하게 날라간다)
- 공이 이동할 때의 x,y 변경 값
드래그 시작점과 종료점은 마우스가 눌려졌을 때(시작)와 마우스가 놓여졌을때(종료)의 x,y좌표를 기록한다.
// 마우스를 클릭했을 때 x,y 저장
function mousePressed(){
x2 = mouseX;
y2 = mouseY;
};
// 마우스를 뗐을때 x,y 저장하고, 간격을 두고 공을 생성하는 함수 init 호출
function mouseReleased(){
x = mouseX;
y = mouseY;
if(abs(x - x2) <= 20 && abs(y - y2) <= 20){return} // 드래그를 너무 조금했을 때에는 무시
num = 0;
repeat = setInterval(function(){ // 공들이 한번에 다 날아가지 않도록 약간씩 시차를 두고 생성시켜준다.
init(x,y);},100);
draw(); // 애니메이션을 구현할 함수를 호출
};
위의 마우스 관련 함수들도 p5.js로 간단히 구현했다.
그리고, 드래그 하는 동안에 직선을 그려줘야하니까,
// 드래그할 때 붉은 선 그리기
function mouseDragged(){ // 마우스 버튼이 눌린 상태에서 움직일 때마다 한 번씩 호출
stroke("red");
strokeWeight(5);
line(x2, y2, mouseX, mouseY);
};
공들을 생성하는 함수.
공들이 날아가는 각종 속성을 정하기 때문에 가장 중요하겠다.
function init(x,y){ // 공을 하나씩 생성하고 속성 부여
p = sqrt(pow((x2-x),2) + pow((y2-y),2));
radian = atan2((x2-x),(y2-y));
dx = (p *sin(radian + ((random(20)-10)*PI/180))*0.05) ;
dy = (p * cos(radian + ((random(20)-10)*PI/180))*0.05) ;
c = 'rgb('+floor(random(255))+','+floor(random(255))+','+floor(random(255))+')';
balls[num] = new Ball(x, y, x2, y2, dx, dy, p, c)
if(num<ballNumber){num++} else {
clearInterval(repeat); // 공이 지정 숫자만큼 생성됬으면, init() 함수 호출을 중지.
} ;
}
위에서 dx,dy가 공들을 이동하는 x,y의 변화값인데,
아래 그림의 c에다가 각도에서 랜덤하게 차이를 두고, 거기서 cos,sin을적용해서 dx,dy를 구했다.
a = c * cos(각도)
b = c * sin(각도)
물론 a = x - x2 , b = y - y2 로도 구할 수 있지만, 랜덤한 각도로 발사가 되어야 해서, 빙~ 돌아서 값을 구했다. (뭔가 더 좋은 방법이 있을 것 같기는 하다. ㅡㅡa)
마우스를 떼면 draw()함수를 실행시키는데, p5.js에서는 draw() 함수는 requestAnimationFrame이 없어도 기본적으로 프레임마다 호출되어 실행된다.
짧게 드래그 했을 때 | 길게 드래그 했을 때 |
전체코드 (HTML)
<div id="inputArea">
<label for="ballNumberInput">공 갯수 : </label>
<input type="text" id='inputBallNumber' name='ballNumberInput' size='3' value="10" onkeyup="setup()">
</div>
<div id="msg">마우스를 왼쪽클릭 후 드래그 했다가 놓으세요<br> 드래그 한 길이가 날라가는 힘이 됩니다.</div>
</body>
|
cs |
전체코드 ( Javascript)
function setup() {
createCanvas(windowWidth,windowHeight);
background('white');
num = 0;
ballNumber = document.querySelector('#inputBallNumber').value;
balls = [];
radius = 30;
}
class Ball {
constructor(x,y,x2,y2,dx,dy,power,color){
this.x = x; // 공이 발사되는 x
this.y = y; // 공이 발사되는 y
this.x2 = x2; // 드래그 시작점 x
this.y2 = y2; // 드래그 시작점 y
this.dx = dx; // 공이 이동하는 x 크기
this.dy = dy; // 공이 이동하는 y 크기
this.p = power; //마우스를 드래그한 길이, 공이 날라가는 힘(속도),
this.c = color; // 공 색깔
}
update(){ // 공을 변화값만큼 이동
this.x = this.x + this.dx;
this.y = this.y + this.dy;
}
drawBall(){ // 프레임마다 변경된 위치로 공을 그려줌
fill(this.c);
stroke('black');
strokeWeight(2);
circle(this.x , this.y, radius);
}
}
function draw(){
fill("rgba(255,255,255,0.8)");
rect(0, 0, canvas.width, canvas.height);
stroke('black');
strokeWeight(2);
for (i =0; i < num; i++) {
balls[i].update();
fill(balls[i].c);
circle(balls[i].x, balls[i].y, radius);
if (balls[num-1].x+radius*2 < 0 || balls[num-1].x - radius*2 > canvas.width || balls[num-1].y + radius*2 < 0 || balls[num-1] - radius*2 > canvas.height) {
return; // 마지막 공이 완전히 캔버스 밖으로 나가면 공 그리기 종료,
}
}
}
function init(x,y){ // 공을 하나씩 생성하고 속성 부여
p = sqrt(pow((x2-x),2) + pow((y2-y),2));
radian = atan2((x2-x),(y2-y));
dx = (p *sin(radian + ((random(20)-10)*PI/180))*0.05) ;
dy = (p * cos(radian + ((random(20)-10)*PI/180))*0.05) ;
c = 'rgb('+floor(random(255))+','+floor(random(255))+','+floor(random(255))+')';
balls[num] = new Ball(x, y, x2, y2, dx, dy, p, c)
if(num<ballNumber){num++} else {
clearInterval(repeat);
} ;
}
// 마우스를 클릭했을 때 x,y 저장
function mousePressed(){
x2 = mouseX;
y2 = mouseY;
print(mouseIsPressed)
};
// 드래그할 때 붉은 선 그리기
function mouseDragged(){ // 마우스 버튼이 눌린 상태에서 움직일 때마다 한 번씩 호출
stroke("red");
strokeWeight(5);
line(x2, y2, mouseX, mouseY);
};
// 마우스를 뗐을때 x,y 저장하고, 간격을 두고 공을 생성하는 함수 init 호출
function mouseReleased(){
x = mouseX;
y = mouseY;
if(abs(x - x2) <= 20 && abs(y - y2) <= 20){return} // 드래그를 너무 조금했을 때에는 무시
num = 0;
repeat = setInterval(function(){
init(x,y);},100);
draw();
};
|
cs |
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받을 수 있습니다.
'문과생의 coding' 카테고리의 다른 글
Javascript 리버시(Reversi) 게임 만들기 (0) | 2022.04.24 |
---|---|
Javascript 오목 게임 만들기 (3) | 2021.02.20 |
Javascript 캔버스에서 튕기는 공들 (w 중력) (0) | 2021.02.08 |
Javascript 캔버스에서 튕기는 공들 (w/o 중력) (0) | 2021.02.07 |
Javascript 캔버스에서 튕기는 공 w 중력 (0) | 2021.01.10 |