Explanation
얼마 전에 Canvas를 이용해서 간단한 게임을 만들어 봤는데요, 그 내용을 모두 적기엔 글이 너무 길어질 것 같아서 간단하게 제가 생각해본 구조?? 에 대해 정리해보려 합니다.
대략 Webpack, Babel, React, Redux, Canvas를 사용하고요, 크게 React로 컴포넌트를 나누어 구성하고 Redux로 현재 게임의 상태를 저장하고 Canvas로 화면을 그립니다. Babel로 ES6+ 문법을 사용하고 Webpack은 이 모든 구성을 쉽게 모아서 사용할 수 있고 hot-loader로 일일이 새로고침을 할 필요가 없어서 편해요. 그리고 polyfill을 설치하면 Async/Await도 사용할 수 있습니다.
예제 소스를 설치하면 대략적으로 시작할 수 있는 밑바탕 정도로 사용할 수 있을 거 같아요.
예제 : https://github.com/falsy/blog-post-example/tree/master/react-redux-canvas
간략하게 코드에 대해 이야기해보면,
// src/views/dashboard.js
...
render() {
return (
<div>
<canvas id={'sample'} width={'500'} height={'500'}></canvas>
<p onClick={this.startAnimation.bind(this)}>애니메이션</p>
</div>
);
}
}
const mstp = (state) => {
return {
canvas: state.canvas
};
};
export default connect(mstp)(Dashboard)
우선 id값으로 sample을 가지고 있는 canvas를 추가했고요,
// src/views/dashboard.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { setCanvas } from '../actions/canvas';
import { printMarble, animationMarble } from '../actions/marble';
class Dashboard extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
const { dispatch } = this.props;
const canvas = document.getElementById('sample');
dispatch(setCanvas(canvas));
printMarble(canvas);
}
...
canvas가 랜더링되고 나면, 나중에 컴포넌트가 많아져도 Redux로 해당 canvas에 그림을 제어하기 위해서 Redux에 canvas를 기억해 두었습니다. 그리고 초기 그림?을 'printMarble' 라는 함수를 통해 canvas에 그립니다.
// src/actions/marble.js
export function printMarble(canvas) {
const ctx = canvas.getContext('2d');
const x = 100;
const y = 240;
const r = 10;
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI * 2, true);
ctx.fillStyle = 'blue';
ctx.fill();
}
...
파라미터로 canvas 엘리먼트를 받아오고 반지름 10px의 파란색 원을 x축 100px, y축 240px에 그립니다.
// src/views/dashboard
...
startAnimation() {
animationMarble(this.props.canvas.element);
}
render() {
return (
<div>
<canvas id={'sample'} width={'500'} height={'500'}></canvas>
<p onClick={this.startAnimation.bind(this)}>애니메이션</p>
</div>
);
}
}
그리고 '애니메이션'이라는 텍스트를 클릭하면 animationMarble 라는 함수를, 그리고 redux에 기억해 놓은 canvas를 파라미터로 실행합니다.
// src/actions/marble.js
...
export function animationMarble(canvas) {
const ctx = canvas.getContext('2d');
const x = 100;
const y = 240;
const r = 10;
let moveSize = 0;
const animate = setInterval(() => {
ctx.clearRect(x - r + moveSize, y - r, 20, 20);
moveSize += 5;
const moveX = x + moveSize;
ctx.beginPath();
ctx.arc(moveX, y, r, 0, Math.PI * 2, true);
ctx.fillStyle = 'blue';
ctx.fill();
if(moveX >= 400) {
clearInterval(animate);
ctx.clearRect(x - r + moveSize, y - r, 20, 20);
}
}, 10);
}
animationMarble 함수는 실행되면 setInterval 메서드로 함수를 반복 실행시켜 애니메이션을 구현합니다. .clearRect()로 이전 위치에 파란 원을 지우고 X축으로 += 5; 씩 추가된 X값으로 파란 원을 새로 그립니다. 그리고 X축으로 400px이상으로 이동하게되면 반복을 멈추고 파란 원을 지우는 것으로 애니메이션이 끝납니다.
그리고 끝으로 제가 간단하게 만들어본 게임은 아래의 링크를 통해서 확인해 볼 수 있습니다.
http://game.tenqube.kr/
제가 Canvas를 제대로 사용해 본 적이 없어서 캔버스를 사용했는데요, 위와 같은 게임은 그냥 canvas를 사용하지 않고 html, javascript로 만드는 게 더 좋을 거 같아요ㅎ



