JS 스터디 2주차
객체 구축 연습(Object building practice)
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_building_practice
기본 설정
1. HTML과 CSS, JavaScript로 기본적인 공 애니메이션을 구현
2. 공들이 화면에서 튕기고 충돌 시 색상이 변경
기본 캔버스 설정
우선 제공되는 js를 살펴보면 캔버스의 크기를 브라우저의 전체크기로 설정해주고
난수를 생성, 랜덤 색상을 생성하는 도우미 함수 정의까지는 되어 있는 상태.
난수 생성 함수는 공의 위치, 속도, 색상 등을 무작위로 설정하기 위해 사용된다.
Ball 클래스 정의
우선 공의 속성을 정의해준다.
공의 위치나 속도, 색상, 크기등을 화면에 그리고 업데이트하기 위한 클래스를 하나 만들었다.
// 공 객체 생성 함수
function createBall() {
return {
x: generateRandomNumber(0, canvas.width),
y: generateRandomNumber(0, canvas.height),
dx: generateRandomNumber(-5, 5),
dy: generateRandomNumber(-5, 5),
size: generateRandomNumber(10, 20),
color: generateRandomColor(),
// 공을 그리는 함수
draw: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fillStyle = this.color;
ctx.fill();
},
// 공의 위치를 업데이트하는 함수
update: function() {
if (this.x + this.size > canvas.width || this.x - this.size < 0) {
this.dx = -this.dx;
}
if (this.y + this.size > canvas.height || this.y - this.size < 0) {
this.dy = -this.dy;
}
this.x += this.dx;
this.y += this.dy;
},
// 공이 다른 공과 충돌하는지 확인하는 함수
checkCollision: function(balls) {
balls.forEach(otherBall => {
if (this !== otherBall) {
const dx = this.x - otherBall.x;
const dy = this.y - otherBall.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.size + otherBall.size) {
this.color = generateRandomColor();
otherBall.color = generateRandomColor();
}
}
});
}
};
}
생성자르 만들어 우선 공의 상태를 초기화해준다. (초기 상태)
x.y 로 공의 위치를 나타내주고 velx, vely는 공의 수평수직 상태로 이동방향 및 속도를 정의한다.
이후 draw메서드를 통해서 공의 색상, 공의 중심위치를 정해 원을 그리고 해당 색으로 공을 화면 그린다.
update메서드를 통해 계속적으로 공의 위치를 업데이트 시키고,
초기 설정에 있던 캔버스의 경계를 벗어나는 경우 방향을 반전시켜 공이 화면 밖으로 나가지 않도록 설정했다.
collisionDetect메서드는 충돌감지 메서드로서 타 공과의 충돌을 감지하고
만약 공끼리 충돌이 생긴 경우에는 color를 변경한다.
공 배열 생성
공이 한개로만 이루어지지 않았기 때문에 여러개의 공을 생성하고 공들을 배열에 저장했다.
공 애니메이션
공을 매 프레임 업데이트하기 위한 애니메이션이다.
최종 코드는 아래와 같이 작성했다.
// 기본 설정
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 무작위 색상 생성 함수
function generateRandomColor() {
return `rgb(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)})`;
}
// 무작위 숫자 생성 함수
function generateRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 공 객체 생성 함수
function createBall() {
return {
x: generateRandomNumber(0, canvas.width),
y: generateRandomNumber(0, canvas.height),
dx: generateRandomNumber(-5, 5),
dy: generateRandomNumber(-5, 5),
size: generateRandomNumber(10, 20),
color: generateRandomColor(),
// 공을 그리는 함수
draw: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fillStyle = this.color;
ctx.fill();
},
// 공의 위치를 업데이트하는 함수
update: function() {
if (this.x + this.size > canvas.width || this.x - this.size < 0) {
this.dx = -this.dx;
}
if (this.y + this.size > canvas.height || this.y - this.size < 0) {
this.dy = -this.dy;
}
this.x += this.dx;
this.y += this.dy;
},
// 공이 다른 공과 충돌하는지 확인하는 함수
checkCollision: function(balls) {
balls.forEach(otherBall => {
if (this !== otherBall) {
const dx = this.x - otherBall.x;
const dy = this.y - otherBall.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.size + otherBall.size) {
this.color = generateRandomColor();
otherBall.color = generateRandomColor();
}
}
});
}
};
}
// 공들을 저장할 배열
const balls = [];
for (let i = 0; i < 25; i++) {
balls.push(createBall());
}
// 애니메이션 루프 함수
function animate() {
ctx.fillStyle = "rgba(0, 0, 0, 0.25)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
balls.forEach(ball => {
ball.draw();
ball.update();
ball.checkCollision(balls);
});
requestAnimationFrame(animate);
}
// 애니메이션 시작
animate();
공 튀기기에 데모기능 추가하기
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features
조금 더 업그레이드 시켜보자!
1.Shpe 클래스를 생성 EvilCircle 클래스 정의 해서 Ball을 상속받는다.
Ball 클래스와 유사하게 Shape 클래스를 정의했다.
Shape는 공통 속성(x, y, velX, velY, color, size)과 메서드(draw, update, collisionDetect)를 갖지만,
실제로 그려지지 않거나 동작하지 않는 기본 클래스로 사용하기 위함!
2.EvilCircle 클래스 정의하여 Shape 클래스를 상속받아서 사용자가 제어가 가능한 원을 만든다.
방향키를 사용하여 움직일 수 있도록 설정해본다.
(이건 코드가 길어서 캡쳐본 대신.. 코드로)
class EvilCircle extends Shape {
constructor(x, y) {
super(x, y, 20, 20, 'white', 10);
window.addEventListener('keydown', (e) => {
switch (e.key) {
case 'a':
this.x -= this.velX;
break;
case 'd':
this.x += this.velX;
break;
case 'w':
this.y -= this.velY;
break;
case 's':
this.y += this.velY;
break;
}
});
}
draw() {
ctx.beginPath();
ctx.strokeStyle = this.color;
ctx.lineWidth = 3;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.stroke();
}
update() {
if (this.x + this.size > width) {
this.x = width - this.size;
}
if (this.x - this.size < 0) {
this.x = this.size;
}
if (this.y + this.size > height) {
this.y = height - this.size;
}
if (this.y - this.size < 0) {
this.y = this.size;
}
}
collisionDetect() {
for (const ball of balls) {
if (ball.exists) {
const dx = this.x - ball.x;
const dy = this.y - ball.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.size + ball.size) {
ball.exists = false; // 공을 없애기
}
}
}
}
}
이후 html 에 점수 카운터를 표시할 p요소를 하나 넣어주고,
js에 점수 카운터 업데이트를 하는 코드도 하나 만들어 넣어줬다.
function updateScore() {
const score = balls.filter(ball => ball.exists).length;
document.getElementById('score').textContent = `Ball count: ${score}`;
}
function loop() {
ctx.fillStyle = "rgba(0, 0, 0, 0.25)";
ctx.fillRect(0, 0, width, height);
for (const ball of balls) {
if (ball.exists) {
ball.draw();
ball.update();
ball.collisionDetect();
}
}
evilCircle.draw();
evilCircle.update();
evilCircle.collisionDetect();
updateScore(); // 점수 업데이트
requestAnimationFrame(loop);
}
loop(); // 애니메이션 루프 시작
ㅎ0ㅎ...... html만 나오고 왜 내가 컨트롤 할 수 있는 공은 나오지 않는가,
첫 술에 배부를 순 없으니 구현 실패한 데모기능 추가는 성공해서 다음에 다시 돌아 올 예정...
'🪄Interview > ✏️Study' 카테고리의 다른 글
[JavaScript Study] 2주차 - 이미지 갤러리(gallery-start) (0) | 2024.08.31 |
---|---|
[JavaScript Study] 1주차 - 구구단 구현하기1 (0) | 2024.08.17 |
[CS STUDY INTERVIEW] 16주차 - 옵저버 패턴 & 스트레티지 패턴 & 컴포지트 패턴 (0) | 2024.07.16 |
[CS STUDY INTERVIEW] 15주차 - 싱글톤 패턴 (0) | 2024.07.06 |
[CS STUDY INTERVIEW] 14주차 - 팩토리 메서드 패턴 (0) | 2024.06.20 |